code_app/modules/imgproc/CvxText.cpp

313 lines
7.9 KiB
C++

#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();
}
bool CvxText::Create(const HGChar* fontPath)
{
if (NULL != m_face)
{
return false;
}
FT_Init_FreeType(&m_library);
if (NULL == m_library)
{
return false;
}
FT_New_Face(m_library, fontPath, 0, &m_face);
if (NULL == m_face)
{
FT_Done_FreeType(m_library);
m_library = NULL;
return false;
}
return true;
}
bool CvxText::Destroy()
{
if (NULL == m_face)
{
return false;
}
FT_Done_Face(m_face);
m_face = NULL;
FT_Done_FreeType(m_library);
m_library = NULL;
return true;
}
#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
bool CvxText::MeasureString(const HGChar* text, HGInt x, HGInt y, HGUInt size,
HGBool bold, HGBool underline, HGBool italic, HGBool strikeout, HGRect* pos)
{
if (NULL == m_face || NULL == text || NULL == pos)
{
return false;
}
#if defined(HG_CMP_MSC)
WCHAR *pUnicode = GetUnicodeStr(text);
#else
uint16_t *pUnicode = GetUnicodeStr(text);
uint16_t *pUnicodeEx = pUnicode + 1;
#endif
pos->left = x;
pos->top = y;
pos->right = x;
pos->bottom = y;
int i = 0;
#if defined(HG_CMP_MSC)
while ('\0' != pUnicode[i])
#else
while ('\0' != pUnicodeEx[i])
#endif
{
if (0 != i)
{
pos->right += (size / 10);
}
uint32_t width, height;
#if defined(HG_CMP_MSC)
MeasureChar(pUnicode[i], size, bold, underline, italic, strikeout, width, height);
#else
MeasureChar(pUnicodeEx[i], size, bold, underline, italic, strikeout, width, height);
#endif
pos->right += width;
if (y + (int32_t)height > pos->bottom)
pos->bottom = y + (int32_t)height;
++i;
}
delete [] pUnicode;
return true;
}
bool CvxText::DrawString(HGImage image, const HGChar* text, HGInt x, HGInt y, HGColor color, HGUInt size,
HGBool bold, HGBool underline, HGBool italic, HGBool strikeout)
{
if (NULL == m_face || NULL == image || NULL == text)
{
return false;
}
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, x, y, color, size, bold, underline, italic, strikeout);
if (HGBASE_ERR_OK == ret)
{
ret = HGBase_CopyImage(imageTmp, image);
}
HGBase_DestroyImage(imageTmp);
}
return ret;
}
#if defined(HG_CMP_MSC)
WCHAR *pUnicode = GetUnicodeStr(text);
#else
uint16_t *pUnicode = GetUnicodeStr(text);
uint16_t *pUnicodeEx = pUnicode + 1;
#endif
int x2 = x;
int y2 = y;
int i = 0;
#if defined(HG_CMP_MSC)
while ('\0' != pUnicode[i])
#else
while ('\0' != pUnicodeEx[i])
#endif
{
if (0 != i)
{
x2 += (size / 10);
}
uint32_t width, height;
#if defined(HG_CMP_MSC)
DrawChar(image, pUnicode[i], x2, y2, color, size, bold, underline, italic, strikeout, width, height);
#else
DrawChar(image, pUnicodeEx[i], x2, y2, color, size, bold, underline, italic, strikeout, width, height);
#endif
x2 += width;
++i;
}
delete [] pUnicode;
return true;
}
void CvxText::MeasureChar(HGUInt wc, HGUInt size, HGBool bold, HGBool underline, HGBool italic, HGBool strikeout,
HGUInt& width, HGUInt& height)
{
FT_Set_Pixel_Sizes(m_face, size, size);
FT_UInt glyph_index = FT_Get_Char_Index(m_face, wc);
FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);
width = (0 == m_face->glyph->bitmap.width) ? size / 2 : m_face->glyph->bitmap.width;
height = (0 == m_face->glyph->bitmap.rows) ? size : m_face->glyph->bitmap.rows;
}
void CvxText::DrawChar(HGImage image, HGUInt wc, HGInt x, HGInt y, HGColor color,
HGUInt size, HGBool bold, HGBool italic, HGBool angle, HGBool underline, HGUInt& width, HGUInt& height)
{
FT_Set_Pixel_Sizes(m_face, size, size);
FT_UInt glyph_index = FT_Get_Char_Index(m_face, wc);
FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);
FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_NORMAL);
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;
if (xOffset >= 0 && xOffset < (int32_t)imgWidth && yOffset >= 0 && yOffset < (int32_t)imgHeight)
{
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));
}
}
}
}
width = (0 == m_face->glyph->bitmap.width) ? size / 2 : m_face->glyph->bitmap.width;
height = (0 == m_face->glyph->bitmap.rows) ? size : m_face->glyph->bitmap.rows;
}