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 pthread_mutex_unlock(&globalLock);
00256 }
00257
00258 bool MMSFBFont::isInitialized() {
00259 return this->initialized;
00260 }
00261
00262 void MMSFBFont::lock() {
00263 this->Lock.lock();
00264 }
00265
00266 void MMSFBFont::unlock() {
00267 this->Lock.unlock();
00268 }
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 void *MMSFBFont::loadFTGlyph(unsigned int character) {
00319 FT_GlyphSlot g = NULL;
00320
00321
00322 if (!FT_Load_Glyph((FT_Face)this->ft_face,
00323 FT_Get_Char_Index((FT_Face)this->ft_face, (FT_ULong)character), FT_LOAD_DEFAULT
00324
00325
00326
00327
00328
00329 )) {
00330 g = ((FT_Face)this->ft_face)->glyph;
00331 } else {
00332 MMSFB_SetError(0, "FT_Load_Glyph(,,FT_LOAD_DEFAULT) failed for " + this->filename);
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 if (g) {
00347 #ifdef __HAVE_OPENGL__
00348 if (!mmsfb->bei) {
00349 #else
00350 if (1) {
00351 #endif
00352
00353 if (g->format != FT_GLYPH_FORMAT_BITMAP) {
00354 if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
00355
00356 MMSFB_SetError(0, "FT_Render_Glyph(,FT_RENDER_MODE_NORMAL) failed for " + this->filename);
00357 return NULL;
00358 }
00359 }
00360
00361 if (g->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY) {
00362
00363 MMSFB_SetError(0, "glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY for " + this->filename);
00364 return NULL;
00365 }
00366 }
00367 else {
00368 #ifndef __HAVE_GLU__
00369
00370 if (g->format != FT_GLYPH_FORMAT_BITMAP) {
00371 if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
00372
00373 MMSFB_SetError(0, "FT_Render_Glyph(,FT_RENDER_MODE_NORMAL) failed for " + this->filename);
00374 return NULL;
00375 }
00376 }
00377
00378 if (g->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY) {
00379
00380 MMSFB_SetError(0, "glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY for " + this->filename);
00381 return NULL;
00382 }
00383 #endif
00384 }
00385
00386
00387 return g;
00388 }
00389 else {
00390
00391 return NULL;
00392 }
00393 }
00394
00395
00396 bool MMSFBFont::setupFTGlyph(unsigned int character, void *ftg, MMSFBFont_Glyph *glyph) {
00397 if (!ftg || !glyph) return false;
00398 FT_GlyphSlot g = (FT_GlyphSlot)ftg;
00399
00400 glyph->character = character;
00401
00402 #ifdef __HAVE_OPENGL__
00403 if (!mmsfb->bei) {
00404 #else
00405 if (1) {
00406 #endif
00407
00408 glyph->left = g->bitmap_left;
00409 glyph->top = g->bitmap_top;
00410 glyph->width = g->bitmap.width;
00411 glyph->height = g->bitmap.rows;
00412 glyph->advanceX = g->advance.x / 64;
00413 glyph->pitch = g->bitmap.pitch;
00414
00415 #ifdef __HAVE_OPENGL__
00416 #ifdef __HAVE_GLU__
00417 glyph->meshes = NULL;
00418 glyph->outline = NULL;
00419 #else
00420 glyph->texture = 0;
00421 #endif
00422 #endif
00423 glyph->buffer = (unsigned char*)calloc(1, glyph->pitch * glyph->height);
00424 memcpy(glyph->buffer, g->bitmap.buffer, glyph->pitch * glyph->height);
00425
00426 if (MMSFBBase_rotate180) {
00427
00428 rotateUCharBuffer180(glyph->buffer, glyph->pitch, glyph->width, glyph->height);
00429 }
00430
00431 return true;
00432 }
00433
00434 #ifndef __HAVE_GLU__
00435 #ifdef __HAVE_OPENGL__
00436
00437 glyph->left = g->bitmap_left;
00438 glyph->top = g->bitmap_top;
00439 glyph->width = g->bitmap.width;
00440 glyph->height = g->bitmap.rows;
00441 glyph->advanceX = g->advance.x / 64;
00442
00443
00444
00445
00446
00447
00448 if (!g->bitmap.pitch) {
00449
00450 glyph->pitch = 0;
00451 glyph->buffer = NULL;
00452 glyph->texture = 0;
00453 return true;
00454 }
00455
00456
00457 if(mmsfb->bei && (g->bitmap.pitch & 3)) {
00458 glyph->pitch = (g->bitmap.pitch & ~3) + 4;
00459 glyph->buffer = (unsigned char*)calloc(1, glyph->pitch * glyph->height);
00460 unsigned char *src = g->bitmap.buffer;
00461 unsigned char *dst = glyph->buffer;
00462 for(int i = 0; i < glyph->height; i++) {
00463 memcpy(dst, src, glyph->pitch);
00464 src += g->bitmap.pitch;
00465 dst += glyph->pitch;
00466 }
00467 }
00468 else {
00469 glyph->pitch = g->bitmap.pitch;
00470 glyph->buffer = (unsigned char*)calloc(1, glyph->pitch * glyph->height);
00471 memcpy(glyph->buffer, g->bitmap.buffer, glyph->pitch * glyph->height);
00472 }
00473
00474 if (MMSFBBase_rotate180) {
00475
00476 rotateUCharBuffer180(glyph->buffer, glyph->pitch, glyph->width, glyph->height);
00477 }
00478
00479
00480 glyph->texture = 0;
00481 mmsfb->bei->createAlphaTexture(&glyph->texture, glyph->buffer,
00482 glyph->pitch, glyph->height);
00483
00484 return true;
00485 #endif
00486
00487 #else
00488
00489
00490
00491 bool with_outline = true;
00492
00493
00494 glyph->buffer = NULL;
00495 glyph->pitch = 0;
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 glyph->left = g->metrics.horiBearingX / 64;
00506 glyph->top = g->metrics.horiBearingY / 64;
00507 glyph->width = g->metrics.width / 64;
00508 glyph->height = g->metrics.height / 64;
00509 glyph->advanceX = g->advance.x / 64;
00510
00511
00512
00513
00514
00515
00516
00517 glyph->meshes = NULL;
00518 glyph->outline = NULL;
00519
00520
00521 unsigned int subkey_mesh = glyph->character;
00522 glyph->meshes = new MMSFBBuffer(this->font_id, subkey_mesh);
00523
00524 if (!with_outline) {
00525
00526 if (glyph->meshes->isInitialized()) {
00527
00528
00529 return true;
00530 }
00531 }
00532 else {
00533
00534 unsigned int subkey_outline = 0x80000000 | glyph->character;
00535 glyph->outline = new MMSFBBuffer(this->font_id, subkey_outline);
00536
00537 if (glyph->meshes->isInitialized() && glyph->outline->isInitialized()) {
00538
00539
00540 return true;
00541 }
00542 }
00543
00544
00545 MMSFTTesselator *ftv = new MMSFTTesselator(g);
00546
00547 if (!glyph->meshes->isInitialized()) {
00548
00549
00550 ftv->generateGlyph();
00551 const MMSFTGlyph *ftglyph = ftv->getGlyph();
00552 if (!ftglyph) {
00553
00554 MMSFB_SetError(0, "MMSFTTesselator::generateGlyph() failed");
00555 delete ftv;
00556 return false;
00557 }
00558
00559 if (!ftglyph->getMeshCount()) {
00560
00561 delete ftv;
00562 return true;
00563 }
00564
00565
00566 unsigned short int max_meshes = 0;
00567 for (unsigned int m = 0; m < ftglyph->getMeshCount(); m++) {
00568 if (!ftglyph->getMesh(m)) continue;
00569 max_meshes++;
00570 if (max_meshes >= MMSFBFONT_GLYPH_MAX_MESHES) {
00571 printf("MMSFBFONT_GLYPH_MAX_MESHES(%u) reached, %u needed\n", MMSFBFONT_GLYPH_MAX_MESHES, ftglyph->getMeshCount());
00572 }
00573 }
00574
00575 if (!max_meshes) {
00576
00577 MMSFB_SetError(0, "no meshes available");
00578 delete ftv;
00579 return false;
00580 }
00581
00582
00583
00584 MMSFBBuffer::INDEX_BUFFER index_buffer;
00585 MMSFBBuffer::VERTEX_BUFFER vertex_buffer;
00586 index_buffer.num_arrays = 0;
00587 index_buffer.max_arrays = max_meshes;
00588 index_buffer.arrays = (MMS_INDEX_ARRAY*)malloc(sizeof(MMS_INDEX_ARRAY) * index_buffer.max_arrays);
00589 vertex_buffer.num_arrays = 0;
00590 vertex_buffer.max_arrays = max_meshes;
00591 vertex_buffer.arrays = (MMS_VERTEX_ARRAY*)malloc(sizeof(MMS_VERTEX_ARRAY) * vertex_buffer.max_arrays);
00592
00593
00594 for (unsigned int m = 0; m < ftglyph->getMeshCount(); m++) {
00595
00596 if (index_buffer.num_arrays >= max_meshes) {
00597 printf("max_meshes(%u) reached\n", max_meshes);
00598 break;
00599 }
00600 MMS_INDEX_ARRAY *indices = &index_buffer.arrays[index_buffer.num_arrays];
00601 MMS_VERTEX_ARRAY *vertices = &vertex_buffer.arrays[vertex_buffer.num_arrays];
00602
00603
00604 const MMSFTMesh *ftmesh = ftglyph->getMesh(m);
00605 if (!ftmesh) continue;
00606
00607
00608
00609 switch (ftmesh->getMeshType()) {
00610 case GL_TRIANGLES:
00611 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLES);
00612 break;
00613 case GL_TRIANGLE_STRIP:
00614 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLE_STRIP);
00615 break;
00616 case GL_TRIANGLE_FAN:
00617 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLE_FAN);
00618 break;
00619 default:
00620
00621 printf("MMSFBFont: unsupported mesh type %u\n", ftmesh->getMeshType());
00622 delete ftv;
00623 return false;
00624 }
00625
00626 #ifndef __HAVE_OGL_HALF_FLOAT__
00627
00628 initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
00629 #else
00630
00631 initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
00632 #endif
00633
00634 for (unsigned int v = 0; v < ftmesh->getVertexCount(); v++) {
00635 const MMSFTVertex &vertex = ftmesh->getVertex(v);
00636 MMS_VA_SET_VERTEX_2v(vertices, v,
00637 (float)(vertex.X() - g->metrics.horiBearingX) / 64,
00638 (float)(g->metrics.horiBearingY - vertex.Y()) / 64);
00639 }
00640
00641
00642 index_buffer.num_arrays++;
00643 vertex_buffer.num_arrays++;
00644 }
00645
00646 glyph->meshes->initBuffer(index_buffer, vertex_buffer);
00647 }
00648
00649 if (with_outline && ftv->getContourCount() > 0) {
00650 if (!glyph->outline->isInitialized()) {
00651
00652
00653
00654 unsigned short int max_outlines = ftv->getContourCount();
00655
00656
00657
00658 MMSFBBuffer::INDEX_BUFFER index_buffer;
00659 MMSFBBuffer::VERTEX_BUFFER vertex_buffer;
00660 index_buffer.num_arrays = 0;
00661 index_buffer.max_arrays = max_outlines;
00662 index_buffer.arrays = (MMS_INDEX_ARRAY*)malloc(sizeof(MMS_INDEX_ARRAY) * index_buffer.max_arrays);
00663 vertex_buffer.num_arrays = 0;
00664 vertex_buffer.max_arrays = max_outlines;
00665 vertex_buffer.arrays = (MMS_VERTEX_ARRAY*)malloc(sizeof(MMS_VERTEX_ARRAY) * vertex_buffer.max_arrays);
00666
00667
00668 for (unsigned int c = 0; c < ftv->getContourCount(); c++) {
00669
00670 if (index_buffer.num_arrays >= max_outlines) {
00671 printf("max_outlines(%u) reached\n", max_outlines);
00672 break;
00673 }
00674 MMS_INDEX_ARRAY *indices = &index_buffer.arrays[index_buffer.num_arrays];
00675 MMS_VERTEX_ARRAY *vertices = &vertex_buffer.arrays[vertex_buffer.num_arrays];
00676
00677
00678 const MMSFTContour *ftcontour = ftv->getContour(c);
00679 if (!ftcontour) continue;
00680
00681
00682
00683 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_LINE_LOOP);
00684
00685 #ifndef __HAVE_OGL_HALF_FLOAT__
00686
00687 initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
00688 #else
00689
00690 initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
00691 #endif
00692
00693 for (unsigned int v = 0; v < ftcontour->getVertexCount(); v++) {
00694 const MMSFTVertex &vertex = ftcontour->Vertex(v);
00695 MMS_VA_SET_VERTEX_2v(vertices, v,
00696 (float)(vertex.X() - g->metrics.horiBearingX) / 64,
00697 (float)(g->metrics.horiBearingY - vertex.Y()) / 64);
00698 }
00699
00700
00701 index_buffer.num_arrays++;
00702 vertex_buffer.num_arrays++;
00703 }
00704
00705 glyph->outline->initBuffer(index_buffer, vertex_buffer);
00706 }
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 delete ftv;
00799 return true;
00800
00801 #endif
00802
00803 return false;
00804 }
00805
00806 bool MMSFBFont::getGlyph(unsigned int character, MMSFBFont_Glyph *glyph) {
00807 if (!glyph) {
00808 return false;
00809 }
00810
00811 if (mmsfb->backend == MMSFB_BE_DFB) {
00812 #ifdef __HAVE_DIRECTFB__
00813 #endif
00814 }
00815 else {
00816 if(!this->ft_face) {
00817 return false;
00818 }
00819
00820 bool ret = false;
00821
00822 lock();
00823
00824
00825 std::map<unsigned int, MMSFBFont_Glyph>::iterator it;
00826 it = this->charmap.find(character);
00827 if (it == this->charmap.end()) {
00828
00829 FT_GlyphSlot g;
00830 if (!(g = (FT_GlyphSlot)loadFTGlyph(character))) {
00831
00832 unlock();
00833 return false;
00834 }
00835
00836
00837 if (!setupFTGlyph(character, g, glyph)) {
00838
00839 unlock();
00840 return false;
00841 }
00842
00843
00844 this->charmap.insert(std::make_pair(character, *glyph));
00845 ret = true;
00846 }
00847 else {
00848
00849 *glyph = it->second;
00850 ret = true;
00851 }
00852
00853 unlock();
00854
00855 return ret;
00856 }
00857
00858 return false;
00859 }
00860
00861
00862 bool MMSFBFont::getStringWidth(string text, int len, int *width) {
00863
00864 INITCHECK;
00865
00866
00867 if (!width) return false;
00868 *width = 0;
00869
00870
00871 if (len < 0) len = text.size();
00872 if (!len) return true;
00873
00874
00875 #ifdef __HAVE_DIRECTFB__
00876 if (this->dfbfont) {
00877 if (((IDirectFBFont*)this->dfbfont)->GetStringWidth((IDirectFBFont*)this->dfbfont, text.c_str(), len, width) != DFB_OK)
00878 return false;
00879 return true;
00880 } else
00881 #endif
00882 {
00883 MMSFBFONT_GET_UNICODE_CHAR(text, len) {
00884 MMSFBFont_Glyph glyph;
00885 if (!getGlyph(character, &glyph)) break;
00886
00887 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00888 if (mmsfb->bei) {
00889
00890 (*width)+= (int)((float)glyph.advanceX * this->scale_coeff + 0.5f);
00891 }
00892 else
00893 #endif
00894 (*width)+= glyph.advanceX;
00895 } }
00896 return true;
00897 }
00898 return false;
00899 }
00900
00901 bool MMSFBFont::getHeight(int *height) {
00902
00903 INITCHECK;
00904
00905
00906 #ifdef __HAVE_DIRECTFB__
00907 if (this->dfbfont) {
00908 if (((IDirectFBFont*)this->dfbfont)->GetHeight((IDirectFBFont*)this->dfbfont, height) != DFB_OK)
00909 return false;
00910 return true;
00911 } else
00912 #endif
00913 {
00914 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00915 if (mmsfb->bei) {
00916
00917 int asc = (int)((float)this->ascender * this->scale_coeff + 0.5f);
00918 int des = (int)((float)this->descender * this->scale_coeff + 0.5f);
00919 *height = asc + des + 1;
00920 }
00921 else
00922 #endif
00923 *height = this->height;
00924
00925 return true;
00926 }
00927 return false;
00928 }
00929
00930 bool MMSFBFont::getAscender(int *ascender) {
00931
00932 INITCHECK;
00933
00934
00935 #ifdef __HAVE_DIRECTFB__
00936 if (this->dfbfont) {
00937 } else
00938 #endif
00939 {
00940 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00941 if (mmsfb->bei) {
00942
00943 *ascender = (int)((float)this->ascender * this->scale_coeff + 0.5f);
00944 }
00945 else
00946 #endif
00947 *ascender = this->ascender;
00948
00949 return true;
00950 }
00951 return false;
00952 }
00953
00954 bool MMSFBFont::getDescender(int *descender) {
00955
00956 INITCHECK;
00957
00958
00959 #ifdef __HAVE_DIRECTFB__
00960 if (this->dfbfont) {
00961 }
00962 else
00963 #endif
00964 {
00965 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00966 if (mmsfb->bei) {
00967
00968 *descender = (int)((float)this->descender * this->scale_coeff + 0.5f);
00969 }
00970 else
00971 #endif
00972 *descender = this->descender;
00973
00974 return true;
00975 }
00976 return false;
00977 }
00978
00979 bool MMSFBFont::getScaleCoeff(float *scale_coeff) {
00980
00981 INITCHECK;
00982
00983 #if (defined(__HAVE_OPENGL__) && defined(__HAVE_GLU__))
00984 if (mmsfb->bei) {
00985 *scale_coeff = this->scale_coeff;
00986 return true;
00987 }
00988 #endif
00989
00990 return false;
00991 }
00992
00993
00994
00995
00996