原来只是以左上对齐点,宽高各偏移描边的厚度大小。但是这样会出现在一些字体与背景阴影字对不齐的情况。
上面第一行:能、好、连、败,显示是不对的。下面一行是修正后的。
unsigned char* FontFreeType::getGlyphBitmap(unsigned short theChar, long &outWidth, long &outHeight, Rect &outRect,int &xAdvance)
{
bool invalidChar = true;
unsigned char * ret = nullptr;
do
{
if (!_fontRef)
break;
auto glyphIndex = FT_Get_Char_Index(_fontRef, theChar);
if(!glyphIndex)
break;
if (_distanceFieldEnabled)
{
if (FT_Load_Glyph(_fontRef,glyphIndex,FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT))
break;
}
else
{
if (FT_Load_Glyph(_fontRef,glyphIndex,FT_LOAD_RENDER))
break;
}
outRect.origin.x = _fontRef->glyph->metrics.horiBearingX >> 6;
outRect.origin.y = - (_fontRef->glyph->metrics.horiBearingY >> 6);
outRect.size.width = (_fontRef->glyph->metrics.width >> 6);
outRect.size.height = (_fontRef->glyph->metrics.height >> 6);
xAdvance = (static_cast<int>(_fontRef->glyph->metrics.horiAdvance >> 6));
outWidth = _fontRef->glyph->bitmap.width;
outHeight = _fontRef->glyph->bitmap.rows;
ret = _fontRef->glyph->bitmap.buffer;
if (_outlineSize > 0)
{
auto copyBitmap = new unsigned char[outWidth * outHeight];
memcpy(copyBitmap,ret,outWidth * outHeight * sizeof(unsigned char));
long bitmapWidth;
long bitmapHeight;
FT_BBox bbox;
auto outlineBitmap = getGlyphBitmapWithOutline(theChar,bbox);
if(outlineBitmap == nullptr)
{
ret = nullptr;
delete [] copyBitmap;
break;
}
bitmapWidth = (bbox.xMax - bbox.xMin)>>6;
bitmapHeight = (bbox.yMax - bbox.yMin)>>6;
//modify 纠正描边时字体与阴影没有对齐问题
int offsetWidth = 0; //X方向偏移
int offsetHeight = 0; //Y方向偏移
if(outRect.origin.x -(bbox.xMin >> 6) != _outlineSize)
offsetWidth = outRect.origin.x -(bbox.xMin >> 6) - _outlineSize;
if((bbox.yMax >> 6) + outRect.origin.y != _outlineSize)
offsetHeight = (bbox.yMax >> 6) + outRect.origin.y - _outlineSize;
long index;
auto blendImage = new unsigned char[bitmapWidth * bitmapHeight * 2];
memset(blendImage, 0, bitmapWidth * bitmapHeight * 2);
for (int x = 0; x < bitmapWidth; ++x)
{
for (int y = 0; y < bitmapHeight; ++y)
{
index = x + ( y * bitmapWidth );
blendImage[2 * index] = outlineBitmap[index];
}
}
long maxX = outWidth + _outlineSize;
long maxY = outHeight + _outlineSize;
for (int x = _outlineSize + offsetWidth; x < maxX + offsetWidth; ++x)
{
for (int y = _outlineSize + offsetHeight; y < maxY + offsetHeight; ++y)
{
index = x + ( y * bitmapWidth );
blendImage[2 * index + 1] = copyBitmap[outWidth * (y - _outlineSize - offsetHeight) + x - _outlineSize - offsetWidth];
}
}
outRect.origin.x = bbox.xMin >> 6;
outRect.origin.y = - (bbox.yMax >> 6);
xAdvance += bitmapWidth - outRect.size.width;
outRect.size.width = bitmapWidth;
outRect.size.height = bitmapHeight;
outWidth = bitmapWidth;
outHeight = bitmapHeight;
delete [] outlineBitmap;
delete [] copyBitmap;
ret = blendImage;
}
invalidChar = false;
} while (0);
if (invalidChar)
{
outRect.size.width = 0;
outRect.size.height = 0;
xAdvance = 0;
return nullptr;
}
else
{
return ret;
}
}