[aseprite] 61/196: Add a simple cache system for glyphs

Tobias Hansen thansen at moszumanska.debian.org
Wed Apr 20 18:50:01 UTC 2016


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository aseprite.

commit dbf5d69219403341dd549a19ed47322d8650c5b7
Author: David Capello <davidcapello at gmail.com>
Date:   Mon Mar 14 12:09:45 2016 -0300

    Add a simple cache system for glyphs
---
 src/app/util/freetype_utils.cpp  |  6 +--
 src/ft/face.h                    | 86 +++++++++++++++++++++++++++++++++-------
 src/ft/freetype_headers.h        |  1 +
 src/she/common/generic_surface.h |  8 ++--
 4 files changed, 80 insertions(+), 21 deletions(-)

diff --git a/src/app/util/freetype_utils.cpp b/src/app/util/freetype_utils.cpp
index 6187ba0..69c4b66 100644
--- a/src/app/util/freetype_utils.cpp
+++ b/src/app/util/freetype_utils.cpp
@@ -50,12 +50,12 @@ doc::Image* render_text(const std::string& fontfile, int fontsize,
 
       face.forEachGlyph(
         begin, end,
-        [&bounds, &image, color, antialias](FT_GlyphSlot glyph, int x) {
-          int t, yimg = - bounds.y - glyph->bitmap_top;
+        [&bounds, &image, color, antialias](FT_BitmapGlyph glyph, int x) {
+          int t, yimg = - bounds.y - glyph->top;
 
           for (int v=0; v<(int)glyph->bitmap.rows; ++v, ++yimg) {
             const uint8_t* p = glyph->bitmap.buffer + v*glyph->bitmap.pitch;
-            int ximg = x - bounds.x + glyph->bitmap_left;
+            int ximg = x - bounds.x + glyph->left;
             int bit = 0;
 
             for (int u=0; u<(int)glyph->bitmap.width; ++u, ++ximg) {
diff --git a/src/ft/face.h b/src/ft/face.h
index 19657bb..0abfed4 100644
--- a/src/ft/face.h
+++ b/src/ft/face.h
@@ -12,6 +12,8 @@
 #include "ft/freetype_headers.h"
 #include "gfx/rect.h"
 
+#include <map>
+
 namespace ft {
 
   template<typename Cache>
@@ -63,10 +65,11 @@ namespace ft {
           x += kerning.x >> 6;
         }
 
-        FT_GlyphSlot glyph = m_cache.loadGlyph(m_face, glyph_index, m_antialias);
+        FT_Glyph glyph = m_cache.loadGlyph(m_face, glyph_index, m_antialias);
         if (glyph) {
-          callback(glyph, x);
-          x += glyph->advance.x >> 6;
+          callback((FT_BitmapGlyph)glyph, x);
+          x += glyph->advance.x >> 16;
+          m_cache.doneGlyph(glyph);
         }
 
         prev_glyph = glyph_index;
@@ -79,11 +82,11 @@ namespace ft {
 
       forEachGlyph(
         first, end,
-        [&bounds](FT_GlyphSlot glyph, int x) {
-          bounds |= gfx::Rect(x + glyph->bitmap_left,
-                              -glyph->bitmap_top,
-                              (int)glyph->bitmap.width,
-                              (int)glyph->bitmap.rows);
+        [&bounds](FT_BitmapGlyph glyph, int x) {
+          bounds |= gfx::Rect(x + glyph->left,
+                              -glyph->top,
+                              glyph->bitmap.width,
+                              glyph->bitmap.rows);
         });
 
       return bounds;
@@ -107,22 +110,77 @@ namespace ft {
       return FT_Get_Char_Index(face, charCode);
     }
 
-    FT_GlyphSlot loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
+    FT_Glyph loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
       FT_Error err = FT_Load_Glyph(
         face, glyphIndex,
         FT_LOAD_RENDER |
-        FT_LOAD_NO_BITMAP |
         (antialias ? FT_LOAD_TARGET_NORMAL:
                      FT_LOAD_TARGET_MONO));
-      if (!err)
-        return face->glyph;
-      else
+      if (err)
+        return nullptr;
+
+      FT_Glyph glyph;
+      err = FT_Get_Glyph(face->glyph, &glyph);
+      if (err)
         return nullptr;
+
+      if (glyph->format != FT_GLYPH_FORMAT_BITMAP) {
+        err = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1);
+        if (!err) {
+          FT_Done_Glyph(glyph);
+          return nullptr;
+        }
+      }
+
+      return glyph;
+    }
+
+    void doneGlyph(FT_Glyph glyph) {
+      FT_Done_Glyph(glyph);
+    }
+
+  };
+
+  class SimpleCache : public NoCache {
+  public:
+    ~SimpleCache() {
+      invalidate();
     }
 
+    void invalidate() {
+      for (auto& it : m_glyphMap)
+        FT_Done_Glyph(it.second);
+
+      m_glyphMap.clear();
+    }
+
+    FT_Glyph loadGlyph(FT_Face face, FT_UInt glyphIndex, bool antialias) {
+      auto it = m_glyphMap.find(glyphIndex);
+      if (it != m_glyphMap.end())
+        return it->second;
+
+      FT_Glyph glyph = NoCache::loadGlyph(face, glyphIndex, antialias);
+      if (glyph) {
+        FT_Glyph newGlyph = nullptr;
+        FT_Glyph_Copy(glyph, &newGlyph);
+        if (newGlyph) {
+          m_glyphMap[glyphIndex] = newGlyph;
+          FT_Done_Glyph(glyph);
+          return newGlyph;
+        }
+      }
+      return glyph;
+    }
+
+    void doneGlyph(FT_Glyph glyph) {
+      // Do nothing
+    }
+
+  private:
+    std::map<FT_UInt, FT_Glyph> m_glyphMap;
   };
 
-  typedef FaceT<NoCache> Face;
+  typedef FaceT<SimpleCache> Face;
 
 } // namespace ft
 
diff --git a/src/ft/freetype_headers.h b/src/ft/freetype_headers.h
index eeb196b..b7a5147 100644
--- a/src/ft/freetype_headers.h
+++ b/src/ft/freetype_headers.h
@@ -8,6 +8,7 @@
 #define FT_FREETYPE_HEADERS_H_INCLUDED
 #pragma once
 
+#include "freetype/ftglyph.h"
 #include "ft2build.h"
 #include FT_FREETYPE_H
 
diff --git a/src/she/common/generic_surface.h b/src/she/common/generic_surface.h
index cafd1fd..ff2f195 100644
--- a/src/she/common/generic_surface.h
+++ b/src/she/common/generic_surface.h
@@ -149,14 +149,14 @@ public:
 
         ttFont->face().forEachGlyph(
           str.begin(), str.end(),
-          [&](FT_GlyphSlot glyph, int local_x) {
+          [this, x, y, fg, fg_alpha, bg, antialias, &clip, &bounds, &fd](FT_BitmapGlyph glyph, int local_x) {
+            int dst_y = y - bounds.y - glyph->top;
             int t;
 
-            for (int v=0; v<(int)glyph->bitmap.rows; ++v) {
+            for (int v=0; v<(int)glyph->bitmap.rows; ++v, ++dst_y) {
               const uint8_t* p = glyph->bitmap.buffer + v*glyph->bitmap.pitch;
               int bit = 0;
-              int dst_x = x + local_x - bounds.x + glyph->bitmap_left;
-              int dst_y = y - bounds.y - glyph->bitmap_top + v;
+              int dst_x = x + local_x - bounds.x + glyph->left;
 
               if (!clip.contains(gfx::Point(dst_x, dst_y)))
                 break;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git



More information about the Pkg-games-commits mailing list