freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2] ot-svg-clean 4e729bb 2/2: Adds OT-SVG glyph support to FT Gl


From: Moazin Khatti
Subject: [freetype2] ot-svg-clean 4e729bb 2/2: Adds OT-SVG glyph support to FT Glyph Management API.
Date: Sat, 10 Aug 2019 14:52:41 -0400 (EDT)

branch: ot-svg-clean
commit 4e729bb89eec041c24e89882b7c3633038ca32d6
Author: Moazin Khatti <address@hidden>
Commit: Moazin Khatti <address@hidden>

    Adds OT-SVG glyph support to FT Glyph Management API.
    
    * include/freetype/ftglyph.h: Adds `FT_SvgGlyph' and
    `FT_SvgGlyphRec'.
    
    * src/base/ftglyph.c: Adds glyph class `ft_svg_glyph_class' and its
    methods. (FT_New_Glyph) Adds code to set the class of OT-SVG
    glyphs. (FT_Glyph_To_Bitmap) Adds code to free memory allocated for
    `FT_SVG_Document' in `dummy.other'.
---
 include/freetype/ftglyph.h |  70 +++++++++++++++++++
 src/base/ftglyph.c         | 167 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 237 insertions(+)

diff --git a/include/freetype/ftglyph.h b/include/freetype/ftglyph.h
index fedab84..95ecbb3 100644
--- a/include/freetype/ftglyph.h
+++ b/include/freetype/ftglyph.h
@@ -225,6 +225,76 @@ FT_BEGIN_HEADER
 
   /**************************************************************************
    *
+   * @type:
+   *   FT_SvgGlyph
+   *
+   * @description:
+   *   A handle to an object used to model an SVG glyph image.  This is a
+   *   sub-class of @FT_Glyph, and a pointer to @FT_SvgGlyphRec.
+   */
+  typedef struct FT_SvgGlyphRec_*  FT_SvgGlyph;
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_SvgGlyphRec
+   *
+   * @description:
+   *   A structure used for SVG glyph images.  This really is a 'sub-class'
+   *   of @FT_GlyphRec.
+   *
+   * @fields:
+   *   root ::
+   *     The root @FT_OutlineGlyphRec fields.
+   *
+   *   svg_document ::
+   *     A pointer to the SVG document.
+   *
+   *   svg_document_length ::
+   *     The length of the svg_document.
+   *
+   *   glyph_index ::
+   *     The index of the glyph to be rendered.
+   *
+   *   metrics ::
+   *     A metrics object storing the size information.
+   *
+   *   units_per_EM ::
+   *     The size of the EM square.
+   *
+   *   start_glyph_id ::
+   *     The starting glyph ID for the glyph range that this document has.
+   *
+   *   end_glyph_id ::
+   *     The ending glyph ID for the glyph range that this document has.
+   *
+   * @note:
+   *   `metrics` and `units_per_EM` might look like repetitions since both
+   *   fields are stored in face objects.  However, the Glyph Management API
+   *   requires an `FT_Glyph` to store all the information that completely
+   *   describes a glyph. Outline glyphs are themselves scaled thus they
+   *   don't need this information. However, SVG documents do. The field of
+   *   `units_per_EM` is needed because the SVG is to be scaled in case its
+   *   viewbox size differs from `units_per_EM`. For more info, refer to
+   *   the section _Coordinate Systems and Glyph Metrics_ of the OpenType
+   *   SVG specs.
+   */
+  typedef struct  FT_SvgGlyphRec_
+  {
+    FT_GlyphRec         root;
+    FT_Byte*            svg_document;
+    FT_ULong            svg_document_length;
+    FT_UInt             glyph_index;
+    FT_Size_Metrics     metrics;
+    FT_UShort           units_per_EM;
+    FT_UShort           start_glyph_id;
+    FT_UShort           end_glyph_id;
+    /* TODO: (OT-SVG) Maybe put a transformation matrix here */
+  } FT_SvgGlyphRec;
+
+
+  /**************************************************************************
+   *
    * @function:
    *   FT_New_Glyph
    *
diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c
index e6b1327..fa60ea1 100644
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -35,6 +35,7 @@
 #include FT_OUTLINE_H
 #include FT_BITMAP_H
 #include FT_INTERNAL_OBJECTS_H
+#include FT_OTSVG_H
 
 
   /**************************************************************************
@@ -275,6 +276,157 @@
     ft_outline_glyph_prepare    /* FT_Glyph_PrepareFunc    glyph_prepare   */
   )
 
