2022-06-13 11:56:43 +00:00
|
|
|
#include "CvxText.hpp"
|
|
|
|
#include "../base/HGDef.h"
|
|
|
|
#include "../base/HGInc.h"
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
CvxText::CvxText()
|
|
|
|
{
|
|
|
|
m_library = NULL;
|
|
|
|
m_face = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
CvxText::~CvxText()
|
|
|
|
{
|
|
|
|
Destroy();
|
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
HGResult CvxText::Create(const HGChar* fontPath)
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
|
|
|
if (NULL != m_face)
|
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
return HGBASE_ERR_FAIL;
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FT_Init_FreeType(&m_library);
|
|
|
|
if (NULL == m_library)
|
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
return HGBASE_ERR_FAIL;
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FT_New_Face(m_library, fontPath, 0, &m_face);
|
|
|
|
if (NULL == m_face)
|
|
|
|
{
|
|
|
|
FT_Done_FreeType(m_library);
|
|
|
|
m_library = NULL;
|
2022-06-14 09:06:19 +00:00
|
|
|
return HGBASE_ERR_FAIL;
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
return HGBASE_ERR_OK;
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
HGResult CvxText::Destroy()
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
|
|
|
if (NULL == m_face)
|
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
return HGBASE_ERR_FAIL;
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FT_Done_Face(m_face);
|
|
|
|
m_face = NULL;
|
|
|
|
FT_Done_FreeType(m_library);
|
|
|
|
m_library = NULL;
|
2022-06-14 09:06:19 +00:00
|
|
|
return HGBASE_ERR_OK;
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(HG_CMP_MSC)
|
|
|
|
static WCHAR *GetUnicodeStr(const char *text)
|
|
|
|
{
|
|
|
|
int len = ::MultiByteToWideChar(CP_ACP, 0, text, -1, NULL, 0);
|
|
|
|
WCHAR *pUnicode = new WCHAR [len];
|
|
|
|
::MultiByteToWideChar(CP_ACP, 0, text, -1, pUnicode, len);
|
|
|
|
return pUnicode;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static uint16_t *GetUnicodeStr(const char *text)
|
|
|
|
{
|
|
|
|
if (0 == *text)
|
|
|
|
{
|
|
|
|
uint16_t *pUnicode = new uint16_t [1];
|
|
|
|
*pUnicode = 0;
|
|
|
|
return pUnicode;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t *pUnicode = new uint16_t [strlen(text) + 2];
|
|
|
|
memset(pUnicode, 0, sizeof(uint16_t) * (strlen(text) + 2));
|
|
|
|
|
|
|
|
iconv_t cd = iconv_open("UNICODE//IGNORE", "UTF-8");
|
|
|
|
if ((iconv_t)-1 != cd)
|
|
|
|
{
|
|
|
|
char *inbuf = (char *)text;
|
|
|
|
size_t inbytes = strlen(text);
|
|
|
|
char *outbuf = (char *)pUnicode;
|
|
|
|
size_t outsize = sizeof(uint16_t) * (strlen(text) + 1);
|
|
|
|
|
|
|
|
iconv(cd, &inbuf, &inbytes, &outbuf, &outsize);
|
|
|
|
iconv_close(cd);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pUnicode;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
HGResult CvxText::DrawString(HGImage image, const HGChar* text, HGColor color, HGUInt posType, HGInt locationX, HGInt locationY,
|
|
|
|
HGUInt fontSize, HGBool bold, HGBool underline, HGBool italic, HGBool strikeout)
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
if (NULL == m_face)
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
return HGBASE_ERR_FAIL;
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
assert(NULL != image);
|
|
|
|
assert(NULL != text && '\0' != *text);
|
|
|
|
assert(posType >= HGIMGPROC_WMPOSTYPE_LEFT && posType <= HGIMGPROC_WMPOSTYPE_LOCATION);
|
|
|
|
assert(0 != fontSize);
|
|
|
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
|
|
if (HGBASE_IMGTYPE_BINARY == imgInfo.type)
|
|
|
|
{
|
|
|
|
HGImage imageTmp = NULL;
|
|
|
|
HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_GRAY, 0, &imageTmp);
|
|
|
|
if (HGBASE_ERR_OK == ret)
|
|
|
|
{
|
|
|
|
ret = DrawString(imageTmp, text, color, posType, locationX, locationY, fontSize, bold, underline, italic, strikeout);
|
|
|
|
HGBase_DestroyImage(imageTmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGUInt width, height;
|
|
|
|
std::vector<HGRect> vPos;
|
|
|
|
GetStringLocation(text, fontSize, bold, underline, italic, strikeout, width, height, vPos);
|
|
|
|
|
|
|
|
if (HGIMGPROC_WMPOSTYPE_LOCATION == posType)
|
|
|
|
{
|
2022-06-13 11:56:43 +00:00
|
|
|
#if defined(HG_CMP_MSC)
|
2022-06-14 09:06:19 +00:00
|
|
|
WCHAR* pUnicode = GetUnicodeStr(text);
|
2022-06-13 11:56:43 +00:00
|
|
|
#else
|
2022-06-14 09:06:19 +00:00
|
|
|
uint16_t* pUnicode = GetUnicodeStr(text);
|
|
|
|
uint16_t* pUnicodeEx = pUnicode + 1;
|
2022-06-13 11:56:43 +00:00
|
|
|
#endif
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
int i = 0;
|
2022-06-13 11:56:43 +00:00
|
|
|
#if defined(HG_CMP_MSC)
|
2022-06-14 09:06:19 +00:00
|
|
|
while ('\0' != pUnicode[i])
|
2022-06-13 11:56:43 +00:00
|
|
|
#else
|
2022-06-14 09:06:19 +00:00
|
|
|
while ('\0' != pUnicodeEx[i])
|
2022-06-13 11:56:43 +00:00
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#if defined(HG_CMP_MSC)
|
2022-06-14 09:06:19 +00:00
|
|
|
DrawChar(image, pUnicode[i], locationX + vPos[i].left, locationY + vPos[i].top, color, fontSize, bold, italic);
|
2022-06-13 11:56:43 +00:00
|
|
|
#else
|
2022-06-14 09:06:19 +00:00
|
|
|
DrawChar(image, pUnicodeEx[i], locationX + vPos[i].left, locationY + vPos[i].top, color, fontSize, bold, italic);
|
2022-06-13 11:56:43 +00:00
|
|
|
#endif
|
2022-06-14 09:06:19 +00:00
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] pUnicode;
|
|
|
|
|
|
|
|
if (underline)
|
|
|
|
{
|
|
|
|
HGImgProc_ImageDrawLine(image, locationX, locationY + height - 1, locationX + width, locationY + height - 1, 1, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strikeout)
|
|
|
|
{
|
|
|
|
if (underline)
|
|
|
|
HGImgProc_ImageDrawLine(image, locationX, locationY + (height - 1) / 2,
|
|
|
|
locationX + width, locationY + (height - 1) / 2, 1, color);
|
|
|
|
else
|
|
|
|
HGImgProc_ImageDrawLine(image, locationX, locationY + height / 2,
|
|
|
|
locationX + width, locationY + height / 2, 1, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HGImageRoi imgRoi;
|
|
|
|
HGBase_GetImageROI(image, &imgRoi);
|
|
|
|
HGInt roiWidth = imgRoi.right - imgRoi.left;
|
|
|
|
HGInt roiHeight = imgRoi.bottom - imgRoi.top;
|
|
|
|
|
|
|
|
HGInt x, y;
|
|
|
|
if (HGIMGPROC_WMPOSTYPE_LEFT == posType)
|
|
|
|
{
|
|
|
|
x = 0;
|
|
|
|
y = (roiHeight - height) / 2;
|
|
|
|
}
|
|
|
|
else if (HGIMGPROC_WMPOSTYPE_TOP == posType)
|
|
|
|
{
|
|
|
|
x = (roiWidth - width) / 2;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
else if (HGIMGPROC_WMPOSTYPE_RIGHT == posType)
|
|
|
|
{
|
|
|
|
x = roiWidth - width;
|
|
|
|
y = (roiHeight - height) / 2;
|
|
|
|
}
|
|
|
|
else if (HGIMGPROC_WMPOSTYPE_BOTTOM == posType)
|
|
|
|
{
|
|
|
|
x = (roiWidth - width) / 2;
|
|
|
|
y = roiHeight - height;
|
|
|
|
}
|
|
|
|
else if (HGIMGPROC_WMPOSTYPE_LEFTTOP == posType)
|
|
|
|
{
|
|
|
|
x = 0;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
else if (HGIMGPROC_WMPOSTYPE_RIGHTTOP == posType)
|
|
|
|
{
|
|
|
|
x = roiWidth - width;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
else if (HGIMGPROC_WMPOSTYPE_LEFTBOTTOM == posType)
|
|
|
|
{
|
|
|
|
x = 0;
|
|
|
|
y = roiHeight - height;
|
|
|
|
}
|
|
|
|
else if (HGIMGPROC_WMPOSTYPE_RIGHTBOTTOM == posType)
|
|
|
|
{
|
|
|
|
x = roiWidth - width;
|
|
|
|
y = roiHeight - height;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x = (roiWidth - width) / 2;
|
|
|
|
y = (roiHeight - height) / 2;
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
return DrawString(image, text, color, HGIMGPROC_WMPOSTYPE_LOCATION, x, y, fontSize, bold, underline, italic, strikeout);
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
void CvxText::MeasureChar(HGUInt wc, HGUInt fontSize, HGBool bold, HGBool italic, FT_BBox& acbox)
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
assert(NULL != m_face);
|
|
|
|
assert(0 != fontSize);
|
|
|
|
|
|
|
|
FT_Set_Pixel_Sizes(m_face, fontSize, fontSize);
|
|
|
|
FT_UInt glyph_index = FT_Get_Char_Index(m_face, wc);
|
|
|
|
FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);
|
|
|
|
|
|
|
|
if (bold)
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
if (m_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
|
|
|
{
|
|
|
|
FT_Outline_Embolden(&m_face->glyph->outline, fontSize * 2);
|
|
|
|
}
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
if (italic)
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
if (m_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
FT_Matrix matrix;
|
|
|
|
matrix.xx = 0x10000L;
|
|
|
|
matrix.xy = 0.5f * 0x10000L;
|
|
|
|
matrix.yx = 0;
|
|
|
|
matrix.yy = 0x10000L;
|
|
|
|
FT_Outline_Transform(&m_face->glyph->outline, &matrix);
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
2022-06-14 09:06:19 +00:00
|
|
|
}
|
2022-06-13 11:56:43 +00:00
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
if (m_face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
|
|
|
|
{
|
|
|
|
FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_NORMAL);
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
FT_Glyph glyph;
|
|
|
|
FT_Get_Glyph(m_face->glyph, &glyph);
|
|
|
|
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &acbox);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CvxText::GetStringLocation(const HGChar* text, HGUInt fontSize, HGBool bold, HGBool underline, HGBool italic, HGBool strikeout,
|
|
|
|
HGUInt& width, HGUInt& height, std::vector<HGRect> &vPos)
|
|
|
|
{
|
|
|
|
assert(NULL != text && '\0' != *text);
|
|
|
|
assert(0 != fontSize);
|
|
|
|
|
|
|
|
width = 0;
|
|
|
|
height = 0;
|
|
|
|
vPos.clear();
|
|
|
|
|
2022-06-13 11:56:43 +00:00
|
|
|
#if defined(HG_CMP_MSC)
|
2022-06-14 09:06:19 +00:00
|
|
|
WCHAR* pUnicode = GetUnicodeStr(text);
|
2022-06-13 11:56:43 +00:00
|
|
|
#else
|
2022-06-14 09:06:19 +00:00
|
|
|
uint16_t* pUnicode = GetUnicodeStr(text);
|
|
|
|
uint16_t* pUnicodeEx = pUnicode + 1;
|
2022-06-13 11:56:43 +00:00
|
|
|
#endif
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
HGInt origin = 0;
|
2022-06-14 10:43:40 +00:00
|
|
|
HGInt minY = INT_MAX, maxY = INT_MIN;
|
2022-06-13 11:56:43 +00:00
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
#if defined(HG_CMP_MSC)
|
|
|
|
while ('\0' != pUnicode[i])
|
|
|
|
#else
|
2022-06-14 09:06:19 +00:00
|
|
|
while ('\0' != pUnicodeEx[i])
|
2022-06-13 11:56:43 +00:00
|
|
|
#endif
|
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
FT_BBox acbox;
|
|
|
|
#if defined(HG_CMP_MSC)
|
|
|
|
MeasureChar(pUnicode[i], fontSize, bold, italic, acbox);
|
|
|
|
#else
|
|
|
|
MeasureChar(pUnicodeEx[i], fontSize, bold, italic, acbox);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
HGRect pos;
|
|
|
|
pos.left = origin + acbox.xMin;
|
|
|
|
pos.right = origin + acbox.xMax;
|
|
|
|
pos.top = -acbox.yMax;
|
|
|
|
pos.bottom = -acbox.yMin;
|
|
|
|
vPos.push_back(pos);
|
2022-06-13 11:56:43 +00:00
|
|
|
|
|
|
|
#if defined(HG_CMP_MSC)
|
2022-06-14 09:06:19 +00:00
|
|
|
if (pUnicode[i] < 255 && (!isprint((int)pUnicode[i]) || isspace((int)pUnicode[i])))
|
2022-06-13 11:56:43 +00:00
|
|
|
#else
|
2022-06-14 09:06:19 +00:00
|
|
|
if (pUnicodeEx[i] < 255 && (!isprint((int)pUnicodeEx[i]) || isspace((int)pUnicodeEx[i])))
|
2022-06-13 11:56:43 +00:00
|
|
|
#endif
|
2022-06-14 09:06:19 +00:00
|
|
|
{
|
|
|
|
origin += fontSize / 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
origin += (acbox.xMax + acbox.xMin);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (acbox.yMin < minY)
|
|
|
|
minY = acbox.yMin;
|
|
|
|
if (acbox.yMax > maxY)
|
|
|
|
maxY = acbox.yMax;
|
|
|
|
|
2022-06-13 11:56:43 +00:00
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
delete[] pUnicode;
|
2022-06-13 11:56:43 +00:00
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
width = origin;
|
|
|
|
height = (maxY - minY);
|
|
|
|
if (underline)
|
|
|
|
++height;
|
2022-06-13 11:56:43 +00:00
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
for (int i = 0; i < (int)vPos.size(); ++i)
|
|
|
|
{
|
|
|
|
vPos[i].top += maxY;
|
|
|
|
vPos[i].bottom += maxY;
|
|
|
|
}
|
2022-06-13 11:56:43 +00:00
|
|
|
}
|
|
|
|
|
2022-06-14 09:06:19 +00:00
|
|
|
void CvxText::DrawChar(HGImage image, HGUInt wc, HGInt x, HGInt y, HGColor color, HGUInt fontSize, HGBool bold, HGBool italic)
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
2022-06-14 09:06:19 +00:00
|
|
|
assert(NULL != m_face);
|
|
|
|
|
|
|
|
FT_Set_Pixel_Sizes(m_face, fontSize, fontSize);
|
2022-06-13 11:56:43 +00:00
|
|
|
FT_UInt glyph_index = FT_Get_Char_Index(m_face, wc);
|
|
|
|
FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);
|
2022-06-14 09:06:19 +00:00
|
|
|
|
|
|
|
if (bold)
|
|
|
|
{
|
|
|
|
if (m_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
|
|
|
{
|
|
|
|
FT_Outline_Embolden(&m_face->glyph->outline, fontSize * 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (italic)
|
|
|
|
{
|
|
|
|
if (m_face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
|
|
|
|
{
|
|
|
|
FT_Matrix matrix;
|
|
|
|
matrix.xx = 0x10000L;
|
|
|
|
matrix.xy = 0.5f * 0x10000L;
|
|
|
|
matrix.yx = 0;
|
|
|
|
matrix.yy = 0x10000L;
|
|
|
|
FT_Outline_Transform(&m_face->glyph->outline, &matrix);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
|
|
|
|
{
|
|
|
|
FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_NORMAL);
|
|
|
|
}
|
2022-06-13 11:56:43 +00:00
|
|
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
|
|
uint32_t imgWidth = imgInfo.width;
|
|
|
|
uint32_t imgHeight = imgInfo.height;
|
|
|
|
uint32_t imgWidthStep = imgInfo.widthStep;
|
|
|
|
uint32_t imgType = imgInfo.type;
|
|
|
|
|
|
|
|
uint8_t *imgData;
|
|
|
|
HGBase_GetImageData(image, &imgData);
|
|
|
|
|
|
|
|
int32_t imgChannel = 0;
|
|
|
|
if (HGBASE_IMGTYPE_GRAY == imgType)
|
|
|
|
imgChannel = 1;
|
|
|
|
else if (HGBASE_IMGTYPE_RGB == imgType || HGBASE_IMGTYPE_BGR == imgType)
|
|
|
|
imgChannel = 3;
|
|
|
|
else if (HGBASE_IMGTYPE_RGBA == imgType || HGBASE_IMGTYPE_BGRA == imgType)
|
|
|
|
imgChannel = 4;
|
|
|
|
assert(0 != imgChannel);
|
|
|
|
|
|
|
|
HGImageRoi imgRoi;
|
|
|
|
HGBase_GetImageROI(image, &imgRoi);
|
|
|
|
uint32_t imgLeft = imgRoi.left;
|
|
|
|
uint32_t imgTop = imgRoi.top;
|
|
|
|
uint32_t imgRight = imgRoi.right;
|
|
|
|
uint32_t imgBottom = imgRoi.bottom;
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < m_face->glyph->bitmap.rows; ++i)
|
|
|
|
{
|
|
|
|
for (unsigned int j = 0; j < m_face->glyph->bitmap.width; ++j)
|
|
|
|
{
|
|
|
|
int32_t xOffset = (int32_t)imgLeft + x + (int32_t)j;
|
|
|
|
int32_t yOffset = (int32_t)imgTop + y + (int32_t)i;
|
|
|
|
|
2022-06-14 10:43:40 +00:00
|
|
|
if (xOffset >= (int32_t)imgLeft && xOffset < (int32_t)imgRight
|
2022-06-14 09:06:19 +00:00
|
|
|
&& yOffset >= (int32_t)imgTop && yOffset < (int32_t)imgBottom)
|
2022-06-13 11:56:43 +00:00
|
|
|
{
|
|
|
|
uint8_t *p = m_face->glyph->bitmap.buffer + m_face->glyph->bitmap.pitch * i + j;
|
|
|
|
int32_t opacity = HG_GETCOLOR_A(color) * (*p) / 255;
|
|
|
|
|
|
|
|
uint8_t *pEx = imgData + yOffset * imgWidthStep + xOffset * imgChannel;
|
|
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
|
|
pEx = imgData + (imgHeight - yOffset - 1) * imgWidthStep + xOffset * imgChannel;
|
|
|
|
|
|
|
|
if (HGBASE_IMGTYPE_RGB == imgType || HGBASE_IMGTYPE_RGBA == imgType)
|
|
|
|
{
|
|
|
|
int32_t v0 = HG_GETCOLOR_R(color);
|
|
|
|
int32_t vDest0 = pEx[0];
|
|
|
|
int32_t value0 = (v0 - vDest0) * opacity;
|
|
|
|
pEx[0] = (uint8_t)(vDest0 + (((value0 << 8) + value0) >> 16));
|
|
|
|
|
|
|
|
int32_t v1 = HG_GETCOLOR_G(color);
|
|
|
|
int32_t vDest1 = pEx[1];
|
|
|
|
int32_t value1 = (v1 - vDest1) * opacity;
|
|
|
|
pEx[1] = (uint8_t)(vDest1 + (((value1 << 8) + value1) >> 16));
|
|
|
|
|
|
|
|
int32_t v2 = HG_GETCOLOR_B(color);
|
|
|
|
int32_t vDest2 = pEx[2];
|
|
|
|
int32_t value2 = (v2 - vDest2) * opacity;
|
|
|
|
pEx[2] = (uint8_t)(vDest2 + (((value2 << 8) + value2) >> 16));
|
|
|
|
}
|
|
|
|
else if (HGBASE_IMGTYPE_BGR == imgType || HGBASE_IMGTYPE_BGRA == imgType)
|
|
|
|
{
|
|
|
|
int32_t v0 = HG_GETCOLOR_B(color);
|
|
|
|
int32_t vDest0 = pEx[0];
|
|
|
|
int32_t value0 = (v0 - vDest0) * opacity;
|
|
|
|
pEx[0] = (uint8_t)(vDest0 + (((value0 << 8) + value0) >> 16));
|
|
|
|
|
|
|
|
int32_t v1 = HG_GETCOLOR_G(color);
|
|
|
|
int32_t vDest1 = pEx[1];
|
|
|
|
int32_t value1 = (v1 - vDest1) * opacity;
|
|
|
|
pEx[1] = (uint8_t)(vDest1 + (((value1 << 8) + value1) >> 16));
|
|
|
|
|
|
|
|
int32_t v2 = HG_GETCOLOR_R(color);
|
|
|
|
int32_t vDest2 = pEx[2];
|
|
|
|
int32_t value2 = (v2 - vDest2) * opacity;
|
|
|
|
pEx[2] = (uint8_t)(vDest2 + (((value2 << 8) + value2) >> 16));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int32_t v = (HG_GETCOLOR_R(color) * 76 + HG_GETCOLOR_G(color) * 150 + HG_GETCOLOR_B(color) * 30) >> 8;
|
|
|
|
int32_t vDest = *pEx;
|
|
|
|
int32_t value = (v - vDest) * opacity;
|
|
|
|
*pEx = (uint8_t)(vDest + (((value << 8) + value) >> 16));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|