From b0d7ecec420e6cf6aea544f3740d08ec0e0ffbc9 Mon Sep 17 00:00:00 2001 From: yodesoft Date: Mon, 3 Sep 2012 12:38:29 +0800 Subject: [PATCH 1/2] Supported display Unicode chars. --- cocos2dx/platform/linux/CCImage.cpp | 174 +++++++++++++++++----------- 1 file changed, 107 insertions(+), 67 deletions(-) diff --git a/cocos2dx/platform/linux/CCImage.cpp b/cocos2dx/platform/linux/CCImage.cpp index 0925eb7cc0..3e65ef7919 100644 --- a/cocos2dx/platform/linux/CCImage.cpp +++ b/cocos2dx/platform/linux/CCImage.cpp @@ -22,8 +22,8 @@ using namespace std; struct TextLine { - string sLineStr; int iLineWidth; + wchar_t* text; }; NS_CC_BEGIN @@ -43,89 +43,134 @@ public: // if (m_pData) { // delete m_pData; // } - + reset(); } void reset() { iMaxLineWidth = 0; iMaxLineHeight = 0; - vLines.clear(); + //Free all text lines + size_t size = vLines.size(); + for (int i=0; iglyph->metrics.horiAdvance + face->glyph->metrics.horiBearingX - face->glyph->metrics.width))/*-iInterval*/;//TODO interval + return a; + } + if ((**p & 0xE0) == 0xC0) + { + int a = *((*p)++) & 0x1F; + int b = *((*p)++) & 0x3F; + + return (a << 6) | b; + } + if ((**p & 0xF0) == 0xE0) + { + int a = *((*p)++) & 0x0F; + int b = *((*p)++) & 0x3F; + int c = *((*p)++) & 0x3F; + + return (a << 12) | (b << 6) | c; + } + if ((**p & 0xF8) == 0xF0) + { + int a = *((*p)++) & 0x07; + int b = *((*p)++) & 0x3F; + int c = *((*p)++) & 0x3F; + int d = *((*p)++) & 0x3F; + + return (a << 18) | (b << 12) | (c << 8) | d; + } + return 0; + } + + void buildLine(wchar_t* buf, size_t buf_len, FT_Face face, int iCurXCursor, FT_UInt cLastChar) { + TextLine oTempLine; + wchar_t* text = (wchar_t*)malloc(sizeof(wchar_t) * (buf_len+1)); + memcpy(text, buf, sizeof(wchar_t) * buf_len); + text[buf_len] = '\0'; + oTempLine.text = text; + + //get last glyph + int iError = FT_Load_Char(face, cLastChar, FT_LOAD_DEFAULT); + + oTempLine.iLineWidth = iCurXCursor;// - SHIFT6((face->glyph->metrics.horiAdvance + face->glyph->metrics.horiBearingX - face->glyph->metrics.width))/*-iInterval*/;//TODO interval iMaxLineWidth = MAX(iMaxLineWidth, oTempLine.iLineWidth); - ss.clear(); - ss.str(""); - vLines.push_back(oTempLine); + vLines.push_back(oTempLine); } bool divideString(FT_Face face, const char* sText, int iMaxWidth, int iMaxHeight) { - const char* pText = sText; int iError = 0; int iCurXCursor, iCurYCursor; - iError = FT_Load_Glyph(face, FT_Get_Char_Index(face, *pText), - FT_LOAD_DEFAULT); + const char* pText = sText; + + FT_UInt unicode = utf8((char**)&pText); + iError = FT_Load_Char(face, unicode, FT_LOAD_DEFAULT); if (iError) { return false; } iCurXCursor = -SHIFT6(face->glyph->metrics.horiBearingX); - //init stringstream - stringstream ss; + FT_UInt cLastCh = 0; - int cLastCh = 0; + pText = sText; + size_t text_len = 0; + wchar_t* text_buf = (wchar_t*) malloc(sizeof(wchar_t) * strlen(sText)); + while (unicode=utf8((char**)&pText)) { + if (unicode == '\n') { + buildLine(text_buf, text_len, face, iCurXCursor, cLastCh); + text_len = 0; - while (*pText != '\0') { - if (*pText == '\n') { - buildLine(ss, face, iCurXCursor, cLastCh); - - pText++; - iError = FT_Load_Glyph(face, FT_Get_Char_Index(face, *pText), - FT_LOAD_DEFAULT); + iError = FT_Load_Char(face, unicode, FT_LOAD_DEFAULT); if (iError) { + free(text_buf); return false; } iCurXCursor = -SHIFT6(face->glyph->metrics.horiBearingX); continue; } - iError = FT_Load_Glyph(face, FT_Get_Char_Index(face, *pText), - FT_LOAD_DEFAULT); + iError = FT_Load_Char(face, unicode, FT_LOAD_DEFAULT); if (iError) { + free(text_buf); return false; - //break; } + //check its width //divide it when exceeding if ((iMaxWidth > 0 && iCurXCursor + SHIFT6(face->glyph->metrics.width) > iMaxWidth)) { - buildLine(ss, face , iCurXCursor, cLastCh); + buildLine(text_buf, text_len, face , iCurXCursor, cLastCh); + text_len = 0; iCurXCursor = -SHIFT6(face->glyph->metrics.horiBearingX); } - cLastCh = *pText; - ss << *pText; + cLastCh = unicode; + text_buf[text_len] = unicode; + ++text_len; iCurXCursor += SHIFT6(face->glyph->metrics.horiAdvance) + iInterval; - pText++; - } + if (iError) { + free(text_buf); return false; } - buildLine(ss,face, iCurXCursor, cLastCh); + buildLine(text_buf, text_len, face, iCurXCursor, cLastCh); + free(text_buf); return true; } @@ -137,11 +182,10 @@ public: * while -1 means fail * */ - int computeLineStart(FT_Face face, CCImage::ETextAlign eAlignMask, char cText, + int computeLineStart(FT_Face face, CCImage::ETextAlign eAlignMask, FT_UInt unicode, int iLineIndex) { int iRet; - int iError = FT_Load_Glyph(face, FT_Get_Char_Index(face, cText), - FT_LOAD_DEFAULT); + int iError = FT_Load_Char(face, unicode, FT_LOAD_DEFAULT); if (iError) { return -1; } @@ -183,7 +227,6 @@ public: FT_Face face; FT_Error iError; - const char* pText = text; //data will be deleted by CCImage // if (m_pData) { // delete m_pData; @@ -195,7 +238,9 @@ public: return false; } do { - iError = FT_New_Face( library, pFontName, 0, &face ); + //iError = FT_New_Face( library, pFontName, 0, &face ); + //TODO: Create font name array??? + iError = FT_New_Face( library, "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc", 0, &face ); if (iError) { //no valid font found use default @@ -216,8 +261,7 @@ public: //compute the final line width iMaxLineWidth = MAX(iMaxLineWidth, nWidth); - iMaxLineHeight = (face->size->metrics.ascender >> 6) - - (face->size->metrics.descender >> 6); + iMaxLineHeight = (face->size->metrics.ascender >> 6) - (face->size->metrics.descender >> 6); iMaxLineHeight *= vLines.size(); int txtHeight = iMaxLineHeight; @@ -230,31 +274,34 @@ public: memset(m_pData,0, iMaxLineWidth * iMaxLineHeight*4); - for (size_t i = 0; i < vLines.size(); i++) { - pText = vLines[i].sLineStr.c_str(); - //initialize the origin cursor - iCurXCursor = computeLineStart(face, eAlignMask, *pText, i); + size_t lines = vLines.size(); + for (size_t i = 0; i < lines; i++) { + const wchar_t* text_ptr = vLines[i].text; - while (*pText != 0) { - int iError = FT_Load_Glyph(face, FT_Get_Char_Index(face, *pText), - FT_LOAD_RENDER); + //initialize the origin cursor + iCurXCursor = computeLineStart(face, eAlignMask, text_ptr[0], i); + + size_t text_len = wcslen(text_ptr); + for (size_t i=0; iglyph->bitmap; + FT_Bitmap& bitmap = face->glyph->bitmap; + int yoffset = iCurYCursor - (face->glyph->metrics.horiBearingY >> 6); + int xoffset = iCurXCursor + (face->glyph->metrics.horiBearingX >> 6); for (int i = 0; i < bitmap.rows; ++i) { for (int j = 0; j < bitmap.width; ++j) { + unsigned char cTemp = bitmap.buffer[i * bitmap.width + j]; + if (cTemp == 0) continue; + // if it has gray>0 we set show it as 1, o otherwise - int iY = iCurYCursor + i - - (face->glyph->metrics.horiBearingY - >> 6); - int iX = iCurXCursor - + (face->glyph->metrics.horiBearingX - >> 6) + j; + int iY = yoffset + i; + int iX = xoffset + j; if (iY>=iMaxLineHeight) { //exceed the height truncate @@ -270,20 +317,16 @@ public: // bitmap.buffer[i * bitmap.width + j];//G // m_pData[(iY * iMaxLineWidth + iX) * 4 + 0] = // bitmap.buffer[i * bitmap.width + j];//B + int iTemp = 0; - unsigned char cTemp = bitmap.buffer[i - * bitmap.width + j]; iTemp |= (cTemp ? 0xff : 0)<<24; iTemp |= cTemp << 16 | cTemp << 8 | cTemp; - *(int*) &m_pData[(iY * iMaxLineWidth + iX) - * 4 + 0] = iTemp; + *(int*) &m_pData[(iY * iMaxLineWidth + iX) * 4 + 0] = iTemp; } } //step to next glyph - iCurXCursor += (face->glyph->metrics.horiAdvance >> 6) - + iInterval; + iCurXCursor += (face->glyph->metrics.horiAdvance >> 6) + iInterval; - pText++; } iCurYCursor += (face->size->metrics.ascender >> 6) - (face->size->metrics.descender >> 6); @@ -301,9 +344,6 @@ public: FT_Done_Face(face); face = NULL; - //clear all lines - vLines.clear(); - //success; if (iError) { bRet = false; From 95f204cd17e0ed31484aeb25eafb25588f5b2a33 Mon Sep 17 00:00:00 2001 From: yodesoft Date: Tue, 4 Sep 2012 10:48:02 +0800 Subject: [PATCH 2/2] Add font table to handler font info, eg. family_name, style_name, filename --- cocos2dx/platform/linux/CCImage.cpp | 48 ++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/cocos2dx/platform/linux/CCImage.cpp b/cocos2dx/platform/linux/CCImage.cpp index 3e65ef7919..e9ea9daa2e 100644 --- a/cocos2dx/platform/linux/CCImage.cpp +++ b/cocos2dx/platform/linux/CCImage.cpp @@ -26,6 +26,21 @@ struct TextLine { wchar_t* text; }; +struct FontTableItem { + char* family_name; + char* style_name; + char* filename; +}; + +const int fontTableItems = 4; +const char* fontPath = "/usr/share/fonts/truetype/"; +FontTableItem fontsTable[fontTableItems] = { + { "Serif", "Medium", "freefont/FreeSerif.ttf" }, + { "Sans", "Medium", "freefont/FreeSans.ttf" }, + { "WenQuanYi Micro Hei", "Regular", "wqy/wqy-microhei.ttc" }, + { "WenQuanYi Zen Hei", "Regular", "wqy/wqy-zenhei.ttc" }, +}; + NS_CC_BEGIN class BitmapDC { @@ -223,6 +238,29 @@ public: return iRet; } + char* getFontFile(const char* family_name) { + char* ret = NULL; + for (int i=0; ifamily_name, family_name) == 0) { + size_t len = strlen(fontPath) + strlen(item->filename) + 1; + ret = (char*) malloc(len); + snprintf(ret, len, "%s%s", fontPath, item->filename); + break; + } + } + + // Return a default font , if font is not found + if (ret == NULL) { + FontTableItem* item = &fontsTable[0]; + size_t len = strlen(fontPath) + strlen(item->filename) + 1; + ret = (char*) malloc(len); + snprintf(ret, len, "%s%s", fontPath, item->filename); + } + + return ret; + } + bool getBitmap(const char *text, int nWidth, int nHeight, CCImage::ETextAlign eAlignMask, const char * pFontName, float fontSize) { FT_Face face; FT_Error iError; @@ -238,9 +276,9 @@ public: return false; } do { - //iError = FT_New_Face( library, pFontName, 0, &face ); - //TODO: Create font name array??? - iError = FT_New_Face( library, "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc", 0, &face ); + char* fontfile = getFontFile(pFontName); + iError = FT_New_Face( library, fontfile, 0, &face ); + free(fontfile); if (iError) { //no valid font found use default @@ -384,9 +422,9 @@ bool CCImage::initWithString( BitmapDC &dc = sharedBitmapDC(); - const char* pFullFontName = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(pFontName); + //const char* pFullFontName = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(pFontName); - CC_BREAK_IF(! dc.getBitmap(pText, nWidth, nHeight, eAlignMask, pFullFontName, nSize)); + CC_BREAK_IF(! dc.getBitmap(pText, nWidth, nHeight, eAlignMask, pFontName, nSize)); // assign the dc.m_pData to m_pData in order to save time m_pData = dc.m_pData;