+#ifdef FT_CONFIG_OPTION_SVG
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
+  /****   FT_SvgGlyph support                                           ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ft_svg_glyph_init( FT_Glyph      svg_glyph,
+                     FT_GlyphSlot  slot )
+  {
+    FT_ULong         doc_length;
+    FT_SVG_Document  document;
+    FT_SvgGlyph      glyph   = (FT_SvgGlyph)svg_glyph;
+    FT_Error         error   = FT_Err_Ok;
+    FT_Memory        memory  = FT_GLYPH( glyph )->library->memory;
+
+
+    if ( slot->format != FT_GLYPH_FORMAT_SVG )
+    {
+      error = FT_THROW( Invalid_Glyph_Format );
+      goto Exit;
+    }
+
+    if ( slot->other == NULL )
+    {
+      error = FT_THROW( Invalid_Slot_Handle );
+      goto Exit;
+    }
+
+    document = (FT_SVG_Document)slot->other;
+
+    if ( document->svg_document_length == 0 )
+    {
+      error = FT_THROW( Invalid_Slot_Handle );
+      goto Exit;
+    }
+
+    /* allocate a new document */
+    doc_length                 = document->svg_document_length;
+    glyph->svg_document        = memory->alloc( memory, doc_length );
+    glyph->svg_document_length = doc_length;
+    glyph->glyph_index         = slot->glyph_index;
+    glyph->metrics             = document->metrics;
+    glyph->units_per_EM        = document->units_per_EM;
+    glyph->start_glyph_id      = document->start_glyph_id;
+    glyph->end_glyph_id        = document->end_glyph_id;
+    /* copy the document into glyph */
+    FT_MEM_COPY( glyph->svg_document, document->svg_document, doc_length );
+
+  Exit:
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( void )
+  ft_svg_glyph_done( FT_Glyph  svg_glyph )
+  {
+    FT_SvgGlyph  glyph  = (FT_SvgGlyph)svg_glyph;
+    FT_Memory    memory = svg_glyph->library->memory;
+
+    /* just free the memory */
+    memory->free( memory, glyph->svg_document );
+  }
+
+  FT_CALLBACK_DEF( FT_Error )
+  ft_svg_glyph_copy( FT_Glyph  svg_source,
+                     FT_Glyph  svg_target )
+  {
+    FT_SvgGlyph  source  = (FT_SvgGlyph)svg_source;
+    FT_SvgGlyph  target  = (FT_SvgGlyph)svg_target;
+    FT_Error     error   = FT_Err_Ok;
+    FT_Memory    memory  = FT_GLYPH( source )->library->memory;
+
+    if ( svg_source->format != FT_GLYPH_FORMAT_SVG )
+    {
+      error = FT_THROW( Invalid_Glyph_Format );
+      return error;
+    }
+
+    if ( source->svg_document_length == 0 )
+    {
+      error = FT_THROW( Invalid_Slot_Handle );
+      return error;
+    }
+
+
+    target->glyph_index         = source->glyph_index;
+    target->svg_document_length = source->svg_document_length;
+    target->metrics             = source->metrics;
+    target->units_per_EM        = source->units_per_EM;
+    target->start_glyph_id      = source->start_glyph_id;
+    target->end_glyph_id        = source->end_glyph_id;
+
+    /* allocate space for the svg document */
+    target->svg_document = memory->alloc( memory,
+                                          target->svg_document_length );
+
+    /* copy the stuff */
+    FT_MEM_COPY( target->svg_document,
+                 source->svg_document,
+                 target->svg_document_length );
+
+    return error;
+  }
+
+  FT_CALLBACK_DEF( FT_Error )
+  ft_svg_glyph_prepare( FT_Glyph     svg_glyph,
+                        FT_GlyphSlot slot )
+  {
+    FT_SvgGlyph   glyph  = (FT_SvgGlyph)svg_glyph;
+    FT_Error      error  = FT_Err_Ok;
+    FT_Memory     memory = svg_glyph->library->memory;
+
+    FT_SVG_Document  document;
+
+    if ( FT_NEW( document ) )
+      return error;
+
+    document->svg_document        = glyph->svg_document;
+    document->svg_document_length = glyph->svg_document_length;
+    document->metrics             = glyph->metrics;
+    document->units_per_EM        = glyph->units_per_EM;
+    document->start_glyph_id      = glyph->start_glyph_id;
+    document->end_glyph_id        = glyph->end_glyph_id;
+
+    slot->format      = FT_GLYPH_FORMAT_SVG;
+    slot->glyph_index = glyph->glyph_index;
+    slot->other       = document;
+
+    return error;
+  }
+
+  FT_DEFINE_GLYPH(
+    ft_svg_glyph_class,
+
+    sizeof ( FT_SvgGlyphRec ),
+    FT_GLYPH_FORMAT_SVG,
+
+    ft_svg_glyph_init,      /* FT_Glyph_InitFunc       glyph_init      */
+    ft_svg_glyph_done,      /* FT_Glyph_DoneFunc       glyph_done      */
+    ft_svg_glyph_copy,      /* FT_Glyph_CopyFunc       glyph_copy      */
+    NULL,                   /* FT_Glyph_TransformFunc  glyph_transform */
+    NULL,                   /* FT_Glyph_GetBBoxFunc    glyph_bbox      */
+    ft_svg_glyph_prepare    /* FT_Glyph_PrepareFunc    glyph_prepare   */
+  )
+
+#endif
 
   /*************************************************************************/
   /*************************************************************************/
@@ -376,6 +528,12 @@
     else if ( format == FT_GLYPH_FORMAT_OUTLINE )
       clazz = &ft_outline_glyph_class;
 
+#ifdef FT_CONFIG_OPTION_SVG
+    /* if it is a SVG glyph */
+    else if ( format == FT_GLYPH_FORMAT_SVG )
+      clazz = &ft_svg_glyph_class;
+#endif
+
     else
     {
       /* try to find a renderer that supports the glyph image format */
@@ -592,7 +750,16 @@
     /* prepare dummy slot for rendering */
     error = clazz->glyph_prepare( glyph, &dummy );
     if ( !error )
+    {
       error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
+#ifdef FT_CONFIG_OPTION_SVG
+      if ( clazz == &ft_svg_glyph_class )
+      {
+        FT_Memory  memory = library->memory;
+        FT_FREE( dummy.other );
+      }
+#endif
+    }
 
 #if 1
     if ( !destroy && origin )



reply via email to

[Prev in Thread] Current Thread [Next in Thread]