diff --git a/cocos/2d/CCFont.cpp b/cocos/2d/CCFont.cpp index 14ff1b3651..3c44e8d5d3 100644 --- a/cocos/2d/CCFont.cpp +++ b/cocos/2d/CCFont.cpp @@ -25,12 +25,9 @@ #include "CCFont.h" #include "ccUTF8.h" -#include "edtaa3func.h" NS_CC_BEGIN -const int Font::DistanceMapSpread = 3; - const char * Font::_glyphASCII = "\"!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ "; const char * Font::_glyphNEHE = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ "; @@ -39,7 +36,6 @@ const char * Font::_glyphNEHE = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM Font::Font() : _usedGlyphs(GlyphCollection::ASCII) , _customGlyphs(nullptr) -,_distanceFieldEnabled(false) { } @@ -103,164 +99,6 @@ const char * Font::getCurrentGlyphCollection() const } } -unsigned char * Font::makeDistanceMap( unsigned char *img, unsigned int width, unsigned int height) -{ - unsigned int pixelAmount = (width + 2 * DistanceMapSpread) * (height + 2 * DistanceMapSpread); - - short * xdist = (short *) malloc( pixelAmount * sizeof(short) ); - short * ydist = (short *) malloc( pixelAmount * sizeof(short) ); - double * gx = (double *) calloc( pixelAmount, sizeof(double) ); - double * gy = (double *) calloc( pixelAmount, sizeof(double) ); - double * data = (double *) calloc( pixelAmount, sizeof(double) ); - double * outside = (double *) calloc( pixelAmount, sizeof(double) ); - double * inside = (double *) calloc( pixelAmount, sizeof(double) ); - unsigned int i,j; - - // Convert img into double (data) rescale image levels between 0 and 1 - unsigned int outWidth = width + 2 * DistanceMapSpread; - for (i = 0; i < width; ++i) - { - for (j = 0; j < height; ++j) - { - data[j * outWidth + DistanceMapSpread + i] = img[j * width + i] / 255.0; - } - } - - width += 2 * DistanceMapSpread; - height += 2 * DistanceMapSpread; - - // Transform background (outside contour, in areas of 0's) - computegradient( data, width, height, gx, gy); - edtaa3(data, gx, gy, width, height, xdist, ydist, outside); - for( i=0; i< pixelAmount; i++) - if( outside[i] < 0.0 ) - outside[i] = 0.0; - - // Transform foreground (inside contour, in areas of 1's) - for( i=0; i< pixelAmount; i++) - data[i] = 1 - data[i]; - computegradient( data, width, height, gx, gy); - edtaa3(data, gx, gy, width, height, xdist, ydist, inside); - for( i=0; i< pixelAmount; i++) - if( inside[i] < 0.0 ) - inside[i] = 0.0; - - // The bipolar distance field is now outside-inside - double dist; - /* Single channel 8-bit output (bad precision and range, but simple) */ - unsigned char *out = (unsigned char *) malloc( pixelAmount * sizeof(unsigned char) ); - for( i=0; i < pixelAmount; i++) - { - dist = outside[i] - inside[i]; - dist = 128.0 - dist*16; - if( dist < 0 ) dist = 0; - if( dist > 255 ) dist = 255; - out[i] = (unsigned char) dist; - } - /* Dual channel 16-bit output (more complicated, but good precision and range) */ - /*unsigned char *out = (unsigned char *) malloc( pixelAmount * 3 * sizeof(unsigned char) ); - for( i=0; i< pixelAmount; i++) - { - dist = outside[i] - inside[i]; - dist = 128.0 - dist*16; - if( dist < 0.0 ) dist = 0.0; - if( dist >= 256.0 ) dist = 255.999; - // R channel is a copy of the original grayscale image - out[3*i] = img[i]; - // G channel is fraction - out[3*i + 1] = (unsigned char) ( 256 - (dist - floor(dist)* 256.0 )); - // B channel is truncated integer part - out[3*i + 2] = (unsigned char)dist; - }*/ - - free( xdist ); - free( ydist ); - free( gx ); - free( gy ); - free( data ); - free( outside ); - free( inside ); - - return out; -} - -void Font::setDistanceFieldEnabled(bool distanceFieldEnabled) -{ - _distanceFieldEnabled = distanceFieldEnabled; -} - -bool Font::renderCharAt(unsigned short int charToRender, int posX, int posY, unsigned char *destMemory, int destSize) -{ - unsigned char *sourceBitmap = 0; - int sourceWidth = 0; - int sourceHeight = 0; - - sourceBitmap = getGlyphBitmap(charToRender, sourceWidth, sourceHeight); - - if (!sourceBitmap) - return false; - - if (_distanceFieldEnabled) - { - unsigned char * out = makeDistanceMap(sourceBitmap,sourceWidth,sourceHeight); - - int iX = posX; - int iY = posY; - - sourceWidth += 2 * DistanceMapSpread; - sourceHeight += 2 * DistanceMapSpread; - - for (int y = 0; y < sourceHeight; ++y) - { - int bitmap_y = y * sourceWidth; - - for (int x = 0; x < sourceWidth; ++x) - { - /* Dual channel 16-bit output (more complicated, but good precision and range) */ - /*int index = (iX + ( iY * destSize )) * 3; - int index2 = (bitmap_y + x)*3; - destMemory[index] = out[index2]; - destMemory[index + 1] = out[index2 + 1]; - destMemory[index + 2] = out[index2 + 2];*/ - - //Single channel 8-bit output - destMemory[iX + ( iY * destSize )] = out[bitmap_y + x]; - - iX += 1; - } - - iX = posX; - iY += 1; - } - free(out); - return true; - } - - int iX = posX; - int iY = posY; - - for (int y = 0; y < sourceHeight; ++y) - { - int bitmap_y = y * sourceWidth; - - for (int x = 0; x < sourceWidth; ++x) - { - unsigned char cTemp = sourceBitmap[bitmap_y + x]; - - // the final pixel - destMemory[(iX + ( iY * destSize ) )] = cTemp; - - iX += 1; - } - - iX = posX; - iY += 1; - } - - //everything good - return true; -} - unsigned short int * Font::getUTF16Text(const char *text, int &outNumLetters) const { unsigned short* utf16String = cc_utf8_to_utf16(text); diff --git a/cocos/2d/CCFont.h b/cocos/2d/CCFont.h index b164468d40..4b0fbe1171 100644 --- a/cocos/2d/CCFont.h +++ b/cocos/2d/CCFont.h @@ -39,13 +39,6 @@ class FontAtlas; class CC_DLL Font : public Object { public: - static const int DistanceMapSpread; - - static unsigned char * makeDistanceMap(unsigned char *img, unsigned int width, unsigned int height); - void setDistanceFieldEnabled(bool distanceFieldEnabled); - bool isDistanceFieldEnabled() const { return _distanceFieldEnabled;} - bool renderCharAt(unsigned short int charToRender, int posX, int posY, unsigned char *destMemory, int destSize); - virtual FontAtlas *createFontAtlas() = 0; virtual Size* getAdvancesForTextUTF16(unsigned short *text, int &outNumLetters) const = 0; @@ -77,7 +70,6 @@ protected: char * _customGlyphs; static const char * _glyphASCII; static const char * _glyphNEHE; - bool _distanceFieldEnabled; }; diff --git a/cocos/2d/CCFontAtlas.cpp b/cocos/2d/CCFontAtlas.cpp index 70d87f679b..a878aa9203 100644 --- a/cocos/2d/CCFontAtlas.cpp +++ b/cocos/2d/CCFontAtlas.cpp @@ -38,7 +38,6 @@ _font(&theFont), _currentPageData(nullptr) { _font->retain(); - _makeDistanceMap = _font->isDistanceFieldEnabled(); FontFreeType* fontTTf = dynamic_cast(_font); if (fontTTf) @@ -50,11 +49,12 @@ _currentPageData(nullptr) _currentPageOrigX = 0; _currentPageOrigY = 0; _letterPadding = 5; - + + _makeDistanceMap = fontTTf->isDistanceFieldEnabled(); if(_makeDistanceMap) { - _commonLineHeight += 2 * Font::DistanceMapSpread; - _letterPadding += 2 * Font::DistanceMapSpread; + _commonLineHeight += 2 * FontFreeType::DistanceMapSpread; + _letterPadding += 2 * FontFreeType::DistanceMapSpread; } _currentPageDataSize = (PAGE_WIDTH * PAGE_HEIGHT * 1); @@ -63,6 +63,10 @@ _currentPageData(nullptr) addTexture(*tex,0); tex->release(); } + else + { + _makeDistanceMap = false; + } } FontAtlas::~FontAtlas() @@ -190,7 +194,7 @@ bool FontAtlas::prepareLetterDefinitions(unsigned short *utf16String) tex->release(); } } - _font->renderCharAt(it->second.letteCharUTF16,_currentPageOrigX,_currentPageOrigY,_currentPageData,PAGE_WIDTH); + fontTTf->renderCharAt(it->second.letteCharUTF16,_currentPageOrigX,_currentPageOrigY,_currentPageData,PAGE_WIDTH); it->second.U = _currentPageOrigX - 1; it->second.V = _currentPageOrigY; @@ -231,7 +235,7 @@ float FontAtlas::getCommonLineHeight() const void FontAtlas::setCommonLineHeight(float newHeight) { if(_makeDistanceMap) - newHeight += 2 * Font::DistanceMapSpread; + newHeight += 2 * FontFreeType::DistanceMapSpread; _commonLineHeight = newHeight; } diff --git a/cocos/2d/CCFontAtlasCache.cpp b/cocos/2d/CCFontAtlasCache.cpp index 44439e2437..1701ac3701 100644 --- a/cocos/2d/CCFontAtlasCache.cpp +++ b/cocos/2d/CCFontAtlasCache.cpp @@ -42,7 +42,7 @@ FontAtlas * FontAtlasCache::getFontAtlasTTF(const std::string& fontFileName, int if ( !tempAtlas ) { - Font *font = FontFreeType::create(fontFileName, size, glyphs, customGlyphs); + FontFreeType *font = FontFreeType::create(fontFileName, size, glyphs, customGlyphs); if (font) { font->setDistanceFieldEnabled(useDistanceField); diff --git a/cocos/2d/CCFontFreeType.cpp b/cocos/2d/CCFontFreeType.cpp index 1adc138b0f..a3afb8d317 100644 --- a/cocos/2d/CCFontFreeType.cpp +++ b/cocos/2d/CCFontFreeType.cpp @@ -29,12 +29,14 @@ THE SOFTWARE. #include "ccUTF8.h" #include "CCFontFreeType.h" #include "platform/CCFileUtils.h" +#include "edtaa3func.h" NS_CC_BEGIN FT_Library FontFreeType::_FTlibrary; bool FontFreeType::_FTInitialized = false; +const int FontFreeType::DistanceMapSpread = 3; FontFreeType * FontFreeType::create(const std::string &fontName, int fontSize, GlyphCollection glyphs, const char *customGlyphs) { @@ -85,9 +87,8 @@ FT_Library FontFreeType::getFTLibrary() FontFreeType::FontFreeType() : _fontRef(nullptr), _letterPadding(5) +,_distanceFieldEnabled(false) { - if(_distanceFieldEnabled) - _letterPadding += 2 * DistanceMapSpread; } bool FontFreeType::createFontObject(const std::string &fontName, int fontSize) @@ -297,4 +298,164 @@ int FontFreeType::getLetterPadding() const return _letterPadding; } +unsigned char * makeDistanceMap( unsigned char *img, unsigned int width, unsigned int height) +{ + unsigned int pixelAmount = (width + 2 * FontFreeType::DistanceMapSpread) * (height + 2 * FontFreeType::DistanceMapSpread); + + short * xdist = (short *) malloc( pixelAmount * sizeof(short) ); + short * ydist = (short *) malloc( pixelAmount * sizeof(short) ); + double * gx = (double *) calloc( pixelAmount, sizeof(double) ); + double * gy = (double *) calloc( pixelAmount, sizeof(double) ); + double * data = (double *) calloc( pixelAmount, sizeof(double) ); + double * outside = (double *) calloc( pixelAmount, sizeof(double) ); + double * inside = (double *) calloc( pixelAmount, sizeof(double) ); + unsigned int i,j; + + // Convert img into double (data) rescale image levels between 0 and 1 + unsigned int outWidth = width + 2 * FontFreeType::DistanceMapSpread; + for (i = 0; i < width; ++i) + { + for (j = 0; j < height; ++j) + { + data[j * outWidth + FontFreeType::DistanceMapSpread + i] = img[j * width + i] / 255.0; + } + } + + width += 2 * FontFreeType::DistanceMapSpread; + height += 2 * FontFreeType::DistanceMapSpread; + + // Transform background (outside contour, in areas of 0's) + computegradient( data, width, height, gx, gy); + edtaa3(data, gx, gy, width, height, xdist, ydist, outside); + for( i=0; i< pixelAmount; i++) + if( outside[i] < 0.0 ) + outside[i] = 0.0; + + // Transform foreground (inside contour, in areas of 1's) + for( i=0; i< pixelAmount; i++) + data[i] = 1 - data[i]; + computegradient( data, width, height, gx, gy); + edtaa3(data, gx, gy, width, height, xdist, ydist, inside); + for( i=0; i< pixelAmount; i++) + if( inside[i] < 0.0 ) + inside[i] = 0.0; + + // The bipolar distance field is now outside-inside + double dist; + /* Single channel 8-bit output (bad precision and range, but simple) */ + unsigned char *out = (unsigned char *) malloc( pixelAmount * sizeof(unsigned char) ); + for( i=0; i < pixelAmount; i++) + { + dist = outside[i] - inside[i]; + dist = 128.0 - dist*16; + if( dist < 0 ) dist = 0; + if( dist > 255 ) dist = 255; + out[i] = (unsigned char) dist; + } + /* Dual channel 16-bit output (more complicated, but good precision and range) */ + /*unsigned char *out = (unsigned char *) malloc( pixelAmount * 3 * sizeof(unsigned char) ); + for( i=0; i< pixelAmount; i++) + { + dist = outside[i] - inside[i]; + dist = 128.0 - dist*16; + if( dist < 0.0 ) dist = 0.0; + if( dist >= 256.0 ) dist = 255.999; + // R channel is a copy of the original grayscale image + out[3*i] = img[i]; + // G channel is fraction + out[3*i + 1] = (unsigned char) ( 256 - (dist - floor(dist)* 256.0 )); + // B channel is truncated integer part + out[3*i + 2] = (unsigned char)dist; + }*/ + + free( xdist ); + free( ydist ); + free( gx ); + free( gy ); + free( data ); + free( outside ); + free( inside ); + + return out; +} + +void FontFreeType::setDistanceFieldEnabled(bool distanceFieldEnabled) +{ + if(distanceFieldEnabled) + _letterPadding += 2 * DistanceMapSpread; + _distanceFieldEnabled = distanceFieldEnabled; +} + +bool FontFreeType::renderCharAt(unsigned short int charToRender, int posX, int posY, unsigned char *destMemory, int destSize) +{ + unsigned char *sourceBitmap = 0; + int sourceWidth = 0; + int sourceHeight = 0; + + sourceBitmap = getGlyphBitmap(charToRender, sourceWidth, sourceHeight); + + if (!sourceBitmap) + return false; + + if (_distanceFieldEnabled) + { + unsigned char * out = makeDistanceMap(sourceBitmap,sourceWidth,sourceHeight); + + int iX = posX; + int iY = posY; + + sourceWidth += 2 * DistanceMapSpread; + sourceHeight += 2 * DistanceMapSpread; + + for (int y = 0; y < sourceHeight; ++y) + { + int bitmap_y = y * sourceWidth; + + for (int x = 0; x < sourceWidth; ++x) + { + /* Dual channel 16-bit output (more complicated, but good precision and range) */ + /*int index = (iX + ( iY * destSize )) * 3; + int index2 = (bitmap_y + x)*3; + destMemory[index] = out[index2]; + destMemory[index + 1] = out[index2 + 1]; + destMemory[index + 2] = out[index2 + 2];*/ + + //Single channel 8-bit output + destMemory[iX + ( iY * destSize )] = out[bitmap_y + x]; + + iX += 1; + } + + iX = posX; + iY += 1; + } + free(out); + return true; + } + + int iX = posX; + int iY = posY; + + for (int y = 0; y < sourceHeight; ++y) + { + int bitmap_y = y * sourceWidth; + + for (int x = 0; x < sourceWidth; ++x) + { + unsigned char cTemp = sourceBitmap[bitmap_y + x]; + + // the final pixel + destMemory[(iX + ( iY * destSize ) )] = cTemp; + + iX += 1; + } + + iX = posX; + iY += 1; + } + + //everything good + return true; +} + NS_CC_END \ No newline at end of file diff --git a/cocos/2d/CCFontFreeType.h b/cocos/2d/CCFontFreeType.h index bcae504c35..33f3f76b36 100644 --- a/cocos/2d/CCFontFreeType.h +++ b/cocos/2d/CCFontFreeType.h @@ -39,11 +39,16 @@ NS_CC_BEGIN class CC_DLL FontFreeType : public Font { public: - + static const int DistanceMapSpread; + static FontFreeType * create(const std::string &fontName, int fontSize, GlyphCollection glyphs, const char *customGlyphs); static void shutdownFreeType(); + void setDistanceFieldEnabled(bool distanceFieldEnabled); + bool isDistanceFieldEnabled() const { return _distanceFieldEnabled;} + bool renderCharAt(unsigned short int charToRender, int posX, int posY, unsigned char *destMemory, int destSize); + virtual FontAtlas * createFontAtlas() override; virtual Size * getAdvancesForTextUTF16(unsigned short *text, int &outNumLetters) const override; @@ -74,6 +79,7 @@ private: int _letterPadding; std::string _fontName; Data _ttfData; + bool _distanceFieldEnabled; }; NS_CC_END