Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsfbfont.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
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 // static variables
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     // get index
00066     pthread_mutex_lock(&globalLock);
00067     MMSFBFONT_MAP::iterator it = this->index.find(this->filename);
00068     if (it == this->index.end()) {
00069         // new id
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         // use existing id
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         // create the dfb font
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         // init freetype library
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         // load the face
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         // select the charmap
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         // check requested width and height
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             // we create base meshes and scale up/down to glyph's destination size
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 //          printf("coeff = %f\n", this->scale_coeff);
00160         }
00161 #endif
00162 
00163         // set the font size
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         // try to load a first glyph
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 printf("asc = %d\n", this->ascender);
00192 printf("des = %d\n", this->descender);
00193 printf("height = %d\n", this->height);
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         // release texture
00216         if (mmsfb->bei)
00217             if (glyph->texture)
00218                 mmsfb->bei->deleteTexture(glyph->texture);
00219 #else
00220         // release mesh memory
00221         if (glyph->meshes) {
00222             delete glyph->meshes;
00223             glyph->meshes = NULL;
00224         }
00225 
00226         // release outline memory
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 void showGlyphAttributes(FT_GlyphSlot glyph) {
00271     FT_Glyph_Metrics *metrics = &glyph->metrics;
00272     FT_Bitmap  *bitmap = &glyph->bitmap;
00273     FT_Outline *outline = &glyph->outline;
00274 
00275     printf("glyph***\n");
00276 
00277     printf("format = %d\n", glyph->format);
00278 
00279     printf("metrics***\n");
00280     printf("  width        = %d, %.02f\n", metrics->width, (float)metrics->width / 64);
00281     printf("  height       = %d, %.02f\n", metrics->height, (float)metrics->height / 64);
00282     printf("  horiBearingX = %d, %.02f\n", metrics->horiBearingX, (float)metrics->horiBearingX / 64);
00283     printf("  horiBearingY = %d, %.02f\n", metrics->horiBearingY, (float)metrics->horiBearingY / 64);
00284     printf("  horiAdvance  = %d, %.02f\n", metrics->horiAdvance, (float)metrics->horiAdvance / 64);
00285     printf("  vertBearingX = %d, %.02f\n", metrics->vertBearingX, (float)metrics->vertBearingX / 64);
00286     printf("  vertBearingY = %d, %.02f\n", metrics->vertBearingY, (float)metrics->vertBearingY / 64);
00287     printf("  vertAdvance  = %d, %.02f\n", metrics->vertAdvance, (float)metrics->vertAdvance / 64);
00288     printf("***metrics\n");
00289 
00290     printf("advance.x    = %d, %.02f\n", glyph->advance.x, (float)glyph->advance.x / 64);
00291     printf("advance.y    = %d, %.02f\n", glyph->advance.y, (float)glyph->advance.y / 64);
00292 
00293     printf("bitmap***\n");
00294     printf("  pitch  = %d\n", bitmap->pitch);
00295     printf("  width  = %d\n", bitmap->width);
00296     printf("  height = %d\n", bitmap->rows);
00297     printf("***bitmap\n");
00298     printf("bitmap_left = %d\n", glyph->bitmap_left);
00299     printf("bitmap_top  = %d\n", glyph->bitmap_top);
00300 
00301     printf("outline***\n");
00302     printf("  n_contours = %d\n", outline->n_contours);
00303     printf("  n_points   = %d\n", outline->n_points);
00304     for (int i = 0; i < outline->n_points; i++) {
00305         printf("    %d, %d\n   >%.02f, %.02f\n", outline->points[i].x, outline->points[i].y,
00306                                               (float)outline->points[i].x / 64, (float)outline->points[i].y / 64);
00307     }
00308     printf("  flags = %d\n", outline->flags);
00309     printf("***outline\n");
00310 
00311     printf("lsb_delta    = %d\n", glyph->lsb_delta);
00312     printf("rsb_delta    = %d\n", glyph->rsb_delta);
00313 
00314     printf("***glyph\n");
00315 }
00316 */
00317 
00318 void *MMSFBFont::loadFTGlyph(unsigned int character) {
00319     FT_GlyphSlot g = NULL;
00320 
00321     // load glyph but do NOT render a bitmap
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 //          FT_Get_Char_Index((FT_Face)this->ft_face, (FT_ULong)character), FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT
00325 //      | FT_LOAD_TARGET_LIGHT
00326 //      | FT_LOAD_TARGET_MONO
00327 //      | FT_LOAD_TARGET_LCD
00328 //      | FT_LOAD_TARGET_LCD_V
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 /*TEST CODE
00336     if (!FT_Load_Glyph((FT_Face)this->ft_face,
00337         FT_Get_Char_Index((FT_Face)this->ft_face, (FT_ULong)character), FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT)) {
00338         g = ((FT_Face)this->ft_face)->glyph;
00339     } else {
00340         MMSFB_SetError(0, "FT_Load_Glyph(,,FT_LOAD_RENDER) failed for " + this->filename);
00341     }
00342     showGlyphAttributes(g);
00343     exit(0);
00344 */
00345 
00346     if (g) {
00347 #ifdef __HAVE_OPENGL__
00348         if (!mmsfb->bei) {
00349 #else
00350         if (1) {
00351 #endif
00352             // OpenGL is not initialized, we need a bitmap from freetype
00353             if (g->format != FT_GLYPH_FORMAT_BITMAP) {
00354                 if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
00355                     // failed to load glyph
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                 // failed to load glyph
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             // OpenGL is initialized but GLU is missing, we need a bitmap from freetype
00370             if (g->format != FT_GLYPH_FORMAT_BITMAP) {
00371                 if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
00372                     // failed to load glyph
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                 // failed to load glyph
00380                 MMSFB_SetError(0, "glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY for " + this->filename);
00381                 return NULL;
00382             }
00383 #endif
00384         }
00385 
00386         // successfully loaded
00387         return g;
00388     }
00389     else {
00390         // failed to load glyph
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         // OpenGL is not initialized, setup glyph for software rendering
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             // rotate glyph by 180°
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     // OpenGL is initialized but GLU is missing, we need a bitmap from freetype
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     printf("left %d width %d advanceX %d top %d height %d fonth %d - %d\n",
00445             glyph->left, glyph->width, glyph->advanceX, glyph->top, glyph->height, this->height, g->advance.y / 64);
00446     */
00447 
00448     if (!g->bitmap.pitch) {
00449         // glyph has no bitmap (e.g. space char)
00450         glyph->pitch = 0;
00451         glyph->buffer = NULL;
00452         glyph->texture = 0;
00453         return true;
00454     }
00455 
00456     // add glyph to charmap, we use a pitch which is a multiple of 4 needed e.g. for OGL textures
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         // rotate glyph by 180°
00476         rotateUCharBuffer180(glyph->buffer, glyph->pitch, glyph->width, glyph->height);
00477     }
00478 
00479     // create a texture for this glyph
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     // OpenGL is initialized and GLU is available, we create meshes based on freetype outlines
00490 
00491 bool with_outline = true;
00492 
00493     // init glyph basics
00494     glyph->buffer   = NULL;
00495     glyph->pitch    = 0;
00496 /*  glyph->left     = (float)g->metrics.horiBearingX * this->scale_coeff;
00497     if (glyph->left>= 0) glyph->left = (glyph->left + 32) / 64; else glyph->left = (glyph->left - 32) / 64;
00498     glyph->top      = (float)g->metrics.horiBearingY * this->scale_coeff;
00499     if (glyph->top >= 0) glyph->top = (glyph->top + 32) / 64; else glyph->top = (glyph->top - 32) / 64;
00500     glyph->width    = ((float)g->metrics.width * this->scale_coeff + 32) / 64;
00501     glyph->height   = ((float)g->metrics.height * this->scale_coeff + 32) / 64;
00502     glyph->advanceX = ((float)g->advance.x * this->scale_coeff + 32) / 64;
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     printf("left %d width %d advanceX %d top %d height %d fonth %d - %d\n",
00513             glyph->left, glyph->width, glyph->advanceX, glyph->top, glyph->height, this->height, g->advance.y / 64);
00514     */
00515 
00516     // init glyph mesh and outline description
00517     glyph->meshes = NULL;
00518     glyph->outline = NULL;
00519 
00520     // my mesh id
00521     unsigned int subkey_mesh = glyph->character;
00522     glyph->meshes = new MMSFBBuffer(this->font_id, subkey_mesh);
00523 
00524     if (!with_outline) {
00525         // without outline
00526         if (glyph->meshes->isInitialized()) {
00527             // meshes already initialized
00528 //          printf("MMSFBFont: meshes already initialized\n");
00529             return true;
00530         }
00531     }
00532     else {
00533         // my outline id
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             // meshes and outline already initialized
00539 //          printf("MMSFBFont: meshes and outline already initialized\n");
00540             return true;
00541         }
00542     }
00543 
00544     // init tesselator
00545     MMSFTTesselator *ftv = new MMSFTTesselator(g);
00546 
00547     if (!glyph->meshes->isInitialized()) {
00548 //      printf("MMSFBFont: have to generate meshes\n");
00549 
00550         ftv->generateGlyph();
00551         const MMSFTGlyph *ftglyph = ftv->getGlyph();
00552         if (!ftglyph) {
00553             // glyph not generated
00554             MMSFB_SetError(0, "MMSFTTesselator::generateGlyph() failed");
00555             delete ftv;
00556             return false;
00557         }
00558 
00559         if (!ftglyph->getMeshCount()) {
00560             // no meshes available, but o.k. (e.g. space char)
00561             delete ftv;
00562             return true;
00563         }
00564 
00565         // count max meshes
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             // no meshes available
00577             MMSFB_SetError(0, "no meshes available");
00578             delete ftv;
00579             return false;
00580         }
00581 
00582         // allocate base buffer for vertices and indices
00583         // we do not need to clear because all fields will be set separately
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         // for all meshes
00594         for (unsigned int m = 0; m < ftglyph->getMeshCount(); m++) {
00595             // prepare access to vertices and indices of glyph
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             // get access to polygon data
00604             const MMSFTMesh *ftmesh = ftglyph->getMesh(m);
00605             if (!ftmesh) continue;
00606 
00607             // prepare indices
00608             // note: no need to allocate index buffer, because vertices are correctly sorted
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                 // unsupported type
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             // prepare vertices using normal 32bit floating point values
00628             initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
00629 #else
00630             // prepare vertices using 16bit half floating point values
00631             initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
00632 #endif
00633             // for all vertices in the polygon
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             // next mesh
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 //          printf("MMSFBFont: have to generate outline\n");
00652 
00653             // add outline primitives
00654             unsigned short int max_outlines = ftv->getContourCount();
00655 
00656             // allocate base buffer for vertices and indices
00657             // we do not need to clear because all fields will be set separately
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             // for all contours (outlines)
00668             for (unsigned int c = 0; c < ftv->getContourCount(); c++) {
00669                 // prepare access to vertices and indices of glyph
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                 // get access to contour data
00678                 const MMSFTContour *ftcontour = ftv->getContour(c);
00679                 if (!ftcontour) continue;
00680 
00681                 // prepare indices
00682                 // note: no need to allocate index buffer, because vertices are correctly sorted
00683                 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_LINE_LOOP);
00684 
00685 #ifndef __HAVE_OGL_HALF_FLOAT__
00686                 // prepare vertices using normal 32bit floating point values
00687                 initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
00688 #else
00689                 // prepare vertices using 16bit half floating point values
00690                 initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
00691 #endif
00692                 // for all vertices in the polygon
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                 // next outline
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 // Test mit dreiecken zieht strom!!! dazu kommt noch das Skalierungsproblem...
00711 /*  if (with_outline && ftv->getContourCount() > 0) {
00712         if (!glyph->outline->isInitialized()) {
00713 
00714             glyph->top      += 0;
00715             glyph->width    += 2;
00716             glyph->height   += 2;
00717             glyph->advanceX += 2;
00718 
00719 
00720             // add outline primitives
00721             unsigned short int max_outlines = ftv->getContourCount();
00722 
00723             // allocate base buffer for vertices and indices
00724             // we do not need to clear because all fields will be set separately
00725             MMSFBBuffer::INDEX_BUFFER index_buffer;
00726             MMSFBBuffer::VERTEX_BUFFER vertex_buffer;
00727             index_buffer.num_arrays = 0;
00728             index_buffer.max_arrays = max_outlines;
00729             index_buffer.arrays = (MMS_INDEX_ARRAY*)malloc(sizeof(MMS_INDEX_ARRAY) * index_buffer.max_arrays);
00730             vertex_buffer.num_arrays = 0;
00731             vertex_buffer.max_arrays = max_outlines;
00732             vertex_buffer.arrays = (MMS_VERTEX_ARRAY*)malloc(sizeof(MMS_VERTEX_ARRAY) * vertex_buffer.max_arrays);
00733 
00734             // for all contours (outlines)
00735             for (unsigned int c = 0; c < ftv->getContourCount(); c++) {
00736                 // prepare access to vertices and indices of glyph
00737                 if (index_buffer.num_arrays >= max_outlines) {
00738                     printf("max_outlines(%u) reached\n", max_outlines);
00739                     break;
00740                 }
00741                 MMS_INDEX_ARRAY  *indices  = &index_buffer.arrays[index_buffer.num_arrays];
00742                 MMS_VERTEX_ARRAY *vertices = &vertex_buffer.arrays[vertex_buffer.num_arrays];
00743 
00744                 // get access to contour data
00745                 const MMSFTContour *ftcontour = ftv->getContour(c);
00746                 if (!ftcontour) continue;
00747 
00748                 // prepare indices
00749                 // note: no need to allocate index buffer, because vertices are correctly sorted
00750                 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLES);
00751 
00752                 // prepare vertices using normal 32bit floating point values
00753                 initVertexArray(vertices, 2, ftcontour->getVertexCount() * 6, MMS_VERTEX_DATA_TYPE_FLOAT);
00754 printf("*********************\n");
00755                 for (unsigned int v = 0; v < ftcontour->getVertexCount(); v++) {
00756                     const MMSFTVertex &vertex1 = ftcontour->Vertex(v);
00757                     const MMSFTVertex &outset1 = ftcontour->Outset(v);
00758                     const MMSFTVertex &vertex2 = ftcontour->Vertex((v+1 < ftcontour->getVertexCount()) ? v+1 : 0);
00759                     const MMSFTVertex &outset2 = ftcontour->Outset((v+1 < ftcontour->getVertexCount()) ? v+1 : 0);
00760 printf("v: %f,%f\n", vertex1.X(), vertex1.Y());
00761 printf("o: %f,%f\n", outset1.X(), outset1.Y());
00762 
00763                     float fac=3.0f;
00764 
00765                     float *vdata = (float *)vertices->data;
00766 
00767 
00768                     vdata[v*6 * vertices->eSize + 0] = (float)(vertex1.X() - g->metrics.horiBearingX) / 64;
00769                     vdata[v*6 * vertices->eSize + 1] = (float)(g->metrics.horiBearingY - vertex1.Y()) / 64;
00770 
00771                     vdata[v*6 * vertices->eSize + 2] = (float)(vertex1.X() + outset1.X() * fac - g->metrics.horiBearingX) / 64;
00772                     vdata[v*6 * vertices->eSize + 3] = (float)(g->metrics.horiBearingY - vertex1.Y() - outset1.Y() * fac) / 64;
00773 
00774                     vdata[v*6 * vertices->eSize + 4] = (float)(vertex2.X() - g->metrics.horiBearingX) / 64;
00775                     vdata[v*6 * vertices->eSize + 5] = (float)(g->metrics.horiBearingY - vertex2.Y()) / 64;
00776 
00777                     vdata[v*6 * vertices->eSize + 6] = (float)(vertex1.X() + outset1.X() * fac - g->metrics.horiBearingX) / 64;
00778                     vdata[v*6 * vertices->eSize + 7] = (float)(g->metrics.horiBearingY - vertex1.Y() - outset1.Y() * fac) / 64;
00779 
00780                     vdata[v*6 * vertices->eSize + 8] = (float)(vertex2.X() + outset2.X() * fac - g->metrics.horiBearingX) / 64;
00781                     vdata[v*6 * vertices->eSize + 9] = (float)(g->metrics.horiBearingY - vertex2.Y() - outset2.Y() * fac) / 64;
00782 
00783                     vdata[v*6 * vertices->eSize + 10]= (float)(vertex2.X() - g->metrics.horiBearingX) / 64;
00784                     vdata[v*6 * vertices->eSize + 11]= (float)(g->metrics.horiBearingY - vertex2.Y()) / 64;
00785                 }
00786 
00787                 // next outline
00788                 index_buffer.num_arrays++;
00789                 vertex_buffer.num_arrays++;
00790             }
00791 
00792             glyph->outline->initBuffer(index_buffer, vertex_buffer);
00793         }
00794     }
00795 */
00796 
00797     // all is successfully done
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         // check if requested character is already loaded
00825         std::map<unsigned int, MMSFBFont_Glyph>::iterator it;
00826         it = this->charmap.find(character);
00827         if (it == this->charmap.end()) {
00828             // no, have to load it
00829             FT_GlyphSlot g;
00830             if (!(g = (FT_GlyphSlot)loadFTGlyph(character))) {
00831                 // failed to load glyph
00832                 unlock();
00833                 return false;
00834             }
00835 
00836             // setup glyph values
00837             if (!setupFTGlyph(character, g, glyph)) {
00838                 // failed to setup glyph
00839                 unlock();
00840                 return false;
00841             }
00842 
00843             // add to charmap
00844             this->charmap.insert(std::make_pair(character, *glyph));
00845             ret = true;
00846         }
00847         else {
00848             // already loaded
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     // check if initialized
00864     INITCHECK;
00865 
00866     // reset width
00867     if (!width) return false;
00868     *width = 0;
00869 
00870     // get the length of the string
00871     if (len < 0) len = text.size();
00872     if (!len) return true;
00873 
00874     // get the width of the whole string
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                 // have to calculate advanceX because of scale coefficient
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     // check if initialized
00903     INITCHECK;
00904 
00905     // get the height of the font
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             // have to calculate height because of scale coefficient
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     // check if initialized
00932     INITCHECK;
00933 
00934     // get the ascender of the font
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             // have to calculate ascender because of scale coefficient
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     // check if initialized
00956     INITCHECK;
00957 
00958     // get the descender of the font
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             // have to calculate descender because of scale coefficient
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     // check if initialized
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 

Generated by doxygen