Browse Source

Use array for glyph index to char code mapping.

aster2013 10 years ago
parent
commit
d34dd34fc9
2 changed files with 41 additions and 35 deletions
  1. 36 32
      Source/Urho3D/UI/FontFaceFreeType.cpp
  2. 5 3
      Source/Urho3D/UI/FontFaceFreeType.h

+ 36 - 32
Source/Urho3D/UI/FontFaceFreeType.cpp

@@ -70,9 +70,9 @@ private:
 
 
 FontFaceFreeType::FontFaceFreeType(Font* font) :
 FontFaceFreeType::FontFaceFreeType(Font* font) :
 FontFace(font),
 FontFace(font),
-    face_(0)
+    face_(0), 
+    loadMode_(FT_LOAD_DEFAULT)
 {
 {
-
 }
 }
 
 
 FontFaceFreeType::~FontFaceFreeType()
 FontFaceFreeType::~FontFaceFreeType()
@@ -87,10 +87,12 @@ FontFaceFreeType::~FontFaceFreeType()
 bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize, int pointSize)
 bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize, int pointSize)
 {
 {
     Context* context = font_->GetContext();
     Context* context = font_->GetContext();
+
     // Create & initialize FreeType library if it does not exist yet
     // Create & initialize FreeType library if it does not exist yet
     FreeTypeLibrary* freeType = font_->GetSubsystem<FreeTypeLibrary>();
     FreeTypeLibrary* freeType = font_->GetSubsystem<FreeTypeLibrary>();
     if (!freeType)
     if (!freeType)
         context->RegisterSubsystem(freeType = new FreeTypeLibrary(context));
         context->RegisterSubsystem(freeType = new FreeTypeLibrary(context));
+
     // Ensure the FreeType library is kept alive as long as TTF font resources exist
     // Ensure the FreeType library is kept alive as long as TTF font resources exist
     freeType_ = freeType;
     freeType_ = freeType;
 
 
@@ -129,22 +131,25 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
 
 
     face_ = face;
     face_ = face;
 
 
-    FT_UInt glyphIndex;
-    unsigned numGlyphs = 0;
-    HashMap<unsigned, unsigned> indexToCharMapping;
+    unsigned numGlyphs = face->num_glyphs;
+    LOGDEBUGF("Font face %s (%dpt) has %d glyphs", GetFileName(font_->GetName()).CString(), pointSize, numGlyphs);
+    
+    PODVector<unsigned> charCodes(numGlyphs);
+    for (unsigned i = 0; i < numGlyphs; ++i)
+        charCodes[i] = 0;
 
 
+    FT_UInt glyphIndex;
     FT_ULong charCode = FT_Get_First_Char(face, &glyphIndex);
     FT_ULong charCode = FT_Get_First_Char(face, &glyphIndex);
     while (glyphIndex != 0)
     while (glyphIndex != 0)
     {
     {
-        numGlyphs = Max((int)glyphIndex + 1, (int)numGlyphs);
-        indexToCharMapping[glyphIndex] = charCode;
+        if (glyphIndex < numGlyphs)
+            charCodes[glyphIndex] = charCode;
+
         charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
         charCode = FT_Get_Next_Char(face, charCode, &glyphIndex);
     }
     }
 
 
-    LOGDEBUGF("Font face %s (%dpt) has %d glyphs", GetFileName(font_->GetName()).CString(), pointSize, numGlyphs);
-
     // Load each of the glyphs to see the sizes & store other information
     // Load each of the glyphs to see the sizes & store other information
-    int loadMode = ui->GetForceAutoHint() ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_DEFAULT;
+    loadMode_ = ui->GetForceAutoHint() ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_DEFAULT;
     ascender_ = face->size->metrics.ascender >> 6;
     ascender_ = face->size->metrics.ascender >> 6;
     int descender = face->size->metrics.descender >> 6;
     int descender = face->size->metrics.descender >> 6;
 
 
@@ -164,7 +169,7 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
 
 
     int textureWidth = maxTextureSize;
     int textureWidth = maxTextureSize;
     int textureHeight = maxTextureSize;
     int textureHeight = maxTextureSize;
-    bool loadAllGlyphs = CanLoadAllGlyphs(numGlyphs, indexToCharMapping, loadMode, textureWidth, textureHeight);
+    bool loadAllGlyphs = CanLoadAllGlyphs(charCodes, textureWidth, textureHeight);
 
 
     SharedPtr<Image> image(new Image(font_->GetContext()));
     SharedPtr<Image> image(new Image(font_->GetContext()));
     image->SetSize(textureWidth, textureHeight, 1);
     image->SetSize(textureWidth, textureHeight, 1);
@@ -174,7 +179,10 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
 
 
     for (unsigned i = 0; i < numGlyphs; ++i)
     for (unsigned i = 0; i < numGlyphs; ++i)
     {
     {
-        unsigned charCode = indexToCharMapping[i];
+        unsigned charCode = charCodes[i];
+        if (charCode == 0)
+            continue;
+        
         if (!loadAllGlyphs && (charCode > 0xff))
         if (!loadAllGlyphs && (charCode > 0xff))
             break;
             break;
 
 
@@ -194,9 +202,9 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
     {
     {
         // Read kerning manually to be more efficient and avoid out of memory crash when use large font file, for example there
         // Read kerning manually to be more efficient and avoid out of memory crash when use large font file, for example there
         // are 29354 glyphs in msyh.ttf
         // are 29354 glyphs in msyh.ttf
-        FT_ULong tag = FT_MAKE_TAG('k', 'e', 'r', 'n');
+        FT_ULong tagKern = FT_MAKE_TAG('k', 'e', 'r', 'n');
         FT_ULong kerningTableSize = 0;
         FT_ULong kerningTableSize = 0;
-        FT_Error error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &kerningTableSize);
+        FT_Error error = FT_Load_Sfnt_Table(face, tagKern, 0, NULL, &kerningTableSize);
         if (error)
         if (error)
         {
         {
             LOGERROR("Could not get kerning table length");
             LOGERROR("Could not get kerning table length");
@@ -204,7 +212,7 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
         }
         }
 
 
         SharedArrayPtr<unsigned char> kerningTable(new unsigned char[kerningTableSize]);
         SharedArrayPtr<unsigned char> kerningTable(new unsigned char[kerningTableSize]);
-        error = FT_Load_Sfnt_Table(face, tag, 0, kerningTable, &kerningTableSize);
+        error = FT_Load_Sfnt_Table(face, tagKern, 0, kerningTable, &kerningTableSize);
         if (error)
         if (error)
         {
         {
             LOGERROR("Could not load kerning table");
             LOGERROR("Could not load kerning table");
@@ -238,15 +246,13 @@ bool FontFaceFreeType::Load(const unsigned char* fontData, unsigned fontDataSize
                         unsigned rightIndex = deserializer.ReadUShort();
                         unsigned rightIndex = deserializer.ReadUShort();
                         short amount = (short)(deserializer.ReadShort() >> 6);
                         short amount = (short)(deserializer.ReadShort() >> 6);
 
 
-                        HashMap<unsigned, unsigned>::ConstIterator leftIter = indexToCharMapping.Find(leftIndex);
-                        HashMap<unsigned, unsigned>::ConstIterator rightIter = indexToCharMapping.Find(rightIndex);
-                        if (leftIter != indexToCharMapping.End() && rightIter != indexToCharMapping.End())
+                        unsigned leftCharCode = leftIndex < numGlyphs ? charCodes[leftIndex] : 0;
+                        unsigned rightCharCode = rightIndex < numGlyphs ? charCodes[rightIndex] : 0;
+                        if (leftCharCode != 0 && rightCharCode != 0)
                         {
                         {
-                            unsigned value = (leftIter->second_ << 16) + rightIter->second_;
+                            unsigned value = (leftCharCode << 16) + rightCharCode;
                             kerningMapping_[value] = amount;
                             kerningMapping_[value] = amount;
                         }
                         }
-                        else
-                            LOGWARNING("Out of range glyph index in kerning information");
                     }
                     }
                 }
                 }
                 else
                 else
@@ -296,16 +302,20 @@ const FontGlyph* FontFaceFreeType::GetGlyph(unsigned c)
     return 0;
     return 0;
 }
 }
 
 
-bool FontFaceFreeType::CanLoadAllGlyphs(unsigned numGlyphs, HashMap<unsigned, unsigned>& indexToCharMapping, int loadMode, int& textureWidth, int& textureHeight) const
+bool FontFaceFreeType::CanLoadAllGlyphs(const PODVector<unsigned>& charCodes, int& textureWidth, int& textureHeight) const
 {
 {
     FT_Face face = (FT_Face)face_;
     FT_Face face = (FT_Face)face_;
     FT_GlyphSlot slot = face->glyph;
     FT_GlyphSlot slot = face->glyph;
     AreaAllocator allocator(FONT_TEXTURE_MIN_SIZE, FONT_TEXTURE_MIN_SIZE, textureWidth, textureHeight);
     AreaAllocator allocator(FONT_TEXTURE_MIN_SIZE, FONT_TEXTURE_MIN_SIZE, textureWidth, textureHeight);
 
 
+    unsigned numGlyphs = charCodes.Size();
     for (unsigned i = 0; i < numGlyphs; ++i)
     for (unsigned i = 0; i < numGlyphs; ++i)
     {
     {
-        unsigned charCode = indexToCharMapping[i];
-        FT_Error error = FT_Load_Char(face, charCode, loadMode);
+        unsigned charCode = charCodes[i];
+        if (charCode == 0)
+            continue;
+
+        FT_Error error = FT_Load_Char(face, charCode, loadMode_);
         if (!error)
         if (!error)
         {
         {
             int width = Max(slot->metrics.width >> 6, slot->bitmap.width);
             int width = Max(slot->metrics.width >> 6, slot->bitmap.width);
@@ -348,11 +358,8 @@ bool FontFaceFreeType::LoadCharGlyph(unsigned charCode, Image* image)
     FT_Face face = (FT_Face)face_;
     FT_Face face = (FT_Face)face_;
     FT_GlyphSlot slot = face->glyph;
     FT_GlyphSlot slot = face->glyph;
 
 
-    UI* ui = font_->GetSubsystem<UI>();
-    int loadMode = ui->GetForceAutoHint() ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_DEFAULT;
-
     FontGlyph fontGlyph;
     FontGlyph fontGlyph;
-    FT_Error error = FT_Load_Char(face, charCode, loadMode);
+    FT_Error error = FT_Load_Char(face, charCode, loadMode_);
     if (!error)
     if (!error)
     {
     {
         // Note: position within texture will be filled later
         // Note: position within texture will be filled later
@@ -367,8 +374,7 @@ bool FontFaceFreeType::LoadCharGlyph(unsigned charCode, Image* image)
             int x, y;
             int x, y;
             if (!allocator_.Allocate(fontGlyph.width_ + 1, fontGlyph.height_ + 1, x, y))
             if (!allocator_.Allocate(fontGlyph.width_ + 1, fontGlyph.height_ + 1, x, y))
             {
             {
-                int textureSize = ui->GetMaxFontTextureSize();
-                if (!SetupNextTexture(textureSize, textureSize))
+                if (!SetupNextTexture(allocator_.GetWidth(), allocator_.GetHeight()))
                     return false;
                     return false;
 
 
                 if (!allocator_.Allocate(fontGlyph.width_ + 1, fontGlyph.height_ + 1, x, y))
                 if (!allocator_.Allocate(fontGlyph.width_ + 1, fontGlyph.height_ + 1, x, y))
@@ -445,6 +451,4 @@ bool FontFaceFreeType::LoadCharGlyph(unsigned charCode, Image* image)
     return true;
     return true;
 }
 }
 
 
-
-
 }
 }

+ 5 - 3
Source/Urho3D/UI/FontFaceFreeType.h

@@ -48,7 +48,7 @@ public:
 
 
 private:
 private:
     /// Check can load all glyph in one texture, return true and texture size if can load.
     /// Check can load all glyph in one texture, return true and texture size if can load.
-    bool CanLoadAllGlyphs(unsigned numGlyphs, HashMap<unsigned, unsigned>& indexToCharMapping, int loadMode, int& textureWidth, int& textureHeight) const;
+    bool CanLoadAllGlyphs(const PODVector<unsigned>& charCodes, int& textureWidth, int& textureHeight) const;
     /// Setup next texture.
     /// Setup next texture.
     bool SetupNextTexture(int textureWidth, int textureHeight);
     bool SetupNextTexture(int textureWidth, int textureHeight);
     /// Load char glyph.
     /// Load char glyph.
@@ -58,10 +58,12 @@ private:
     SharedPtr<FreeTypeLibrary> freeType_;
     SharedPtr<FreeTypeLibrary> freeType_;
     /// FreeType face. Non-null after creation only in dynamic mode.
     /// FreeType face. Non-null after creation only in dynamic mode.
     void* face_;
     void* face_;
-    /// Has mutable glyph.
-    bool hasMutableGlyph_;
+    /// Load mode.
+    int loadMode_;
     /// Ascender.
     /// Ascender.
     int ascender_;
     int ascender_;
+    /// Has mutable glyph.
+    bool hasMutableGlyph_;
     /// Glyph area allocator.
     /// Glyph area allocator.
     AreaAllocator allocator_;
     AreaAllocator allocator_;
 };
 };