Commit be15811c4602a1c2584684eb7ed5242e2bf16a5e

suzuki toshiya 2023-05-03T01:31:37

[t1cid] Improve cid_get_cid_from_glyph_index(). Update cid_get_cid_from_glyph_index() to return an error and CID=0 in the case that the specified glyph index points to an invalid entry. cidgload.h (cid_compute_fd_and_offsets): Declare new helper function to set the fd_select and 2 offsets to access the glyph description data. cidgload.c (cid_compute_fd_and_offsets): Move the part loading fd_select and 2 offsets from cid_load_glyph() to here. If the loaded parameters are broken, return the Invalid_Offset error. This function does not load the glyph data, only fills these parameters. (cid_load_glyph): Use new helper function in above. cidriver.c (cid_get_cid_from_glyph_index): Check whether the requested glyph index points to a valid entry, by calling cid_compute_fd_and_offsets(). If it is valid, fill the cid by the glyph index (=CID). If it is invalid, return an error and fill the cid by 0.

diff --git a/src/cid/cidgload.c b/src/cid/cidgload.c
index f4fe582..babaf95 100644
--- a/src/cid/cidgload.c
+++ b/src/cid/cidgload.c
@@ -40,6 +40,108 @@
 #define FT_COMPONENT  cidgload
 
 
+  /*
+   * A helper function to compute FD number (fd_select),
+   * the offset to the head of the glyph data (off1),
+   * and the offset to the and of the glyph data (off2).
+   *
+   * The number how many times cid_get_offset() is invoked
+   * can be controlled by the number how many non-NULL
+   * arguments are given.  If fd_select is non-NULL but
+   * off1 and off2 are NULL, cid_get_offset() is invoked
+   * only for fd_select, off1/off2 are not validated.
+   *
+   */
+  FT_LOCAL_DEF( FT_Error )
+  cid_compute_fd_and_offsets( CID_Face    face,
+                              FT_UInt     glyph_index,
+                              FT_ULong*   fd_select_p,
+                              FT_ULong*   off1_p,
+                              FT_ULong*   off2_p )
+  {
+    FT_Error      error  =  FT_Err_Ok;
+    CID_FaceInfo  cid    = &face->cid;
+    FT_Stream     stream =  face->cid_stream;
+    FT_UInt       entry_len = cid->fd_bytes + cid->gd_bytes;
+    FT_Byte*      p;
+    FT_Bool       need_frame_exit = 0;
+    FT_ULong      fd_select, off1, off2;
+
+
+    /* For ordinary fonts read the CID font dictionary index */
+    /* and charstring offset from the CIDMap.                */
+
+    if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset +
+                         glyph_index * entry_len )               ||
+         FT_FRAME_ENTER( 2 * entry_len )                         )
+      goto Exit;
+
+    need_frame_exit = 1;
+
+    p = (FT_Byte*)stream->cursor;
+    fd_select = cid_get_offset( &p, cid->fd_bytes );
+    off1      = cid_get_offset( &p, cid->gd_bytes );
+
+    p += cid->fd_bytes;
+    off2      = cid_get_offset( &p, cid->gd_bytes );
+
+    if (fd_select_p)
+      *fd_select_p = fd_select;
+
+    if (off1_p)
+      *off1_p = off1;
+
+    if (off2_p)
+      *off2_p = off2;
+  
+    if ( fd_select >= cid->num_dicts )
+    {
+      /*
+       * fd_select == 0xFF is often used to indicate that the CID
+       * has no charstring to be rendered, similar to GID = 0xFFFF
+       * in TrueType fonts.
+       */
+      if ( (cid->fd_bytes == 1 && fd_select == 0xFFU   ) ||
+           (cid->fd_bytes == 2 && fd_select == 0xFFFFU ) )
+      {
+        FT_TRACE1(( "cid_load_glyph: fail for glyph_index=%d, "
+                    "FD number %ld is the max integer fitting into %d byte%s\n",
+                    glyph_index, fd_select, cid->fd_bytes,
+                    cid->fd_bytes == 1 ? "" : "s" ));
+      }
+      else
+      {
+        FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
+                    "FD number %ld > number of dicts %d\n",
+                    glyph_index, fd_select, cid->num_dicts ));
+      }
+      error = FT_THROW( Invalid_Offset );
+      goto Exit;
+    }
+    else if ( off2 > stream->size )
+    {
+      FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
+                  "end of the glyph data is beyond the data stream\n",
+                  glyph_index ));
+      error = FT_THROW( Invalid_Offset );
+      goto Exit;
+    }
+    else if ( off1 > off2 )
+    {
+      FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
+                  "the end position of glyph data is set before the start position\n",
+                  glyph_index ));
+      error = FT_THROW( Invalid_Offset );
+    }
+
+    Exit:
+      if ( need_frame_exit )
+        FT_FRAME_EXIT();
+
+    return error; 
+  }
+
+
   FT_CALLBACK_DEF( FT_Error )
   cid_load_glyph( T1_Decoder  decoder,
                   FT_UInt     glyph_index )
