00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "pgfont.h"
00030 #include "pglog.h"
00031 #include "pgfilearchive.h"
00032 #include "facecache.h"
00033 #include "pgstring.h"
00034
00035
00036
00037
00038 PG_FontEngine::MAP_FONTS PG_FontEngine::my_fontcache;
00039 FT_Library PG_FontEngine::my_library;
00040
00041 PG_FontEngine::PG_FontEngine() {
00042 FT_Init_FreeType(&my_library);
00043 }
00044
00045 PG_FontEngine::~PG_FontEngine() {
00046
00047
00048 for(MAP_FONTS::iterator i = my_fontcache.begin(); i != my_fontcache.end(); i++) {
00049 delete (*i).second;
00050 }
00051 my_fontcache.clear();
00052
00053 FT_Done_FreeType(my_library);
00054
00055
00056
00057
00058 }
00059
00060 void PG_FontEngine::FontEngineError(FT_Error error) {
00061 #undef __FTERRORS_H__
00062 #define FT_ERRORDEF( e, v, s ) { e, s },
00063 #define FT_ERROR_START_LIST {
00064 #define FT_ERROR_END_LIST { -1, NULL } };
00065 const struct {
00066 int err_code;
00067 const char *err_msg;
00068 }
00069 ft_errors[] =
00070 #include FT_ERRORS_H
00071
00072 int i = 0;
00073 while (ft_errors[i].err_code != -1) {
00074 if (ft_errors[i].err_code == error) {
00075 PG_LogWRN("FreeType error %d : %s",error,ft_errors[i].err_msg);
00076 return;
00077 }
00078 i++;
00079 }
00080
00081 PG_LogWRN("FreeType : Unknown error : %d", error);
00082 return;
00083 }
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 PG_GlyphCacheItem* PG_FontEngine::GetGlyph(PG_Font *Param, int glyph_index) {
00096
00097 PG_FontFaceCacheItem* facecache = Param->GetFaceCache();
00098 PG_GlyphCacheItem *GlyphCacheItem = facecache->GlyphCache[glyph_index];
00099
00100 if(GlyphCacheItem != NULL) {
00101 return GlyphCacheItem;
00102 }
00103
00104 FT_Face face = facecache->Face;
00105
00106 if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER ))
00107 return NULL;
00108
00109 Uint32 bitmapsize = face->glyph->bitmap.pitch * face->glyph->bitmap.rows;
00110 GlyphCacheItem = new PG_GlyphCacheItem(bitmapsize);
00111
00112 GlyphCacheItem->Glyph_Index = glyph_index;
00113 GlyphCacheItem->Bitmap = face->glyph->bitmap;
00114 GlyphCacheItem->Bitmap_left = face->glyph->bitmap_left;
00115 GlyphCacheItem->Bitmap_top = face->glyph->bitmap_top;
00116 GlyphCacheItem->Advance_x = FT_CEIL(face->glyph->metrics.horiAdvance);
00117 memcpy(GlyphCacheItem->data(), face->glyph->bitmap.buffer, bitmapsize);
00118 GlyphCacheItem->Bitmap.buffer = (unsigned char*)GlyphCacheItem->data();
00119
00120 facecache->GlyphCache[glyph_index] = GlyphCacheItem;
00121 return GlyphCacheItem;
00122 }
00123
00124 #ifndef OLD_TEXTRENDERING
00125
00126 template < class DT >
00127 inline void BlitTemplate(DT pixels, SDL_Surface* Surface, FT_Bitmap *Bitmap, int PosX, int PosY, int x0, int x1, int y0, int y1, PG_Font *Param) {
00128 int xw = x1-x0;
00129
00130 SDL_PixelFormat* format = Surface->format;
00131 Uint8 Rloss = format->Rloss;
00132 Uint8 Gloss = format->Gloss;
00133 Uint8 Bloss = format->Bloss;
00134 Uint8 Aloss = format->Aloss;
00135 Uint8 Rloss8 = 8-Rloss;
00136 Uint8 Gloss8 = 8-Gloss;
00137 Uint8 Bloss8 = 8-Bloss;
00138 Uint8 Aloss8 = 8-Aloss;
00139 Uint8 Rshift = format->Rshift;
00140 Uint8 Gshift = format->Gshift;
00141 Uint8 Bshift = format->Bshift;
00142 Uint8 Ashift = format->Ashift;
00143 Uint32 Rmask = format->Rmask;
00144 Uint32 Gmask = format->Gmask;
00145 Uint32 Bmask = format->Bmask;
00146 Uint32 Amask = format->Amask;
00147
00148 Uint8 bpp = format->BytesPerPixel;
00149 Uint32 pitch = Surface->pitch;
00150 Uint32 src_pitch = Bitmap->pitch;
00151 register Uint8* src_pixels = Bitmap->buffer + x0 + y0*Bitmap->pitch;
00152 register Uint8* dst_pixels = (Uint8*)pixels + (PosX+x0)*bpp + (PosY+y0)*pitch ;
00153 Uint8* line;
00154
00155 Uint8 r,g,b,a;
00156 unsigned rv,gv,bv,av;
00157 Sint32 cr,cg,cb;
00158 Uint32 color = 0;
00159 Sint32 v;
00160
00161 PG_Color fc = Param->GetColor();
00162 cr = fc.r;
00163 cg = fc.g;
00164 cb = fc.b;
00165
00166 int alpha = Param->GetAlpha();
00167
00168 line = dst_pixels;
00169 for (register int y = y0; y <y1; y++, src_pixels += src_pitch) {
00170
00171 dst_pixels = line;
00172
00173 for (register int x = x0; x < x1; x++, dst_pixels += bpp) {
00174
00175
00176 v = *(Uint8 *)(src_pixels++);
00177
00178
00179 if(v == 0) {
00180 continue;
00181 }
00182
00183 if(alpha != 255) {
00184 v = (v * alpha) >> 8;
00185 }
00186
00187
00188 color = *((DT) (dst_pixels));
00189 switch(Surface->format->BytesPerPixel) {
00190 default:
00191
00192 rv = (color & Rmask) >> Rshift;
00193 r = (rv << Rloss) + (rv >> Rloss8);
00194 gv = (color & Gmask) >> Gshift;
00195 g = (gv << Gloss) + (gv >> Gloss8);
00196 bv = (color & Bmask) >> Bshift;
00197 b = (bv << Bloss) + (bv >> Bloss8);
00198 if(Amask) {
00199 av = (color & Amask) >> Ashift;
00200 a = (av << Aloss) + (av >> Aloss8);
00201 } else
00202 a = SDL_ALPHA_OPAQUE;
00203
00204
00205
00206
00207 if(v == 255) {
00208 r = cr;
00209 g = cg;
00210 b = cb;
00211 } else {
00212
00213
00214
00215 r += ((cr - r) * v) >> 8;
00216 g += ((cg - g) * v) >> 8;
00217 b += ((cb - b) * v) >> 8;
00218 }
00219
00220
00221
00222 if(a == 0) {
00223 a = v;
00224 }
00225
00226
00227 color = (r >> Rloss) << Rshift
00228 | (g >> Gloss) << Gshift
00229 | (b >> Bloss) << Bshift
00230 | ((a >> Aloss) << Ashift & Amask);
00231
00232 *((DT) (dst_pixels)) = color;
00233 break;
00234
00235 case 3:
00236 cr = (fc.r << format->Rshift) >> 16 & 0xff;
00237 cg = (fc.g << format->Gshift) >> 8 & 0xff;
00238 cb = fc.b << format->Bshift & 0xff;
00239
00240 if (v == 255) {
00241 r = cr;
00242 g = cg;
00243 b = cb;
00244 }
00245
00246 else {
00247 b = *(dst_pixels);
00248 g = *(dst_pixels+1);
00249 r = *(dst_pixels+2);
00250 r += ((cr - r) * v) >> 8;
00251 g += ((cg - g) * v) >> 8;
00252 b += ((cb - b) * v) >> 8;
00253 }
00254
00255 *dst_pixels = b;
00256 *(dst_pixels + 1) = g;
00257 *(dst_pixels + 2) = r;
00258 break;
00259
00260 case 1:
00261 SDL_GetRGBA(color, format, &r, &g, &b, &a);
00262
00263
00264 if(v == 255) {
00265 r = cr;
00266 g = cg;
00267 b = cb;
00268 } else {
00269
00270
00271
00272 r += ((cr - r) * v) >> 8;
00273 g += ((cg - g) * v) >> 8;
00274 b += ((cb - b) * v) >> 8;
00275 }
00276
00277
00278
00279 if(a == 0) {
00280 a = v;
00281 }
00282 color = SDL_MapRGBA(format, r,g,b, a);
00283 *((DT) (dst_pixels)) = color;
00284 break;
00285 }
00286
00287 }
00288 src_pixels -= xw;
00289 line += pitch;
00290 }
00291 }
00292
00293 bool PG_FontEngine::BlitFTBitmap(SDL_Surface *Surface, FT_Bitmap *Bitmap, int PosX, int PosY, PG_Font *Param, const PG_Rect* ClipRect) {
00294 int BitmapRealWidth;
00295
00296
00297
00298
00299
00300
00301
00302 if (Param->GetAlpha() == 0)
00303 return true;
00304
00305 BitmapRealWidth = Bitmap->width;
00306
00307
00308 static PG_Rect srfclip;
00309 SDL_GetClipRect(Surface, &srfclip);
00310
00311
00312 static PG_Rect clip;
00313 clip = *ClipRect / srfclip;
00314
00315
00316
00317
00318
00319
00320 int x0 = 0;
00321 int x1 = BitmapRealWidth;
00322 int y0 = 0;
00323 int y1 = Bitmap->rows;
00324
00325 if(PosX < clip.x) {
00326 x0 = clip.x - PosX;
00327 }
00328
00329 if(PosX+BitmapRealWidth > clip.x + clip.w) {
00330 x1 = (clip.x + clip.w) - PosX;
00331 }
00332
00333 if(PosY < clip.y) {
00334 y0 = clip.y - PosY;
00335 }
00336
00337 if(PosY+Bitmap->rows > clip.y + clip.h) {
00338 y1 = (clip.y + clip.h) - PosY;
00339 }
00340
00341 if((x1 <= x0) || (y1 <= y0)) {
00342 return false;
00343 }
00344
00345 switch(Surface->format->BytesPerPixel) {
00346 case 1:
00347 case 3:
00348 BlitTemplate((Uint8*)Surface->pixels, Surface, Bitmap, PosX, PosY, x0, x1, y0, y1, Param);
00349 break;
00350 case 2:
00351 BlitTemplate((Uint16*)Surface->pixels, Surface, Bitmap, PosX, PosY, x0, x1, y0, y1, Param);
00352 break;
00353 case 4:
00354 BlitTemplate((Uint32*)Surface->pixels, Surface, Bitmap, PosX, PosY, x0, x1, y0, y1, Param);
00355 break;
00356 default:
00357 PG_LogWRN("Unable to draw font: unsupported bit depth!");
00358 break;
00359 }
00360
00361 return true;
00362 }
00363
00364 #else
00365
00366 bool PG_FontEngine::BlitFTBitmap(SDL_Surface *Surface, FT_Bitmap *Bitmap, int PosX, int PosY, PG_Font *Param, PG_Rect *ClipRect) {
00367 int x,y;
00368 Uint32 *raw_pixels;
00369 SDL_Rect TargetPos;
00370 SDL_Rect SourcePos;
00371 int BitmapRealWidth;
00372
00373 if (Param->Alpha == 0)
00374 return true;
00375
00376 TargetPos.x = PosX;
00377 TargetPos.y = PosY;
00378
00379
00380 BitmapRealWidth = Bitmap->width;
00381 if (Param->Style & PG_FSTYLE_ITALIC) {
00382 BitmapRealWidth += (int)(Bitmap->rows * PG_FITALIC_ANGLE);
00383 }
00384
00385
00386 if ((TargetPos.x > (ClipRect->x + ClipRect->w)) || (TargetPos.y > (ClipRect->y +ClipRect->h )) || ((TargetPos.y+Bitmap->rows) < ClipRect->y) || ((TargetPos.x+BitmapRealWidth) < ClipRect->x))
00387 return true;
00388
00389
00390 if (my_charSurface != NULL) {
00391 if ((my_charSurface->w < BitmapRealWidth)||(my_charSurface->h < Bitmap->rows)) {
00392 SDL_FreeSurface(my_charSurface);
00393 my_charSurface = NULL;
00394 }
00395 }
00396
00397 if (my_charSurface == NULL) {
00398 my_charSurface = SDL_CreateRGBSurface(SDL_SRCALPHA , BitmapRealWidth, Bitmap->rows, 32, 0xff0000, 0xff00, 0xff, 0xff000000);
00399 if (my_charSurface == NULL) {
00400 PG_LogWRN("Can`t get char surface : %s",SDL_GetError());
00401 return false;
00402 }
00403 }
00404
00405 if (Param->Style & PG_FSTYLE_ITALIC) {
00406 SDL_FillRect(my_charSurface, NULL, 0);
00407 }
00408
00409 SourcePos.x = 0;
00410 SourcePos.y = 0;
00411 SourcePos.w = BitmapRealWidth;
00412 SourcePos.h = Bitmap->rows;
00413
00414
00415 if ((TargetPos.x + SourcePos.w) > (ClipRect->x + ClipRect->w))
00416 SourcePos.w = ClipRect->w - (TargetPos.x - ClipRect->x);
00417 if ((TargetPos.y + SourcePos.h) > (ClipRect->y + ClipRect->h))
00418 SourcePos.h = ClipRect->h - (TargetPos.y - ClipRect->y);
00419 if (TargetPos.x < ClipRect->x) {
00420 int delta;
00421
00422 delta = ClipRect->x - TargetPos.x;
00423 SourcePos.w -= delta;
00424 TargetPos.x += delta;
00425 SourcePos.x += delta;
00426 }
00427
00428 if (TargetPos.y < ClipRect->y) {
00429 int delta;
00430
00431 delta = ClipRect->y - TargetPos.y;
00432 SourcePos.h -= delta;
00433 TargetPos.y += delta;
00434 SourcePos.y += delta;
00435 }
00436
00437 raw_pixels = (Uint32 *) my_charSurface->pixels;
00438 Uint32 pitch_diff = 0;
00439
00440 switch (Bitmap->pixel_mode) {
00441 case ft_pixel_mode_grays: {
00442 Uint8 *SrcPix = Bitmap->buffer;
00443 int a;
00444
00445
00446 if (Param->Style & PG_FSTYLE_ITALIC) {
00447 double ioffset = Bitmap->rows * PG_FITALIC_ANGLE;
00448
00449 for (y = 0; y < Bitmap->rows; y++, SrcPix += Bitmap->pitch, ioffset -= PG_FITALIC_ANGLE) {
00450 for (x = 0; x < Bitmap->width; x++) {
00451 a = *(Uint8 *)(SrcPix++);
00452
00453
00454
00455
00456
00457 raw_pixels[int(ioffset) + x + (my_charSurface->pitch/4)*(y)] = Param->Color.MapRGBA(my_charSurface->format, a);
00458 }
00459 SrcPix -= x;
00460 }
00461 } else
00462 pitch_diff = (my_charSurface->pitch/4);
00463
00464 for (y = 0; y < Bitmap->rows; y++, SrcPix += Bitmap->pitch) {
00465 for (x = 0; x < Bitmap->width; x++) {
00466 a = *(Uint8 *)(SrcPix++);
00467
00468
00469
00470
00471
00472 if (Param->Alpha != 255)
00473 a = (a * Param->Alpha) / 255;
00474
00475 *raw_pixels = Param->Color.MapRGBA(my_charSurface->format, a);
00476 raw_pixels++;
00477 }
00478 SrcPix -= x;
00479 raw_pixels -= x;
00480 raw_pixels += pitch_diff;
00481 }
00482 break;
00483 }
00484
00485 default:
00486 PG_LogWRN("Unknown pixel type in font !");
00487 return false;
00488 }
00489
00490
00491 SDL_Rect BoldTarget = TargetPos;
00492 SDL_BlitSurface(my_charSurface, &SourcePos, Surface, &TargetPos);
00493
00494
00495 if (Param->Style & PG_FSTYLE_BOLD) {
00496 BoldTarget.x += Param->FaceCache->Bold_Offset;
00497 SDL_BlitSurface(my_charSurface, &SourcePos, Surface, &BoldTarget);
00498 }
00499
00500 return true;
00501 }
00502
00503 #endif
00504
00505
00506 bool PG_FontEngine::RenderText(SDL_Surface *Surface, const PG_Rect& ClipRect, int BaseLineX, int BaseLineY, const PG_String& Text, PG_Font *ParamIn) {
00507 return RenderText(Surface, (PG_Rect*)&ClipRect, BaseLineX, BaseLineY, Text, ParamIn);
00508 }
00509
00510 bool PG_FontEngine::RenderText(SDL_Surface *Surface, const PG_Rect *ClipRect, int BaseLineX, int BaseLineY, const PG_String& Text, PG_Font* font) {
00511 static bool bRecursion = false;
00512 int OriBaseX = BaseLineX;
00513 FT_UInt previous = 0;
00514
00515 PG_FontFaceCacheItem* FaceCache = font->GetFaceCache();
00516
00517
00518 if (FaceCache == NULL) {
00519 return false;
00520 }
00521
00522 FT_Face Face = FaceCache->Face;
00523 FT_Vector delta;
00524
00525 if(SDL_MUSTLOCK(Surface)) {
00526 SDL_LockSurface(Surface);
00527 }
00528
00529 Uint32 c0;
00530
00531
00532 int len = Text.size();
00533 for(int i = 0; i < len; i++) {
00534 int glyph_index;
00535 PG_GlyphCacheItem* Glyph;
00536 int OldBaseLineX = BaseLineX;
00537
00538 c0 = (PG_Char)(Text[i]);
00539
00540
00541 if (c0 < 32) {
00542 continue;
00543 }
00544
00545
00546 glyph_index = FT_Get_Char_Index(Face, c0);
00547
00548
00549 if ( FaceCache->Use_Kerning && previous && glyph_index ) {
00550 FT_Get_Kerning(Face, previous, glyph_index, ft_kerning_default, &delta );
00551 BaseLineX += delta.x >> 6;
00552 }
00553 previous = glyph_index;
00554
00555
00556 Glyph = GetGlyph(font, glyph_index);
00557
00558
00559 if (c0 != ' ') {
00560 BlitFTBitmap(Surface, &Glyph->Bitmap, BaseLineX + Glyph->Bitmap_left, BaseLineY - Glyph->Bitmap_top, font, ClipRect);
00561 }
00562
00563 BaseLineX += Glyph->Advance_x;
00564 if (font->GetStyle() & PG_Font::BOLD) {
00565 BaseLineX += FaceCache->Bold_Offset;
00566 }
00567
00568
00569
00570 if (font->GetStyle() & PG_Font::UNDERLINE) {
00571 SDL_Rect und_rect;
00572
00573 und_rect.x = OldBaseLineX;
00574 und_rect.y = BaseLineY;
00575 und_rect.h = FaceCache->Underline_Height;
00576 und_rect.w = BaseLineX - OldBaseLineX;
00577
00578 SDL_FillRect(
00579 Surface,
00580 &und_rect,
00581 font->GetColor().MapRGB(Surface->format)
00582 );
00583 }
00584 }
00585
00586
00587 if (font->GetStyle() & PG_Font::BOLD && !bRecursion) {
00588 bRecursion = true;
00589 RenderText(Surface, ClipRect, OriBaseX+1, BaseLineY, Text, font);
00590 bRecursion = false;
00591 }
00592
00593 if(SDL_MUSTLOCK(Surface)) {
00594 SDL_UnlockSurface(Surface);
00595 }
00596
00597 return true;
00598 }
00599
00600 bool PG_FontEngine::GetTextSize(const PG_String& Text, PG_Font* font, Uint16 *Width, Uint16 *Height, int *BaselineY, int *FontLineSkip, Uint16 *FontHeight, int *Ascent, int *Descent) {
00601 FT_UInt previous = 0;
00602 int BaseLineX = 0;
00603 int preBaseLineY = 0;
00604 int MaxY = 0;
00605
00606 Uint16 preFontHeight = 0;
00607 int preLineSkip = 0;
00608 int preAscent = 0;
00609 int preDescent = 0;
00610
00611 PG_FontFaceCacheItem* FaceCache = font->GetFaceCache();
00612
00613
00614 if (FaceCache == NULL) {
00615 return false;
00616 }
00617
00618 FT_Face Face = FaceCache->Face;
00619
00620
00621 if (FaceCache != NULL) {
00622 if (preFontHeight < FaceCache->Height)
00623 preFontHeight = FaceCache->Height;
00624 if (preLineSkip < FaceCache->LineSkip)
00625 preLineSkip = FaceCache->LineSkip;
00626 if (preAscent < FaceCache->Ascent)
00627 preAscent = FaceCache->Ascent;
00628 if (preDescent > FaceCache->Descent)
00629 preDescent = FaceCache->Descent;
00630 }
00631
00632
00633
00634 Uint32 c0;
00635
00636 int len = Text.size();
00637 for(int i = 0; i < len; i++) {
00638 int glyph_index;
00639 PG_GlyphCacheItem *Glyph;
00640
00641 c0 = Text[i];
00642
00643
00644 if (c0 < 32) {
00645 continue;
00646 }
00647
00648
00649 glyph_index = FT_Get_Char_Index(Face, c0);
00650
00651
00652 if ( FaceCache->Use_Kerning && previous && glyph_index ) {
00653 FT_Vector delta;
00654
00655 FT_Get_Kerning(Face, previous, glyph_index, ft_kerning_default, &delta );
00656 BaseLineX += delta.x >> 6;
00657 }
00658 previous = glyph_index;
00659
00660
00661 Glyph = GetGlyph(font, glyph_index);
00662
00663 if (preBaseLineY < Glyph->Bitmap_top) {
00664 preBaseLineY = Glyph->Bitmap_top;
00665 }
00666
00667 if (MaxY < Glyph->Bitmap.rows) {
00668 MaxY = Glyph->Bitmap.rows;
00669 }
00670
00671 BaseLineX += Glyph->Advance_x;
00672 if (font->GetStyle() & PG_Font::BOLD) {
00673 BaseLineX += FaceCache->Bold_Offset;
00674 }
00675
00676 }
00677
00678 if (Height != NULL)
00679 *Height = MaxY;
00680 if (Width != NULL)
00681 *Width = BaseLineX;
00682 if (BaselineY!= NULL)
00683 *BaselineY = preBaseLineY;
00684 if (FontLineSkip!= NULL)
00685 *FontLineSkip = preLineSkip;
00686 if (FontHeight != NULL)
00687 *FontHeight = preFontHeight;
00688 if (Ascent != NULL)
00689 *Ascent = preAscent;
00690 if (Descent != NULL)
00691 *Descent = preDescent;
00692
00693 return true;
00694 }
00695
00696 PG_FontFaceCacheItem* PG_FontEngine::LoadFontFace(const std::string& filename, FT_F26Dot6 fontsize, int index) {
00697
00698
00699 FONT_ITEM* item = my_fontcache[filename];
00700
00701
00702 if(item == NULL) {
00703
00704
00705 PG_DataContainer* data = PG_FileArchive::ReadFile(filename);
00706 if(!data) {
00707 return NULL;
00708 }
00709
00710
00711 item = new FONT_ITEM;
00712 item->name = filename;
00713 item->memdata = data;
00714
00715
00716 my_fontcache[filename] = item;
00717 }
00718
00719
00720 PG_FontFaceCacheItem* subitem = item->subitems[fontsize];
00721
00722
00723 if(subitem == NULL) {
00724 subitem = new PG_FontFaceCacheItem;
00725 subitem->fontsize = fontsize;
00726
00727
00728 FT_New_Memory_Face(my_library, (FT_Byte*)item->memdata->data(),
00729 item->memdata->size(), 0,
00730 &(subitem->Face));
00731
00732
00733 if (!FT_IS_SCALABLE(subitem->Face) ) {
00734 PG_LogWRN("Font %s is not scalable !", filename.c_str());
00735 delete subitem;
00736 return NULL;
00737 }
00738
00739
00740 FT_Set_Char_Size(subitem->Face, 0, fontsize*64, 0, 0);
00741
00742
00743 subitem->Bold_Offset = 1 + fontsize / 20;
00744 subitem->Underline_Height = FT_FLOOR(FT_MulFix(subitem->Face->underline_thickness, subitem->Face->size->metrics.y_scale));
00745 if ( subitem->Underline_Height < 1 ) {
00746 subitem->Underline_Height = 1;
00747 }
00748
00749 subitem->Ascent = FT_CEIL(FT_MulFix(subitem->Face->bbox.yMax, subitem->Face->size->metrics.y_scale));
00750 subitem->Descent = FT_CEIL(FT_MulFix(subitem->Face->bbox.yMin, subitem->Face->size->metrics.y_scale));
00751 subitem->Height = subitem->Ascent - subitem->Descent + 1;
00752 subitem->LineSkip = FT_CEIL(FT_MulFix(subitem->Face->height, subitem->Face->size->metrics.y_scale));
00753 subitem->Use_Kerning = FT_HAS_KERNING(subitem->Face);
00754
00755
00756 item->subitems[fontsize] = subitem;
00757 }
00758
00759 return subitem;
00760 }
00761
00762 PG_FontEngine::FONT_ITEM::~FONT_ITEM() {
00763 for(MAP_SUBITEMS::iterator i = subitems.begin(); i != subitems.end(); i++) {
00764 delete (*i).second;
00765 }
00766 delete memdata;
00767 }
00768
00769
00770
00771
00772
00773
00774
00775
00776