/home/rixxx/src/glttf/src/font.h

00001 #ifndef _FONT_H_
00002 #define _FONT_H_
00003 
00004 #include <limits>
00005 #include <string>
00006 #include <stdexcept>
00007 #include <map>
00008 #include <cmath>
00009 
00011 namespace glttf {
00012 
00014 
00028 class Font
00029 {
00030 public:
00032     static const unsigned long DEFAULT_FACE_INDEX = 0;
00033     
00035     typedef unsigned char FontStyle;
00037     static const FontStyle PLAIN = 0x0;
00039     static const FontStyle BOLD = 0x1;
00041     static const FontStyle ITALIC = 0x2;
00042     
00044     typedef unsigned char Flags;
00046     static const Flags FLIP_Y_AXIS = 0x1;
00048     static const Flags SCALE_TO_1EM = 0x2;
00050     static const Flags TOP_LEFT_ORIGIN = 0x4;
00051     
00053     static const float BOLD_WEIGHT;
00055     static const float ITALIC_SHEAR;
00056     
00058 
00078     Font(const std::string &filename, unsigned int size, FontStyle style, unsigned long faceIndex = DEFAULT_FACE_INDEX);
00079     
00081 
00088     virtual ~Font();
00089     
00091 
00106     void setPixelSize(unsigned int width, unsigned int height = 0);
00107     
00109 
00127     void setCharSize(float width, float height, unsigned int hres = 0, unsigned int vres = 0);
00128     
00130 
00140     void setTransformation(float weight, float shear);
00141     
00143 
00151     void setStyle(FontStyle style);
00152     
00154 
00171     Glyph &getGlyph(unsigned long ch, bool cache);
00172     
00174 
00187     void drawCharacter(unsigned long ch, bool cache = true);
00188     
00190 
00205     template<typename Iterator>
00206     void drawString(Iterator begin, Iterator end, bool cache = true);
00207 
00209 
00229     template<typename Iterator>
00230     void getBoundingBox(Iterator begin, Iterator end, float &minX, float &minY, float &maxX, float &maxY, bool cache = true);
00231     
00233 
00241     void drawString(std::string const &str, bool cache = true);
00242     
00244 
00257     void getBoundingBox(std::string const &str, float &minX, float &minY, float &maxX, float &maxY, bool cache = true);
00258 
00259 #ifdef HAVE_WSTRING
00261 
00269     void drawString(std::wstring const &str, bool cache = true);
00270     
00272 
00285     void getBoundingBox(std::wstring const &str, float &minX, float &minY, float &maxX, float &maxY, bool cache = true);
00286 #endif
00287     
00289 
00296     void buildCache(unsigned long from = 0, unsigned long to = 127);
00297     
00299 
00310     virtual void setupState();
00311     
00313 
00324     virtual void cleanupState();
00325 
00327 
00335     void setScaleTo1EM(bool enable);
00336     
00338 
00341     bool getScaleTo1EM() const;
00342     
00344 
00350     void setFlipYAxis(bool enable);
00351     
00353 
00356     bool getFlipYAxis() const;
00357     
00359 
00364     void setTopLeftOrigin(bool enable);
00365     
00367 
00370     bool getTopLeftOrigin() const;
00371     
00373 
00376     Flags getFlags() const;
00377     
00379 
00382     void setFlags(Flags f);
00383 
00385 
00388     float getTextHeight() const;
00389     
00391 
00394     float getUnitsPerEM() const;
00395     
00397 
00400     float getAscender() const;
00401     
00403 
00406     float getDescender() const;
00407     
00409 
00415     float getMaxAdvanceX() const;
00416     
00418 
00421     float getMaxAdvanceY() const;
00422     
00424 
00427     float getWeight() const;
00428     
00430 
00433     float getShear() const;
00434 
00436 
00439     unsigned int getTabSize() const;
00440     
00442 
00445     void setTabSize(unsigned int size);
00446     
00448 
00454     void setTabWidth(float width);
00455     
00457 
00461     float getTabWidth() const;
00462     
00464 
00471     float getTabWidth(bool cache = true);
00472     
00473 protected:
00474     unsigned int getCharIndex(unsigned long charcode) const;
00475     FT_GlyphSlot getFTGlyph(unsigned int index) const;
00476     
00478 
00485     void deleteCache();
00486     
00488 
00499     virtual Glyph *makeGlyph(FT_GlyphSlot glyph) = 0;
00500     
00501 private:
00502     Font(const Font& font);
00503     Font &operator=(const Font &font);
00504     
00505     unsigned int stateSet;
00506     Flags flags;
00507     unsigned int tabSize;
00508     float tabWidth;
00509     
00510     typedef std::map<unsigned long, Glyph*> GlyphMap;
00511     GlyphMap glyphs;
00512     
00513     void loadCharacter(unsigned long ch);
00514     
00515     void initLibrary();
00516     void deinitLibrary();
00517     FT_Face face;
00518     
00519     bool kerning;
00520     
00521     FontStyle style;
00522     float weight, shear;
00523     
00524     float textHeight;
00525     float unitsPerEM;
00526     float ascender, descender;
00527     float maxAdvanceX, maxAdvanceY;
00528     
00529     static FT_Library library;
00530     static int instances;
00531     
00532     void calculateTabWidth(bool cache);
00533 };
00534 
00535 template<typename Iterator>
00536 void Font::drawString(Iterator begin, Iterator end, bool cache)
00537 {
00538     setupState();
00539     
00540     glPushMatrix();
00541     
00542     if(flags & FLIP_Y_AXIS) glScalef(1.0f, -1.0f, 1.0f);
00543     if(flags & SCALE_TO_1EM)
00544     {
00545         float scale = 1.0 / unitsPerEM;
00546         glScalef(scale, scale, scale);
00547     }
00548     if(flags & TOP_LEFT_ORIGIN) glTranslatef(0.0f, -ascender, 0.0f);
00549     
00550     glPushMatrix();
00551     
00552     float x0 = 0.0f;
00553     unsigned int prev = 0;
00554     for(Iterator i(begin); i != end; ++i)
00555     {
00556         unsigned long ch = (*i < 0)?(0):(*i);
00557 
00558         if(kerning)
00559         {
00560             unsigned int index = getCharIndex(ch);
00561             
00562             if(prev && index)
00563             {
00564                 FT_Vector delta;
00565                 if(FT_Get_Kerning(face, prev, index, FT_KERNING_DEFAULT, &delta))
00566                 {
00567                     glPopMatrix();
00568                     glPopMatrix();
00569                     cleanupState();
00570                     throw std::runtime_error("Can't get glyph kerning");
00571                 }
00572                 
00573                 glTranslatef(weight * delta.x / 64.0f, 0.0f, 0.0f);
00574             }
00575             
00576             prev = index;
00577         }
00578         
00579         // TODO: tab, etc
00580         if(ch == '\n')
00581         {
00582             x0 = 0.0f;
00583             glPopMatrix();
00584             glTranslatef(0.0f, -textHeight, 0.0f);
00585             glPushMatrix();
00586             continue;
00587         } else if(ch == '\r')
00588         {
00589             continue;
00590         } else if(ch == '\t')
00591         {
00592             ch = ' ';
00593             prev = getCharIndex(ch);
00594             
00595             if(tabWidth < 0.0)
00596             {
00597                 try
00598                 {
00599                     calculateTabWidth(cache);
00600                 } catch(...)
00601                 {
00602                     glPopMatrix();
00603                     glPopMatrix();
00604                     cleanupState();
00605                     throw;
00606                 }
00607             }
00608             
00609             float tx = std::floor((x0 + tabWidth) / tabWidth) * tabWidth;
00610             glTranslatef(tx - x0, 0.0f ,0.0f);
00611             x0 = tx;
00612             
00613             continue;
00614         }
00615         
00616         try
00617         {
00618             const Glyph &glyph = getGlyph(ch, cache);
00619             glyph.draw();
00620             glTranslatef(weight * glyph.getAdvanceX(), 0.0f, 0.0f);
00621             x0 += glyph.getAdvanceX() * weight;
00622         } catch(...)
00623         {
00624             glPopMatrix();
00625             glPopMatrix();
00626             cleanupState();
00627             throw;
00628         }
00629     }
00630     
00631     glPopMatrix();
00632     glPopMatrix();
00633     cleanupState();
00634 }
00635 
00636 template<typename Iterator>
00637 void Font::getBoundingBox(Iterator begin, Iterator end, float &minX, float &minY, float &maxX, float &maxY, bool cache)
00638 {   
00639     float x0 = 0.0;
00640     float y0 = 0.0;
00641     
00642     const float MAX = std::numeric_limits<float>::max();
00643     const float MIN = std::numeric_limits<float>::min();
00644     minX = MAX;
00645     maxX = MIN;
00646     minY = MAX;
00647     maxY = MIN;
00648     
00649     unsigned int prev = 0;
00650     for(Iterator i(begin); i != end; ++i)
00651     {
00652         unsigned long ch = (*i < 0)?(0):(*i);
00653     
00654         unsigned int index = getCharIndex(ch);
00655         if(kerning && index)
00656         {
00657             if(prev)
00658             {
00659                 FT_Vector delta;
00660                 if(FT_Get_Kerning(face, prev, index, FT_KERNING_DEFAULT, &delta))
00661                 {
00662                     throw std::runtime_error("Can't get glyph kerning");
00663                 }
00664                 x0 += weight * delta.x / 64.0f;
00665             }
00666         }
00667         prev = index;
00668 
00669         // TODO: tab, etc.
00670         if(ch == '\n')
00671         {
00672             x0 = 0.0f;
00673             y0 -= textHeight;
00674             continue;
00675         } else if(ch == '\r')
00676         {
00677             continue;
00678         } else if(ch == '\t')
00679         {
00680             ch = ' ';
00681             prev = index = getCharIndex(ch);
00682 
00683             if(tabWidth < 0.0f) calculateTabWidth(cache);
00684 
00685             x0 = std::floor((x0 + tabWidth) / tabWidth) * tabWidth;
00686     
00687             continue;
00688         }
00689 
00690         float x1, y1, x2, y2;
00691 
00692         const Glyph &glyph = getGlyph(ch, cache);
00693 
00694         x1 = x0 + glyph.getMinX();
00695         y1 = y0 + glyph.getMinY();
00696         x2 = x0 + glyph.getMaxX();
00697         y2 = y0 + glyph.getMaxY();
00698             
00699         x0 += glyph.getAdvanceX() * weight;
00700 
00701         if(x1 < minX) minX = x1;
00702         if(y1 < minY) minY = y1;
00703         if(x2 > maxX) maxX = x2;
00704         if(y2 > maxY) maxY = y2;
00705     }
00706     
00707     if(flags & FLIP_Y_AXIS)
00708     {
00709         minY = -minY;
00710         maxY = -maxY;
00711     }
00712     
00713     float scale = 1.0;
00714     if(flags & SCALE_TO_1EM)
00715     {
00716         scale = 1.0 / unitsPerEM;
00717         maxX *= scale;
00718         minX *= scale;
00719         maxY *= scale;
00720         minY *= scale;
00721     }
00722     
00723     if(flags & FLIP_Y_AXIS) scale = -scale;
00724     
00725     if(flags & TOP_LEFT_ORIGIN)
00726     {
00727         minY -= ascender * scale;
00728         maxY -= ascender * scale;
00729     }
00730 }
00731 
00732 
00734 
00738 template <class T>
00739 class BasicFont : public Font
00740 {
00741 public:
00743     typedef T GlyphType;
00744     
00746     typedef typename T::Parameter Parameter;
00747     
00749 
00757     BasicFont(const std::string &filename, unsigned int size = 32, Font::FontStyle style = Font::PLAIN, unsigned long faceIndex = Font::DEFAULT_FACE_INDEX)
00758         : Font(filename, size, style, faceIndex), stateSet(0), parameter(GlyphType::DEFAULT_PARAMETER)
00759     {
00760     }
00761     
00763     ~BasicFont() {}
00764     
00766 
00770     void setupState()
00771     {
00772         if(stateSet)
00773         {
00774             ++stateSet;
00775             return;
00776         }
00777         ++stateSet;
00778     
00779         Font::setupState();
00780         GlyphType::setupState();
00781     }
00782     
00784 
00789     void cleanupState()
00790     {
00791         if(!stateSet) return;
00792         --stateSet;
00793         if(stateSet) return;
00794 
00795         GlyphType::cleanupState();
00796         Font::cleanupState();
00797     }
00798     
00800 
00805     void setParameter(const Parameter &param)
00806     {
00807         if(stateSet) throw std::logic_error("Can't set font parameters when in rendering state");
00808         deleteCache();
00809         parameter = param;
00810     }
00811     
00813 
00816     const Parameter &getParameter() const
00817     {
00818         return parameter;
00819     }
00820 protected:
00822 
00830     Glyph *makeGlyph(FT_GlyphSlot glyph)
00831     {
00832         return dynamic_cast<Glyph*>(new GlyphType(glyph, parameter));
00833     }
00834 private:
00835     BasicFont(const BasicFont<GlyphType> &font);
00836     BasicFont& operator=(const BasicFont<GlyphType> &font);
00837     int stateSet;
00838     
00839     Parameter parameter;
00840 };
00841 
00842 }
00843 
00844 #endif
00845 

Generated on Mon Jan 8 12:08:37 2007 for GLttf by  doxygen 1.5.1