@@ -97,67 +199,14 @@
     else
 
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
-
-    /* For ordinary fonts read the CID font dictionary index */
-    /* and charstring offset from the CIDMap.                */
     {
-      FT_UInt   entry_len = cid->fd_bytes + cid->gd_bytes;
       FT_ULong  off1, off2;
 
 
-      if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset +
-                           glyph_index * entry_len )               ||
-           FT_FRAME_ENTER( 2 * entry_len )                         )
-        goto Exit;
-
-      p         = (FT_Byte*)stream->cursor;
-      fd_select = cid_get_offset( &p, cid->fd_bytes );
-      off1      = cid_get_offset( &p, cid->gd_bytes );
-      p        += cid->fd_bytes;
-      off2      = cid_get_offset( &p, cid->gd_bytes );
-      FT_FRAME_EXIT();
-
-  
-      if ( fd_select >= cid->num_dicts )
-      {
-        /*
-         * fd_select == 0xFF is often used to indicate that the CID
-         * has no charstring to be rendered, similar to GID = 0xFFFF
-         * in TrueType fonts.
-         */
-        if ( (cid->fd_bytes == 1 && fd_select == 0xFFU   ) ||
-             (cid->fd_bytes == 2 && fd_select == 0xFFFFU ) )
-        {
-          FT_TRACE1(( "cid_load_glyph: fail for glyph_index=%d, "
-                      "FD number %ld is the max integer fitting into %d byte%s\n",
-                      glyph_index, fd_select, cid->fd_bytes,
-                      cid->fd_bytes == 1 ? "" : "s" ));
-        }
-        else
-        {
-          FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
-                      "FD number %ld > number of dicts %d\n",
-                      glyph_index, fd_select, cid->num_dicts ));
-        }
-        error = FT_THROW( Invalid_Offset );
-        goto Exit;
-      }
-      else if ( off2 > stream->size )
-      {
-        FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
-                    "end of the glyph data is beyond the data stream\n",
-                    glyph_index ));
-        error = FT_THROW( Invalid_Offset );
-        goto Exit;
-      }
-      else if ( off1 > off2 )
-      {
-        FT_TRACE0(( "cid_load_glyph: fail for glyph_index=%d, "
-                    "the end position of glyph data is set before the start position\n",
-                    glyph_index ));
-        error = FT_THROW( Invalid_Offset );
+      error = cid_compute_fd_and_offsets( face, glyph_index,
+                                          &fd_select, &off1, &off2 );
+      if ( error )
         goto Exit;
-      }
 
       glyph_length = off2 - off1;
 
diff --git a/src/cid/cidgload.h b/src/cid/cidgload.h
index 97954d4..edd6229 100644
--- a/src/cid/cidgload.h
+++ b/src/cid/cidgload.h
@@ -42,6 +42,14 @@ FT_BEGIN_HEADER
                        FT_Int32      load_flags );
 
 
+  FT_LOCAL( FT_Error )
+  cid_compute_fd_and_offsets( CID_Face   face,
+                              FT_UInt    glyph_index,
+                              FT_ULong*  fd_select_p,
+                              FT_ULong*  off1_p,
+                              FT_ULong*  off2_p );
+
+
 FT_END_HEADER
 
 #endif /* CIDGLOAD_H_ */
diff --git a/src/cid/cidriver.c b/src/cid/cidriver.c
index f749923..10cb8c1 100644
--- a/src/cid/cidriver.c
+++ b/src/cid/cidriver.c
@@ -150,11 +150,23 @@
                                 FT_UInt  *cid )
   {
     FT_Error  error = FT_Err_Ok;
-    FT_UNUSED( face );
 
 
-    if ( cid )
-      *cid = glyph_index; /* identity mapping */
+    /*
+     * Currently, FreeType does not support an incrementally-
+     * defined CID-keyed font that stores the glyph description
+     * data in /GlyphDirectory array or dictionary.
+     * Thus the font loaded by the incremental loading feature
+     * is not handled in here.
+     */
+    error = cid_compute_fd_and_offsets( face, glyph_index,
+                                        NULL, NULL, NULL );
+
+
+    if ( error )
+      *cid = 0;
+    else
+      *cid = glyph_index;
 
     return error;
   }