move some method to FontFreeType that only relating to FontFreeType from Font.

This commit is contained in:
Dhilan007 2014-01-21 10:36:32 +08:00
parent 802fc092be
commit f22e4d474f
6 changed files with 181 additions and 180 deletions

View File

@ -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);

View File

@ -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;
};

View File

@ -38,7 +38,6 @@ _font(&theFont),
_currentPageData(nullptr)
{
_font->retain();
_makeDistanceMap = _font->isDistanceFieldEnabled();
FontFreeType* fontTTf = dynamic_cast<FontFreeType*>(_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;
}

View File

@ -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);

View File

@ -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

View File

@ -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