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 
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 void showGlyphAttributes(FT_GlyphSlot glyph) {
00272     FT_Glyph_Metrics *metrics = &glyph->metrics;
00273     FT_Bitmap  *bitmap = &glyph->bitmap;
00274     FT_Outline *outline = &glyph->outline;
00275 
00276     printf("glyph***\n");
00277 
00278     printf("format = %d\n", glyph->format);
00279 
00280     printf("metrics***\n");
00281     printf("  width        = %d, %.02f\n", metrics->width, (float)metrics->width / 64);
00282     printf("  height       = %d, %.02f\n", metrics->height, (float)metrics->height / 64);
00283     printf("  horiBearingX = %d, %.02f\n", metrics->horiBearingX, (float)metrics->horiBearingX / 64);
00284     printf("  horiBearingY = %d, %.02f\n", metrics->horiBearingY, (float)metrics->horiBearingY / 64);
00285     printf("  horiAdvance  = %d, %.02f\n", metrics->horiAdvance, (float)metrics->horiAdvance / 64);
00286     printf("  vertBearingX = %d, %.02f\n", metrics->vertBearingX, (float)metrics->vertBearingX / 64);
00287     printf("  vertBearingY = %d, %.02f\n", metrics->vertBearingY, (float)metrics->vertBearingY / 64);
00288     printf("  vertAdvance  = %d, %.02f\n", metrics->vertAdvance, (float)metrics->vertAdvance / 64);
00289     printf("***metrics\n");
00290 
00291     printf("advance.x    = %d, %.02f\n", glyph->advance.x, (float)glyph->advance.x / 64);
00292     printf("advance.y    = %d, %.02f\n", glyph->advance.y, (float)glyph->advance.y / 64);
00293 
00294     printf("bitmap***\n");
00295     printf("  pitch  = %d\n", bitmap->pitch);
00296     printf("  width  = %d\n", bitmap->width);
00297     printf("  height = %d\n", bitmap->rows);
00298     printf("***bitmap\n");
00299     printf("bitmap_left = %d\n", glyph->bitmap_left);
00300     printf("bitmap_top  = %d\n", glyph->bitmap_top);
00301 
00302     printf("outline***\n");
00303     printf("  n_contours = %d\n", outline->n_contours);
00304     printf("  n_points   = %d\n", outline->n_points);
00305     for (int i = 0; i < outline->n_points; i++) {
00306         printf("    %d, %d\n   >%.02f, %.02f\n", outline->points[i].x, outline->points[i].y,
00307                                               (float)outline->points[i].x / 64, (float)outline->points[i].y / 64);
00308     }
00309     printf("  flags = %d\n", outline->flags);
00310     printf("***outline\n");
00311 
00312     printf("lsb_delta    = %d\n", glyph->lsb_delta);
00313     printf("rsb_delta    = %d\n", glyph->rsb_delta);
00314 
00315     printf("***glyph\n");
00316 }
00317 */
00318 
00319 void *MMSFBFont::loadFTGlyph(unsigned int character) {
00320     FT_GlyphSlot g = NULL;
00321 
00322     // load glyph but do NOT render a bitmap
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 //          FT_Get_Char_Index((FT_Face)this->ft_face, (FT_ULong)character), FT_LOAD_DEFAULT | FT_LOAD_FORCE_AUTOHINT
00326 //      | FT_LOAD_TARGET_LIGHT
00327 //      | FT_LOAD_TARGET_MONO
00328 //      | FT_LOAD_TARGET_LCD
00329 //      | FT_LOAD_TARGET_LCD_V
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 /*TEST CODE
00337     if (!FT_Load_Glyph((FT_Face)this->ft_face,
00338         FT_Get_Char_Index((FT_Face)this->ft_face, (FT_ULong)character), FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT)) {
00339         g = ((FT_Face)this->ft_face)->glyph;
00340     } else {
00341         MMSFB_SetError(0, "FT_Load_Glyph(,,FT_LOAD_RENDER) failed for " + this->filename);
00342     }
00343     showGlyphAttributes(g);
00344     exit(0);
00345 */
00346 
00347     if (g) {
00348 #ifdef __HAVE_OPENGL__
00349         if (!mmsfb->bei) {
00350 #else
00351         if (1) {
00352 #endif
00353             // OpenGL is not initialized, we need a bitmap from freetype
00354             if (g->format != FT_GLYPH_FORMAT_BITMAP) {
00355                 if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
00356                     // failed to load glyph
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                 // failed to load glyph
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             // OpenGL is initialized but GLU is missing, we need a bitmap from freetype
00371             if (g->format != FT_GLYPH_FORMAT_BITMAP) {
00372                 if (FT_Render_Glyph(g, FT_RENDER_MODE_NORMAL)) {
00373                     // failed to load glyph
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                 // failed to load glyph
00381                 MMSFB_SetError(0, "glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY for " + this->filename);
00382                 return NULL;
00383             }
00384 #endif
00385         }
00386 
00387         // successfully loaded
00388         return g;
00389     }
00390     else {
00391         // failed to load glyph
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         // OpenGL is not initialized, setup glyph for software rendering
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             // rotate glyph by 180°
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     // OpenGL is initialized but GLU is missing, we need a bitmap from freetype
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     printf("left %d width %d advanceX %d top %d height %d fonth %d - %d\n",
00446             glyph->left, glyph->width, glyph->advanceX, glyph->top, glyph->height, this->height, g->advance.y / 64);
00447     */
00448 
00449     if (!g->bitmap.pitch) {
00450         // glyph has no bitmap (e.g. space char)
00451         glyph->pitch = 0;
00452         glyph->buffer = NULL;
00453         glyph->texture = 0;
00454         return true;
00455     }
00456 
00457     // add glyph to charmap, we use a pitch which is a multiple of 4 needed e.g. for OGL textures
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         // rotate glyph by 180°
00477         rotateUCharBuffer180(glyph->buffer, glyph->pitch, glyph->width, glyph->height);
00478     }
00479 
00480     // create a texture for this glyph
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     // OpenGL is initialized and GLU is available, we create meshes based on freetype outlines
00491 
00492 bool with_outline = true;
00493 
00494     // init glyph basics
00495     glyph->buffer   = NULL;
00496     glyph->pitch    = 0;
00497 /*  glyph->left     = (float)g->metrics.horiBearingX * this->scale_coeff;
00498     if (glyph->left>= 0) glyph->left = (glyph->left + 32) / 64; else glyph->left = (glyph->left - 32) / 64;
00499     glyph->top      = (float)g->metrics.horiBearingY * this->scale_coeff;
00500     if (glyph->top >= 0) glyph->top = (glyph->top + 32) / 64; else glyph->top = (glyph->top - 32) / 64;
00501     glyph->width    = ((float)g->metrics.width * this->scale_coeff + 32) / 64;
00502     glyph->height   = ((float)g->metrics.height * this->scale_coeff + 32) / 64;
00503     glyph->advanceX = ((float)g->advance.x * this->scale_coeff + 32) / 64;
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     printf("left %d width %d advanceX %d top %d height %d fonth %d - %d\n",
00514             glyph->left, glyph->width, glyph->advanceX, glyph->top, glyph->height, this->height, g->advance.y / 64);
00515     */
00516 
00517     // init glyph mesh and outline description
00518     glyph->meshes = NULL;
00519     glyph->outline = NULL;
00520 
00521     // my mesh id
00522     unsigned int subkey_mesh = glyph->character;
00523     glyph->meshes = new MMSFBBuffer(this->font_id, subkey_mesh);
00524 
00525     if (!with_outline) {
00526         // without outline
00527         if (glyph->meshes->isInitialized()) {
00528             // meshes already initialized
00529 //          printf("MMSFBFont: meshes already initialized\n");
00530             return true;
00531         }
00532     }
00533     else {
00534         // my outline id
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             // meshes and outline already initialized
00540 //          printf("MMSFBFont: meshes and outline already initialized\n");
00541             return true;
00542         }
00543     }
00544 
00545     // init tesselator
00546     MMSFTTesselator *ftv = new MMSFTTesselator(g);
00547 
00548     if (!glyph->meshes->isInitialized()) {
00549 //      printf("MMSFBFont: have to generate meshes\n");
00550 
00551         ftv->generateGlyph();
00552         const MMSFTGlyph *ftglyph = ftv->getGlyph();
00553         if (!ftglyph) {
00554             // glyph not generated
00555             MMSFB_SetError(0, "MMSFTTesselator::generateGlyph() failed");
00556             delete ftv;
00557             return false;
00558         }
00559 
00560         if (!ftglyph->getMeshCount()) {
00561             // no meshes available, but o.k. (e.g. space char)
00562             delete ftv;
00563             return true;
00564         }
00565 
00566         // count max meshes
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             // no meshes available
00578             MMSFB_SetError(0, "no meshes available");
00579             delete ftv;
00580             return false;
00581         }
00582 
00583         // allocate base buffer for vertices and indices
00584         // we do not need to clear because all fields will be set separately
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         // for all meshes
00595         for (unsigned int m = 0; m < ftglyph->getMeshCount(); m++) {
00596             // prepare access to vertices and indices of glyph
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             // get access to polygon data
00605             const MMSFTMesh *ftmesh = ftglyph->getMesh(m);
00606             if (!ftmesh) continue;
00607 
00608             // prepare indices
00609             // note: no need to allocate index buffer, because vertices are correctly sorted
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                 // unsupported type
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             // prepare vertices using normal 32bit floating point values
00629             initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
00630 #else
00631             // prepare vertices using 16bit half floating point values
00632             initVertexArray(vertices, 2, ftmesh->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
00633 #endif
00634             // for all vertices in the polygon
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             // next mesh
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 //          printf("MMSFBFont: have to generate outline\n");
00653 
00654             // add outline primitives
00655             unsigned short int max_outlines = ftv->getContourCount();
00656 
00657             // allocate base buffer for vertices and indices
00658             // we do not need to clear because all fields will be set separately
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             // for all contours (outlines)
00669             for (unsigned int c = 0; c < ftv->getContourCount(); c++) {
00670                 // prepare access to vertices and indices of glyph
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                 // get access to contour data
00679                 const MMSFTContour *ftcontour = ftv->getContour(c);
00680                 if (!ftcontour) continue;
00681 
00682                 // prepare indices
00683                 // note: no need to allocate index buffer, because vertices are correctly sorted
00684                 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_LINE_LOOP);
00685 
00686 #ifndef __HAVE_OGL_HALF_FLOAT__
00687                 // prepare vertices using normal 32bit floating point values
00688                 initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_FLOAT);
00689 #else
00690                 // prepare vertices using 16bit half floating point values
00691                 initVertexArray(vertices, 2, ftcontour->getVertexCount(), MMS_VERTEX_DATA_TYPE_HALF_FLOAT);
00692 #endif
00693                 // for all vertices in the polygon
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                 // next outline
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 // Test mit dreiecken zieht strom!!! dazu kommt noch das Skalierungsproblem...
00712 /*  if (with_outline && ftv->getContourCount() > 0) {
00713         if (!glyph->outline->isInitialized()) {
00714 
00715             glyph->top      += 0;
00716             glyph->width    += 2;
00717             glyph->height   += 2;
00718             glyph->advanceX += 2;
00719 
00720 
00721             // add outline primitives
00722             unsigned short int max_outlines = ftv->getContourCount();
00723 
00724             // allocate base buffer for vertices and indices
00725             // we do not need to clear because all fields will be set separately
00726             MMSFBBuffer::INDEX_BUFFER index_buffer;
00727             MMSFBBuffer::VERTEX_BUFFER vertex_buffer;
00728             index_buffer.num_arrays = 0;
00729             index_buffer.max_arrays = max_outlines;
00730             index_buffer.arrays = (MMS_INDEX_ARRAY*)malloc(sizeof(MMS_INDEX_ARRAY) * index_buffer.max_arrays);
00731             vertex_buffer.num_arrays = 0;
00732             vertex_buffer.max_arrays = max_outlines;
00733             vertex_buffer.arrays = (MMS_VERTEX_ARRAY*)malloc(sizeof(MMS_VERTEX_ARRAY) * vertex_buffer.max_arrays);
00734 
00735             // for all contours (outlines)
00736             for (unsigned int c = 0; c < ftv->getContourCount(); c++) {
00737                 // prepare access to vertices and indices of glyph
00738                 if (index_buffer.num_arrays >= max_outlines) {
00739                     printf("max_outlines(%u) reached\n", max_outlines);
00740                     break;
00741                 }
00742                 MMS_INDEX_ARRAY  *indices  = &index_buffer.arrays[index_buffer.num_arrays];
00743                 MMS_VERTEX_ARRAY *vertices = &vertex_buffer.arrays[vertex_buffer.num_arrays];
00744 
00745                 // get access to contour data
00746                 const MMSFTContour *ftcontour = ftv->getContour(c);
00747                 if (!ftcontour) continue;
00748 
00749                 // prepare indices
00750                 // note: no need to allocate index buffer, because vertices are correctly sorted
00751                 initIndexArray(indices, MMS_INDEX_ARRAY_TYPE_TRIANGLES);
00752 
00753                 // prepare vertices using normal 32bit floating point values
00754                 initVertexArray(vertices, 2, ftcontour->getVertexCount() * 6, MMS_VERTEX_DATA_TYPE_FLOAT);
00755 printf("*********************\n");
00756                 for (unsigned int v = 0; v < ftcontour->getVertexCount(); v++) {
00757                     const MMSFTVertex &vertex1 = ftcontour->Vertex(v);
00758                     const MMSFTVertex &outset1 = ftcontour->Outset(v);
00759                     const MMSFTVertex &vertex2 = ftcontour->Vertex((v+1 < ftcontour->getVertexCount()) ? v+1 : 0);
00760                     const MMSFTVertex &outset2 = ftcontour->Outset((v+1 < ftcontour->getVertexCount()) ? v+1 : 0);
00761 printf("v: %f,%f\n", vertex1.X(), vertex1.Y());
00762 printf("o: %f,%f\n", outset1.X(), outset1.Y());
00763 
00764                     float fac=3.0f;
00765 
00766                     float *vdata = (float *)vertices->data;
00767 
00768 
00769                     vdata[v*6 * vertices->eSize + 0] = (float)(vertex1.X() - g->metrics.horiBearingX) / 64;
00770                     vdata[v*6 * vertices->eSize + 1] = (float)(g->metrics.horiBearingY - vertex1.Y()) / 64;
00771 
00772                     vdata[v*6 * vertices->eSize + 2] = (float)(vertex1.X() + outset1.X() * fac - g->metrics.horiBearingX) / 64;
00773                     vdata[v*6 * vertices->eSize + 3] = (float)(g->metrics.horiBearingY - vertex1.Y() - outset1.Y() * fac) / 64;
00774 
00775                     vdata[v*6 * vertices->eSize + 4] = (float)(vertex2.X() - g->metrics.horiBearingX) / 64;
00776                     vdata[v*6 * vertices->eSize + 5] = (float)(g->metrics.horiBearingY - vertex2.Y()) / 64;
00777 
00778                     vdata[v*6 * vertices->eSize + 6] = (float)(vertex1.X() + outset1.X() * fac - g->metrics.horiBearingX) / 64;
00779                     vdata[v*6 * vertices->eSize + 7] = (float)(g->metrics.horiBearingY - vertex1.Y() - outset1.Y() * fac) / 64;
00780 
00781                     vdata[v*6 * vertices->eSize + 8] = (float)(vertex2.X() + outset2.X() * fac - g->metrics.horiBearingX) / 64;
00782                     vdata[v*6 * vertices->eSize + 9] = (float)(g->metrics.horiBearingY - vertex2.Y() - outset2.Y() * fac) / 64;
00783 
00784                     vdata[v*6 * vertices->eSize + 10]= (float)(vertex2.X() - g->metrics.horiBearingX) / 64;
00785                     vdata[v*6 * vertices->eSize + 11]= (float)(g->metrics.horiBearingY - vertex2.Y()) / 64;
00786                 }
00787 
00788                 // next outline
00789                 index_buffer.num_arrays++;
00790                 vertex_buffer.num_arrays++;
00791             }
00792 
00793             glyph->outline->initBuffer(index_buffer, vertex_buffer);
00794         }
00795     }
00796 */
00797 
00798     // all is successfully done
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         // check if requested character is already loaded
00826         std::map<unsigned int, MMSFBFont_Glyph>::iterator it;
00827         it = this->charmap.find(character);
00828         if (it == this->charmap.end()) {
00829             // no, have to load it
00830             FT_GlyphSlot g;
00831             if (!(g = (FT_GlyphSlot)loadFTGlyph(character))) {
00832                 // failed to load glyph
00833                 unlock();
00834                 return false;
00835             }
00836 
00837             // setup glyph values
00838             if (!setupFTGlyph(character, g, glyph)) {
00839                 // failed to setup glyph
00840                 unlock();
00841                 return false;
00842             }
00843 
00844             // add to charmap
00845             this->charmap.insert(std::make_pair(character, *glyph));
00846             ret = true;
00847         }
00848         else {
00849             // already loaded
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     // check if initialized
00865     INITCHECK;
00866 
00867     // reset width
00868     if (!width) return false;
00869     *width = 0;
00870 
00871     // get the length of the string
00872     if (len < 0) len = text.size();
00873     if (!len) return true;
00874 
00875     // get the width of the whole string
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                 // have to calculate advanceX because of scale coefficient
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     // check if initialized
00904     INITCHECK;
00905 
00906     // get the height of the font
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             // have to calculate height because of scale coefficient
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     // check if initialized
00933     INITCHECK;
00934 
00935     // get the ascender of the font
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             // have to calculate ascender because of scale coefficient
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     // check if initialized
00957     INITCHECK;
00958 
00959     // get the descender of the font
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             // have to calculate descender because of scale coefficient
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     // check if initialized
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 

Generated by doxygen