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
00030
00031
00032
00033 #include "mmsgui/fb/mmsfbfont.h"
00034 #include "mmsgui/fb/mmsfb.h"
00035
00036 #include "mmsgui/ft/mmsfttesselator.h"
00037
00038 #include <ft2build.h>
00039 #include FT_GLYPH_H
00040
00041 #include <math.h>
00042
00043
00044 pthread_mutex_t globalLock = PTHREAD_MUTEX_INITIALIZER;
00045 void *MMSFBFont::ft_library = NULL;
00046 unsigned int MMSFBFont::numReferences = 0;
00047
00048 MMSFBFont::MMSFBFONT_MAP MMSFBFont::index;
00049 unsigned int MMSFBFont::index_pos = 0;
00050
00051
00052 #define INITCHECK if(!this->isInitialized()){MMSFB_SetError(0,"MMSFBFont is not initialized");return false;}
00053
00054 MMSFBFont::MMSFBFont(string filename, int w, int h) :
00055 initialized(false),
00056 #ifdef __HAVE_DIRECTFB__
00057 dfbfont(NULL),
00058 #endif
00059 ft_face(NULL),
00060 filename(filename),
00061 ascender(0),
00062 descender(0),
00063 height(0) {
00064
00065
00066 pthread_mutex_lock(&globalLock);
00067 MMSFBFONT_MAP::iterator it = this->index.find(this->filename);
00068 if (it == this->index.end()) {
00069
00070 this->index_pos++;
00071 this->font_id = this->index_pos;
00072 this->index.insert(make_pair(this->filename, this->font_id));
00073 }
00074 else {
00075
00076 this->font_id = it->second;
00077 }
00078 pthread_mutex_unlock(&globalLock);
00079
00080
00081 if (mmsfb->backend == MMSFB_BE_DFB) {
00082 #ifdef __HAVE_DIRECTFB__
00083
00084
00085 DFBResult dfbres;
00086 DFBFontDescription desc;
00087 if (w > 0) {
00088 desc.flags = DFDESC_WIDTH;
00089 desc.width = w;
00090 }
00091 if (h > 0) {
00092 desc.flags = DFDESC_HEIGHT;
00093 desc.height = h;
00094 }
00095 if ((dfbres=mmsfb->dfb->CreateFont(mmsfb->dfb, this->filename.c_str(), &desc, (IDirectFBFont**)&this->dfbfont)) != DFB_OK) {
00096 MMSFB_SetError(dfbres, "IDirectFB::CreateFont(" + this->filename + ") failed");
00097 return;
00098 }
00099 this->initialized = true;
00100 #endif
00101 }
00102 else {
00103
00104 pthread_mutex_lock(&globalLock);
00105 if (!ft_library) {
00106 if (FT_Init_FreeType((FT_Library*)&this->ft_library)) {
00107 MMSFB_SetError(0, "FT_Init_FreeType() failed");
00108 this->ft_library = NULL;
00109 pthread_mutex_unlock(&globalLock);
00110 return;
00111 }
00112 }
00113
00114 this->numReferences++;
00115 pthread_mutex_unlock(&globalLock);
00116
00117
00118 if (FT_New_Face((FT_Library)this->ft_library, this->filename.c_str(), 0, (FT_Face*)&this->ft_face)) {
00119 this->ft_face = NULL;
00120 MMSFB_SetError(0, "FT_New_Face(" + this->filename + ") failed");
00121 return;
00122 }
00123
00124
00125 if (FT_Select_Charmap((FT_Face)this->ft_face, ft_encoding_unicode)) {
00126 FT_Done_Face((FT_Face)this->ft_face);
00127 this->ft_face = NULL;
00128 MMSFB_SetError(0, "FT_Select_Charmap(ft_encoding_unicode) for " + this->filename + " failed");
00129 return;
00130 }
00131
00132
00133 if (w < 0) w = 0;
00134 if (h < 0) h = 0;
00135
00136 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00137 if (mmsfb->bei) {
00138
00139 int rw = w;
00140 int rh = h;
00141 if (rw && rh) {
00142 float ratio = (float)rw / (float)rh;
00143 h = 200;
00144 w = h * ratio;
00145 if (w == h) w = 0;
00146 this->scale_coeff = (float)rh / (float)h;
00147 }
00148 else
00149 if (rh) {
00150 w = 0;
00151 h = 200;
00152 this->scale_coeff = (float)rh / (float)h;
00153 }
00154 else {
00155 w = 200;
00156 h = 0;
00157 this->scale_coeff = (float)rw / (float)w;
00158 }
00159
00160 }
00161 #endif
00162
00163
00164 if (FT_Set_Char_Size((FT_Face)this->ft_face, w << 6, h << 6, 0, 0)) {
00165 FT_Done_Face((FT_Face)this->ft_face);
00166 this->ft_face = NULL;
00167 MMSFB_SetError(0, "FT_Set_Char_Size(" + iToStr(w << 6) + "," + iToStr(h << 6) + ") for " + this->filename + " failed");
00168 return;
00169 }
00170
00171
00172 if (FT_Load_Glyph((FT_Face)this->ft_face, FT_Get_Char_Index((FT_Face)this->ft_face, '0'), FT_LOAD_RENDER)) {
00173 FT_Done_Face((FT_Face)this->ft_face);
00174 this->ft_face = NULL;
00175 MMSFB_SetError(0, "FT_Load_Glyph('0') for " + this->filename + " failed");
00176 return;
00177 }
00178
00179 if (((FT_Face)this->ft_face)->glyph->format != FT_GLYPH_FORMAT_BITMAP) {
00180 FT_Done_Face((FT_Face)this->ft_face);
00181 this->ft_face = NULL;
00182 MMSFB_SetError(0, "Glyph format is not FT_GLYPH_FORMAT_BITMAP for " + this->filename);
00183 return;
00184 }
00185
00186 this->ascender = ((FT_Face)this->ft_face)->size->metrics.ascender / 64;
00187 this->descender = abs(((FT_Face)this->ft_face)->size->metrics.descender / 64);
00188 this->height = this->ascender + this->descender + 1;
00189
00190
00191
00192
00193
00194
00195
00196 this->initialized = true;
00197 }
00198 }
00199
00200 MMSFBFont::~MMSFBFont() {
00201 lock();
00202
00203 for (std::map<unsigned int, MMSFBFont_Glyph>::iterator it = this->charmap.begin();
00204 it != this->charmap.end(); ++it) {
00205
00206 MMSFBFont_Glyph *glyph = &it->second;
00207
00208 if (glyph->buffer) {
00209 free(glyph->buffer);
00210 glyph->buffer = NULL;
00211 }
00212
00213 #ifdef __HAVE_OPENGL__
00214 #ifndef __HAVE_GLU__
00215
00216 if (mmsfb->bei)
00217 if (glyph->texture)
00218 mmsfb->bei->deleteTexture(glyph->texture);
00219 #else
00220
00221 if (glyph->meshes) {
00222 delete glyph->meshes;
00223 glyph->meshes = NULL;
00224 }
00225
00226
00227 if (glyph->outline) {
00228 delete glyph->outline;
00229 glyph->outline = NULL;
00230 }
00231 #endif
00232 #endif
00233
00234 }
00235 this->charmap.clear();
00236
00237 if(mmsfb->backend != MMSFB_BE_DFB) {
00238 if(this->ft_face) {
00239 FT_Done_Face((FT_Face)this->ft_face);
00240 this->ft_face = NULL;
00241 }
00242 }
00243
00244 unlock();
00245
00246 pthread_mutex_lock(&globalLock);
00247 this->numReferences--;
00248
00249 if(mmsfb->backend != MMSFB_BE_DFB) {
00250 if(this->ft_library && this->numReferences == 0) {
00251 FT_Done_FreeType((FT_Library)this->ft_library);
00252 this->ft_library = NULL;
00253 }
00254 }
00255
00256 pthread_mutex_unlock(&globalLock);
00257 }
00258
00259 bool MMSFBFont::isInitialized() {
00260 return this->initialized;
00261 }
00262
00263 void MMSFBFont::lock() {
00264 this->Lock.lock();
00265 }
00266
00267 void MMSFBFont::unlock() {
00268 this->Lock.unlock();
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 void *MMSFBFont::loadFTGlyph(unsigned int character) {
00320 FT_GlyphSlot g = NULL;
00321
00322
00323 if (!FT_Load_Glyph((FT_Face)this->ft_face,
00324 FT_Get_Char_Index((FT_Face)this->ft_face, (FT_ULong)character), FT_LOAD_DEFAULT
00325
00326
00327
00328
00329
00330 )) {
00331 g = ((FT_Face)this->ft_face)->glyph;
00332 } else {
00333 MMSFB_SetError(0, "FT_Load_Glyph(,,FT_LOAD_DEFAULT) failed for " + this->filename);
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 if (g) {
00348 #ifdef __HAVE_OPENGL__
00349 if (!mmsfb->bei) {
00350 #else
00351 if (1) {
00352 #endif
00353
00354 if (g->format != FT_GLYPH_FORMAT_BITMAP) {
00355 if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
00356
00357 MMSFB_SetError(0, "FT_Render_Glyph(,FT_RENDER_MODE_NORMAL) failed for " + this->filename);
00358 return NULL;
00359 }
00360 }
00361
00362 if (g->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY) {
00363
00364 MMSFB_SetError(0, "glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY for " + this->filename);
00365 return NULL;
00366 }
00367 }
00368 else {
00369 #ifndef __HAVE_GLU__
00370
00371 if (g->format != FT_GLYPH_FORMAT_BITMAP) {
00372 if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
00373
00374 MMSFB_SetError(0, "FT_Render_Glyph(,FT_RENDER_MODE_NORMAL) failed for " + this->filename);
00375 return NULL;
00376 }
00377 }
00378
00379 if (g->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY) {
00380
00381 MMSFB_SetError(0, "glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY for " + this->filename);
00382 return NULL;
00383 }
00384 #endif
00385 }
00386
00387
00388 return g;
00389 }
00390 else {
00391
00392 return NULL;
00393 }
00394 }
00395
00396
00397 bool MMSFBFont::setupFTGlyph(unsigned int character, void *ftg, MMSFBFont_Glyph *glyph) {
00398 if (!ftg || !glyph) return false;
00399 FT_GlyphSlot g = (FT_GlyphSlot)ftg;
00400
00401 glyph->character = character;
00402
00403 #ifdef __HAVE_OPENGL__
00404 if (!mmsfb->bei) {
00405 #else
00406 if (1) {
00407 #endif
00408
00409 glyph->left = g->bitmap_left;
00410 glyph->top = g->bitmap_top;
00411 glyph->width = g->bitmap.width;
00412 glyph->height = g->bitmap.rows;
00413 glyph->advanceX = g->advance.x / 64;
00414 glyph->pitch = g->bitmap.pitch;
00415
00416 #ifdef __HAVE_OPENGL__
00417 #ifdef __HAVE_GLU__
00418 glyph->meshes = NULL;
00419 glyph->outline = NULL;
00420 #else
00421 glyph->texture = 0;
00422 #endif
00423 #endif
00424 glyph->buffer = (unsigned char*)calloc(1, glyph->pitch * glyph->height);
00425 memcpy(glyph->buffer, g->bitmap.buffer, glyph->pitch * glyph->height);
00426
00427 if (MMSFBBase_rotate180) {
00428
00429 rotateUCharBuffer180(glyph->buffer, glyph->pitch, glyph->width, glyph->height);
00430 }
00431
00432 return true;
00433 }
00434
00435 #ifndef __HAVE_GLU__
00436 #ifdef __HAVE_OPENGL__
00437
00438 glyph->left = g->bitmap_left;
00439 glyph->top = g->bitmap_top;
00440 glyph->width = g->bitmap.width;
00441 glyph->height = g->bitmap.rows;
00442 glyph->advanceX = g->advance.x / 64;
00443
00444
00445
00446
00447
00448
00449 if (!g->bitmap.pitch) {
00450
00451 glyph->pitch = 0;
00452 glyph->buffer = NULL;
00453 glyph->texture = 0;
00454 return true;
00455 }
00456
00457
00458 if(mmsfb->bei && (g->bitmap.pitch & 3)) {
00459 glyph->pitch = (g->bitmap.pitch & ~3) + 4;
00460 glyph->buffer = (unsigned char*)calloc(1, glyph->pitch * glyph->height);
00461 unsigned char *src = g->bitmap.buffer;
00462 unsigned char *dst = glyph->buffer;
00463 for(int i = 0; i < glyph->height; i++) {
00464 memcpy(dst, src, g->bitmap.pitch);
00465 src += g->bitmap.pitch;
00466 dst += glyph->pitch;
00467 }
00468 }
00469 else {
00470 glyph->pitch = g->bitmap.pitch;
00471 glyph->buffer = (unsigned char*)calloc(1, glyph->pitch * glyph->height);
00472 memcpy(glyph->buffer, g->bitmap.buffer, glyph->pitch * glyph->height);
00473 }
00474
00475 if (MMSFBBase_rotate180) {
00476
00477 rotateUCharBuffer180(glyph->buffer, glyph->pitch, glyph->width, glyph->height);
00478 }
00479
00480
00481 glyph->texture = 0;
00482 mmsfb->bei->createAlphaTexture(&glyph->texture, glyph->buffer,
00483 glyph->pitch, glyph->height);
00484
00485 return true;
00486 #endif
00487
00488 #else
00489
00490
00491
00492 bool with_outline = true;
00493
00494
00495 glyph->buffer = NULL;
00496 glyph->pitch = 0;
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 glyph->left = g->metrics.horiBearingX / 64;
00507 glyph->top = g->metrics.horiBearingY / 64;
00508 glyph->width = g->metrics.width / 64;
00509 glyph->height = g->metrics.height / 64;
00510 glyph->advanceX = g->advance.x / 64;
00511
00512
00513
00514
00515
00516
00517
00518 glyph->meshes = NULL;
00519 glyph->outline = NULL;
00520
00521
00522 unsigned int subkey_mesh = glyph->character;
00523 glyph->meshes = new MMSFBBuffer(this->font_id, subkey_mesh);
00524
00525 if (!with_outline) {
00526
00527 if (glyph->meshes->isInitialized()) {
00528
00529
00530 return true;
00531 }
00532 }
00533 else {
00534
00535 unsigned int subkey_outline = 0x80000000 | glyph->character;
00536 glyph->outline = new MMSFBBuffer(this->font_id, subkey_outline);
00537
00538 if (glyph->meshes->isInitialized() && glyph->outline->isInitialized()) {
00539
00540
00541 return true;
00542 }
00543 }
00544
00545
00546 MMSFTTesselator *ftv = new MMSFTTesselator(g);
00547
00548 if (!glyph->meshes->isInitialized()) {
00549
00550
00551 ftv->generateGlyph();
00552 const MMSFTGlyph *ftglyph = ftv->getGlyph();
00553 if (!ftglyph) {
00554
00555 MMSFB_SetError(0, "MMSFTTesselator::generateGlyph() failed");
00556 delete ftv;
00557 return false;
00558 }
00559
00560 if (!ftglyph->getMeshCount()) {
00561
00562 delete ftv;
00563 return true;
00564 }
00565
00566
00567 unsigned short int max_meshes = 0;
00568 for (unsigned int m = 0; m < ftglyph->getMeshCount(); m++) {
00569 if (!ftglyph->getMesh(m)) continue;
00570 max_meshes++;
00571 if (max_meshes >= MMSFBFONT_GLYPH_MAX_MESHES) {
00572 printf("MMSFBFONT_GLYPH_MAX_MESHES(%u) reached, %u needed\n", MMSFBFONT_GLYPH_MAX_MESHES, ftglyph->getMeshCount());
00573 }
00574 }
00575
00576 if (!max_meshes) {
00577
00578 MMSFB_SetError(0, "no meshes available");
00579 delete ftv;
00580 return false;
00581 }
00582
00583
00584
00585 MMSFBBuffer::INDEX_BUFFER index_buffer;
00586 MMSFBBuffer::VERTEX_BUFFER vertex_buffer;
00587 index_buffer.num_arrays = 0;
00588 index_buffer.max_arrays = max_meshes;
00589 index_buffer.arrays = (MMS_INDEX_ARRAY*)malloc(sizeof(MMS_INDEX_ARRAY) * index_buffer.max_arrays);
00590 vertex_buffer.num_arrays = 0;
00591 vertex_buffer.max_arrays = max_meshes;
00592 vertex_buffer.arrays = (MMS_VERTEX_ARRAY*)malloc(sizeof(MMS_VERTEX_ARRAY) * vertex_buffer.max_arrays);
00593
00594
00595 for (unsigned int m = 0; m < ftglyph->getMeshCount(); m++) {
00596
00597 if (index_buffer.num_arrays >= max_meshes) {
00598 printf("max_meshes(%u) reached\n", max_meshes);
00599 break;
00600 }
00601 MMS_INDEX_ARRAY *indices = &index_buffer.arrays[index_buffer.num_arrays];
00602 MMS_VERTEX_ARRAY *vertices = &vertex_buffer.arrays[vertex_buffer.num_arrays];
00603
00604
00605 const MMSFTMesh *ftmesh = ftglyph->getMesh(m);
00606 if (!ftmesh) continue;
00607
00608
00609
00610 switch (ftmesh->getMeshType()) {
00611 case GL_TRIANGLES:
00612 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLES);
00613 break;
00614 case GL_TRIANGLE_STRIP:
00615 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLE_STRIP);
00616 break;
00617 case GL_TRIANGLE_FAN:
00618 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLE_FAN);
00619 break;
00620 default:
00621
00622 printf("MMSFBFont: unsupported mesh type %u\n", ftmesh->getMeshType());
00623 delete ftv;
00624 return false;
00625 }
00626
00627 #ifndef __HAVE_OGL_HALF_FLOAT__
00628
00629 initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
00630 #else
00631
00632 initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
00633 #endif
00634
00635 for (unsigned int v = 0; v < ftmesh->getVertexCount(); v++) {
00636 const MMSFTVertex &vertex = ftmesh->getVertex(v);
00637 MMS_VA_SET_VERTEX_2v(vertices, v,
00638 (float)(vertex.X() - g->metrics.horiBearingX) / 64,
00639 (float)(g->metrics.horiBearingY - vertex.Y()) / 64);
00640 }
00641
00642
00643 index_buffer.num_arrays++;
00644 vertex_buffer.num_arrays++;
00645 }
00646
00647 glyph->meshes->initBuffer(index_buffer, vertex_buffer);
00648 }
00649
00650 if (with_outline && ftv->getContourCount() > 0) {
00651 if (!glyph->outline->isInitialized()) {
00652
00653
00654
00655 unsigned short int max_outlines = ftv->getContourCount();
00656
00657
00658
00659 MMSFBBuffer::INDEX_BUFFER index_buffer;
00660 MMSFBBuffer::VERTEX_BUFFER vertex_buffer;
00661 index_buffer.num_arrays = 0;
00662 index_buffer.max_arrays = max_outlines;
00663 index_buffer.arrays = (MMS_INDEX_ARRAY*)malloc(sizeof(MMS_INDEX_ARRAY) * index_buffer.max_arrays);
00664 vertex_buffer.num_arrays = 0;
00665 vertex_buffer.max_arrays = max_outlines;
00666 vertex_buffer.arrays = (MMS_VERTEX_ARRAY*)malloc(sizeof(MMS_VERTEX_ARRAY) * vertex_buffer.max_arrays);
00667
00668
00669 for (unsigned int c = 0; c < ftv->getContourCount(); c++) {
00670
00671 if (index_buffer.num_arrays >= max_outlines) {
00672 printf("max_outlines(%u) reached\n", max_outlines);
00673 break;
00674 }
00675 MMS_INDEX_ARRAY *indices = &index_buffer.arrays[index_buffer.num_arrays];
00676 MMS_VERTEX_ARRAY *vertices = &vertex_buffer.arrays[vertex_buffer.num_arrays];
00677
00678
00679 const MMSFTContour *ftcontour = ftv->getContour(c);
00680 if (!ftcontour) continue;
00681
00682
00683
00684 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_LINE_LOOP);
00685
00686 #ifndef __HAVE_OGL_HALF_FLOAT__
00687
00688 initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
00689 #else
00690
00691 initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
00692 #endif
00693
00694 for (unsigned int v = 0; v < ftcontour->getVertexCount(); v++) {
00695 const MMSFTVertex &vertex = ftcontour->Vertex(v);
00696 MMS_VA_SET_VERTEX_2v(vertices, v,
00697 (float)(vertex.X() - g->metrics.horiBearingX) / 64,
00698 (float)(g->metrics.horiBearingY - vertex.Y()) / 64);
00699 }
00700
00701
00702 index_buffer.num_arrays++;
00703 vertex_buffer.num_arrays++;
00704 }
00705
00706 glyph->outline->initBuffer(index_buffer, vertex_buffer);
00707 }
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 delete ftv;
00800 return true;
00801
00802 #endif
00803
00804 return false;
00805 }
00806
00807 bool MMSFBFont::getGlyph(unsigned int character, MMSFBFont_Glyph *glyph) {
00808 if (!glyph) {
00809 return false;
00810 }
00811
00812 if (mmsfb->backend == MMSFB_BE_DFB) {
00813 #ifdef __HAVE_DIRECTFB__
00814 #endif
00815 }
00816 else {
00817 if(!this->ft_face) {
00818 return false;
00819 }
00820
00821 bool ret = false;
00822
00823 lock();
00824
00825
00826 std::map<unsigned int, MMSFBFont_Glyph>::iterator it;
00827 it = this->charmap.find(character);
00828 if (it == this->charmap.end()) {
00829
00830 FT_GlyphSlot g;
00831 if (!(g = (FT_GlyphSlot)loadFTGlyph(character))) {
00832
00833 unlock();
00834 return false;
00835 }
00836
00837
00838 if (!setupFTGlyph(character, g, glyph)) {
00839
00840 unlock();
00841 return false;
00842 }
00843
00844
00845 this->charmap.insert(std::make_pair(character, *glyph));
00846 ret = true;
00847 }
00848 else {
00849
00850 *glyph = it->second;
00851 ret = true;
00852 }
00853
00854 unlock();
00855
00856 return ret;
00857 }
00858
00859 return false;
00860 }
00861
00862
00863 bool MMSFBFont::getStringWidth(string text, int len, int *width) {
00864
00865 INITCHECK;
00866
00867
00868 if (!width) return false;
00869 *width = 0;
00870
00871
00872 if (len < 0) len = text.size();
00873 if (!len) return true;
00874
00875
00876 #ifdef __HAVE_DIRECTFB__
00877 if (this->dfbfont) {
00878 if (((IDirectFBFont*)this->dfbfont)->GetStringWidth((IDirectFBFont*)this->dfbfont, text.c_str(), len, width) != DFB_OK)
00879 return false;
00880 return true;
00881 } else
00882 #endif
00883 {
00884 MMSFBFONT_GET_UNICODE_CHAR(text, len) {
00885 MMSFBFont_Glyph glyph;
00886 if (!getGlyph(character, &glyph)) break;
00887
00888 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00889 if (mmsfb->bei) {
00890
00891 (*width)+= (int)((float)glyph.advanceX * this->scale_coeff + 0.5f);
00892 }
00893 else
00894 #endif
00895 (*width)+= glyph.advanceX;
00896 } }
00897 return true;
00898 }
00899 return false;
00900 }
00901
00902 bool MMSFBFont::getHeight(int *height) {
00903
00904 INITCHECK;
00905
00906
00907 #ifdef __HAVE_DIRECTFB__
00908 if (this->dfbfont) {
00909 if (((IDirectFBFont*)this->dfbfont)->GetHeight((IDirectFBFont*)this->dfbfont, height) != DFB_OK)
00910 return false;
00911 return true;
00912 } else
00913 #endif
00914 {
00915 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00916 if (mmsfb->bei) {
00917
00918 int asc = (int)((float)this->ascender * this->scale_coeff + 0.5f);
00919 int des = (int)((float)this->descender * this->scale_coeff + 0.5f);
00920 *height = asc + des + 1;
00921 }
00922 else
00923 #endif
00924 *height = this->height;
00925
00926 return true;
00927 }
00928 return false;
00929 }
00930
00931 bool MMSFBFont::getAscender(int *ascender) {
00932
00933 INITCHECK;
00934
00935
00936 #ifdef __HAVE_DIRECTFB__
00937 if (this->dfbfont) {
00938 } else
00939 #endif
00940 {
00941 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00942 if (mmsfb->bei) {
00943
00944 *ascender = (int)((float)this->ascender * this->scale_coeff + 0.5f);
00945 }
00946 else
00947 #endif
00948 *ascender = this->ascender;
00949
00950 return true;
00951 }
00952 return false;
00953 }
00954
00955 bool MMSFBFont::getDescender(int *descender) {
00956
00957 INITCHECK;
00958
00959
00960 #ifdef __HAVE_DIRECTFB__
00961 if (this->dfbfont) {
00962 }
00963 else
00964 #endif
00965 {
00966 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00967 if (mmsfb->bei) {
00968
00969 *descender = (int)((float)this->descender * this->scale_coeff + 0.5f);
00970 }
00971 else
00972 #endif
00973 *descender = this->descender;
00974
00975 return true;
00976 }
00977 return false;
00978 }
00979
00980 bool MMSFBFont::getScaleCoeff(float *scale_coeff) {
00981
00982 INITCHECK;
00983
00984 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00985 if (mmsfb->bei) {
00986 *scale_coeff = this->scale_coeff;
00987 return true;
00988 }
00989 #endif
00990
00991 return false;
00992 }
00993
00994
00995
00996
00997