14 #if OSSIM_HAS_FREETYPE 24 static ossimTrace traceDebug (
"ossimFreeTypeFont:debug");
28 ossimFreeTypeFont::ossimFreeTypeFont(
const ossimFilename& fontFile)
32 theFontFile(fontFile),
33 theOutputBuffer(NULL),
35 theKerningEnabledFlag(
true),
36 theNeedToLayoutGlyphsFlag(
true),
37 theBoundingRectIsValid(false)
42 error = FT_Init_FreeType(&theLibrary);
50 error = FT_New_Face( theLibrary,
54 if (error == FT_Err_Unknown_File_Format)
59 <<
"WARNING ossimFreeTypeFont::ossimFreeTypeFont: Unable to create a font face for file = " 63 FT_Done_Library(theLibrary);
69 setBaseClassInformation();
79 ossimFreeTypeFont::ossimFreeTypeFont(
const ossimFreeTypeFont& rhs)
81 theMatrix(rhs.theMatrix),
82 theFontFile(rhs.theFontFile),
83 theOutputBuffer(NULL),
85 theKerningEnabledFlag(rhs.theKerningEnabledFlag),
86 theNeedToLayoutGlyphsFlag(rhs.theNeedToLayoutGlyphsFlag),
87 theStringCenter(rhs.theStringCenter),
88 theShift(rhs.theShift),
89 thePrecomputedBoundingRect(rhs.thePrecomputedBoundingRect),
90 theBoundingRectIsValid(rhs.theBoundingRectIsValid)
92 if(rhs.getErrorStatus())
99 error = FT_Init_FreeType(&theLibrary);
108 error = FT_New_Face( theLibrary,
109 rhs.theFontFile.c_str(),
112 if(error == FT_Err_Unknown_File_Format)
117 <<
"WARNING ossimFreeTypeFoont::ossimFreeTypeFont: Unable to create a font face for file = " 122 FT_Done_Library(theLibrary);
128 if(rhs.theBufferSize)
130 theBufferSize = rhs.theBufferSize;
132 memcpy(theOutputBuffer, rhs.theOutputBuffer, theBufferSize);
133 setBaseClassInformation();
134 theNeedToLayoutGlyphsFlag =
true;
135 layoutGlyphs(theStringToRasterize);
142 ossimFreeTypeFont::~ossimFreeTypeFont()
146 delete [] theOutputBuffer;
147 theOutputBuffer = NULL;
151 FT_Done_Face(theFontFace);
156 FT_Done_FreeType(theLibrary);
161 void ossimFreeTypeFont::layoutGlyphs(
const ossimString& s )
163 if(!theNeedToLayoutGlyphsFlag||!theFontFace)
174 FT_UInt prev_index = 0;
175 FT_UInt num_glyphs = (FT_UInt)s.
size();
178 deleteGlyphs(theStringLayout);
179 theStringLayout.resize(s.
size());
181 theMatrix.xx = (FT_Fixed)(theAffineTransform[0][0]*0x10000);
182 theMatrix.xy = (FT_Fixed)(theAffineTransform[1][0]*0x10000);
183 theMatrix.yx = (FT_Fixed)(theAffineTransform[0][1]*0x10000);
184 theMatrix.yy = (FT_Fixed)(theAffineTransform[1][1]*0x10000);
186 int hasKerning = FT_HAS_KERNING(theFontFace);
191 const char* c = s.
c_str();
192 for (
n = 0;
n < (int)num_glyphs;
n++)
194 long charOffset = c[
n];
196 FT_ULong charIndex = 0;
200 charIndex = (charOffset + 256);
204 charIndex = charOffset;
206 theStringLayout[
n].glyph_index = FT_Get_Char_Index( theFontFace,
208 theStringLayout[
n].image = NULL;
210 if (hasKerning&&theKerningEnabledFlag&&prev_index)
215 FT_Get_Kerning( theFontFace,
217 theStringLayout[
n].glyph_index,
221 origin_x += (kern.x);
230 error = FT_Load_Glyph( theFontFace,
231 theStringLayout[
n].glyph_index,
238 error = FT_Get_Glyph ( theFontFace->glyph, &theStringLayout[
n].image );
245 theStringLayout[
n].pos = origin;
247 origin_x += (theFontFace->glyph->advance.x);
248 prev_index = theStringLayout[
n].glyph_index;
251 theStringCenter.x = origin_x / 2;
252 theStringCenter.y = 0;
254 FT_Vector_Transform( &theStringCenter, &theMatrix );
255 theNeedToLayoutGlyphsFlag =
false;
261 setupForRasterization();
262 layoutGlyphs(theStringToRasterize);
264 int num_glyphs = (int)theStringLayout.size();
270 delta.x = -theStringCenter.x;
273 memset(theOutputBuffer, 0, theBufferSize);
274 for (
n = 0;
n < num_glyphs;
n++)
280 if ( !theStringLayout[
n].image )
286 error = FT_Glyph_Copy( theStringLayout[
n].image, &image );
291 vec = theStringLayout[
n].pos;
292 FT_Vector_Transform( &vec, &theMatrix );
295 error = FT_Glyph_Transform( image, &theMatrix, &vec );
302 FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
315 getBufferRect(bufRect);
316 getBoundingBox(boundingBox);
319 boundingBox.
lr().
y - bufRect.
ul().
y,
321 boundingBox.
lr().
y - bufRect.
lr().
y,
328 error = FT_Glyph_To_Bitmap( &image,
329 ft_render_mode_normal,
335 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)image;
337 ossimIpt ul(bitmap->left -theShift.x,
338 bitmap->top -theShift.y);
346 ul.x + bitmap->bitmap.width-1,
347 ul.y - (bitmap->bitmap.rows-1),
351 drawBitmap(&bitmap->bitmap,
357 FT_Done_Glyph( image );
360 return theOutputBuffer;
363 void ossimFreeTypeFont::getBoundingBox(
ossimIrect& box)
366 if(theBoundingRectIsValid)
368 box = thePrecomputedBoundingRect;
371 setupForRasterization();
372 layoutGlyphs(theStringToRasterize);
374 int num_glyphs = (int)theStringLayout.size();
378 bool firstBoxSet =
false;
380 delta.x = -theStringCenter.x;
383 for (
n = 0;
n < num_glyphs;
n++)
389 if ( !theStringLayout[
n].image )
395 error = FT_Glyph_Copy( theStringLayout[
n].image, &image );
400 vec = theStringLayout[
n].pos;
401 FT_Vector_Transform( &vec, &theMatrix );
404 error = FT_Glyph_Transform( image, &theMatrix, &vec );
411 FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
427 FT_Done_Glyph( image );
435 thePrecomputedBoundingRect = box;
438 void ossimFreeTypeFont::computeGlyphBox(FT_Glyph ,
441 long yBearing = theFontFace->glyph->metrics.horiBearingY/64;
442 long h = theFontFace->glyph->metrics.
height/64;
443 long w = theFontFace->glyph->metrics.width/64;
458 void ossimFreeTypeFont::drawBitmap(FT_Bitmap* bitmap,
464 unsigned char* buf = bitmap->buffer;
465 if(!theOutputBuffer||!buf)
return;
470 long difInX = intersectionRect.
ul().
x - glyphBox.
ul().
x;
471 long difInY = glyphBox.
ul().
y - intersectionRect.
ul().
y;
473 long difOutX = intersectionRect.
ul().
x - bufRect.
ul().
x;
474 long difOutY = bufRect.
ul().
y - intersectionRect.
ul().
y;
478 long startInOffset = bitmap->width*difInY + difInX;
479 long startOutOffset = bufRect.
width()*difOutY + difOutX;
481 long outBufW = bufRect.
width();
482 long inBufW = bitmap->width;
490 for(
long rows = 0 ; rows < height; ++rows)
492 for(
long cols = 0; cols < width; ++cols)
494 if(buf[startInOffset+cols])
496 theOutputBuffer[startOutOffset + cols] = buf[startInOffset+cols];
499 startInOffset+=inBufW;
500 startOutOffset+=outBufW;
505 void ossimFreeTypeFont::setupForRasterization()
508 if(!theFontFace)
return;
510 if(!theFontFace->charmap)
512 error = FT_Select_Charmap(theFontFace,
516 error = FT_Set_Char_Size(theFontFace,
517 theHorizontalPixelSize*64,
518 theVerticalPixelSize*64,
519 theHorizontalDeviceUnits,
520 theVerticalDeviceUnits);
527 void ossimFreeTypeFont::setBaseClassInformation()
531 theFamilyName = theFontFace->family_name;
535 vector<ossimIpt> initialPointList;
536 getFixedSizes(initialPointList);
538 theHorizontalPixelSize = initialPointList[0].x;
539 theVerticalPixelSize = initialPointList[0].y;
543 theHorizontalPixelSize = 8;
544 theVerticalPixelSize = 8;
546 if((theFontFace->style_flags & FT_STYLE_FLAG_BOLD) &&
547 (theFontFace->style_flags&FT_STYLE_FLAG_ITALIC))
549 theStyleName =
"bold italic";
551 else if(theFontFace->style_flags & FT_STYLE_FLAG_BOLD)
553 theStyleName =
"bold";
555 else if(theFontFace->style_flags & FT_STYLE_FLAG_ITALIC)
557 theStyleName =
"italic";
561 theStyleName =
"normal";
567 void ossimFreeTypeFont::setCurrentFace(
long index)
572 if((index >0) && (index < theFontFace->num_faces))
574 FT_Done_Face(theFontFace);
577 error = FT_New_Face( theLibrary,
581 if((error == FT_Err_Unknown_File_Format)||error)
587 setBaseClassInformation();
589 theBoundingRectIsValid =
false;
594 void ossimFreeTypeFont::getFixedSizes(vector<ossimIpt>& sizeArray)
const 601 for(i = 0; i < theFontFace->num_fixed_sizes; ++i)
603 sizeArray.push_back(
ossimIpt(theFontFace->available_sizes[i].width,
604 theFontFace->available_sizes[i].height));
609 void ossimFreeTypeFont::allocateBuffer()
612 setupForRasterization();
613 getBoundingClipBox(box);
615 if(bufferSize != theBufferSize)
617 theBufferSize = bufferSize;
621 delete theOutputBuffer;
622 theOutputBuffer = NULL;
624 if(!theOutputBuffer&&theBufferSize)
631 void ossimFreeTypeFont::deleteGlyphs(vector<TGlyph>& glyphs)
635 for(i = 0; i < (int)glyphs.size(); ++i)
639 FT_Done_Glyph(glyphs[i].image);
static const ossimErrorCode OSSIM_OK
ossim_uint32 height() const
const ossimIpt & ul() const
bool intersects(const ossimIrect &rect) const
std::string::size_type size() const
os2<< "> n<< " > nendobj n
const ossimIpt & lr() const
ossim_uint32 width() const
ossimIrect clipToRect(const ossimIrect &rect) const
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string's contents...
#define RTTI_DEF1(cls, name, b1)
ossimIrect combine(const ossimIrect &rect) const
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)