Repository: celiagg/celiagg (language: python)

Issue:
Fonts can't load all fonts from .ttc files with FreeType engine
Sometimes fonts are found in .ttc archive files which contain multiple related fonts.  In these cases you need to pass the index of the font in the file to free type as well as the file, I think here:

https://github.com/celiagg/celiagg/blob/1af9287ea193ca3e355526c4481cf6e34fa57bae/celiagg/font.cpp#L60

But that means that the Celiagg `Font` needs to have the index information available (and assume 0 if not provided).


Discussion / hints:
Sure enough, that's exactly where we can do this. The [Freetype docs](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_open_face) have more detail. (`face_index` is what that `0` gets passed as)

Fix patch:
diff --git a/celiagg/_font.pxd b/celiagg/_font.pxd
index 2e4c48f..febb5c7 100644
--- a/celiagg/_font.pxd
+++ b/celiagg/_font.pxd
@@ -28,7 +28,8 @@ cimport _enums
 
 cdef extern from "font.h":
     cdef cppclass Font:
-        Font(char* fileName, double height, _enums.FontCacheType ch)
+        Font(char* fileName, double height, _enums.FontCacheType ch,
+             unsigned face_index)
 
         _enums.FontCacheType cache_type() const
         bool hinting() const
@@ -36,3 +37,4 @@ cdef extern from "font.h":
         double height() const
         const char* filepath() const
         double string_width(char* str)
+        unsigned face_index() const
diff --git a/celiagg/font.cpp b/celiagg/font.cpp
index 1edf22b..9e2c29a 100644
--- a/celiagg/font.cpp
+++ b/celiagg/font.cpp
@@ -29,7 +29,7 @@
 
 #ifndef _ENABLE_TEXT_RENDERING
 // This is what happens when you disable font support!
-Font::Font(char const* fontName, double const height, FontCacheType const ch)
+Font::Font(char const* fontName, double const height, FontCacheType const ch, unsigned const face_index)
 : m_cache_type(ch) {}
 Font::~Font() {}
 
@@ -42,6 +42,7 @@ bool Font::hinting() const { return false; }
 void Font::hinting(bool const hint) {}
 const char* Font::filepath() const { return ""; }
 double Font::string_width(char const* str) { return 0.0; }
+unsigned Font::face_index() const { return 0; }
 void Font::transform(const agg::trans_affine& transform) {}
 
 #else
@@ -54,10 +55,11 @@ thread_local Font::FontEngine Font::m_font_engine;
 #endif
 thread_local Font::FontCacheManager Font::m_font_cache_manager(Font::m_font_engine);
 
-Font::Font(char const* fontName, double const height, FontCacheType const ch)
+Font::Font(char const* fontName, double const height, FontCacheType const ch, unsigned const face_index)
 : m_height(height)
 , m_font_name(fontName)
 , m_cache_type(ch)
+, m_face_index(face_index)
 {}
 
 Font::~Font()
@@ -78,8 +80,8 @@ Font::activate()
 {
 #ifdef _USE_FREETYPE
     m_font_engine.load_font(m_font_name.c_str(),
-                           0,
-                           (m_cache_type == VectorFontCache) ?
+                            m_face_index,
+                            (m_cache_type == VectorFontCache) ?
                                 agg::glyph_ren_outline :
                                 agg::glyph_ren_agg_gray8);
     m_font_engine.hinting(true);
@@ -151,6 +153,12 @@ Font::string_width(char const* str)
     return iterator.x_offset();
 }
 
+unsigned
+Font::face_index() const
+{
+    return m_face_index;
+}
+
 void
 Font::transform(const agg::trans_affine& transform)
 {
diff --git a/celiagg/font.h b/celiagg/font.h
index 549cb7f..46cd55c 100644
--- a/celiagg/font.h
+++ b/celiagg/font.h
@@ -61,7 +61,8 @@ class Font
 public:
 
                         Font(char const* fileName, double const height,
-                             FontCacheType const ch = RasterFontCache);
+                             FontCacheType const ch = RasterFontCache,
+                             unsigned const face_index = 0);
                         ~Font();
 
     void                activate();
@@ -78,6 +79,7 @@ class Font
     void                hinting(bool const hint);
     const char*         filepath() const;
     double              string_width(char const* str);
+    unsigned            face_index() const;
     void                transform(const agg::trans_affine& transform);
 
 private:
@@ -85,6 +87,7 @@ class Font
     double              m_height;
     std::string         m_font_name;
     FontCacheType       m_cache_type;
+    unsigned            m_face_index;
 
 #ifdef _ENABLE_TEXT_RENDERING
 #ifndef _USE_FREETYPE
diff --git a/celiagg/font.pxi b/celiagg/font.pxi
index 1f958fb..09be1be 100644
--- a/celiagg/font.pxi
+++ b/celiagg/font.pxi
@@ -35,25 +35,32 @@ IF _ENABLE_TEXT_RENDERING:
         :param path: A Unicode string containing the path of a ``Font`` file
         :param size: The size of the font
         :param cache_type: A ``FontCacheType``
+        :param face_index: For .ttc fonts, the index of the desired font within
+                           the collection.
         """
         cdef _font.Font* _this
 
-        def __cinit__(self, fontName, double size, FontCacheType ch):
+        def __cinit__(self, fontName, double size, FontCacheType ch,
+                      unsigned face_index=0):
             fontName = _get_utf8_text(fontName,
                                     "Font path must be a unicode string")
-            self._this = new _font.Font(fontName, size, ch)
+            self._this = new _font.Font(fontName, size, ch, face_index)
 
         def __dealloc__(self):
             del self._this
 
         def copy(self):
             return Font(self._this.filepath(), self._this.height(),
-                        self._this.cache_type())
+                        self._this.cache_type(), self._this.face_index())
 
         property cache_type:
             def __get__(self):
                 return FontCacheType(self._this.cache_type())
 
+        property face_index:
+            def __get__(self):
+                return self._this.face_index()
+
         property filepath:
             def __get__(self):
                 return self._this.filepath()


Test patch:
diff --git a/celiagg/tests/test_text.py b/celiagg/tests/test_text.py
index 9f46ee0..fd0817d 100644
--- a/celiagg/tests/test_text.py
+++ b/celiagg/tests/test_text.py
@@ -18,6 +18,7 @@ def test_font_byte_string(self):
             'Times New Roman',
             12.0,
             agg.FontCacheType.RasterFontCache,
+            face_index=1,
         )
         text_byte = b'Hello!'
         font_byte = agg.Font(