Commit 37580053b491b69284988ed25cbbf6e884151eb0

Werner Lemberg 2019-05-16T12:15:54

[truetype] Use 26.6 format for storing unscaled CVT values. If `CVAR' data is applied to variation fonts, fractional values are possible. * include/freetype/internal/tttypes.h (TT_FaceRec): Change type of `cvt' from `FT_Short' to `FT_Int32'. * src/truetype/ttgxvar.c (FT_fdot6ToFixed): New macro. (tt_face_vary_cvt): Use it to update code to 26.6 format. * src/truetype/ttobjs.c (tt_size_run_prep): Update code to 26.6 format. * src/truetype/ttpload.c (tt_face_load_cvt): Stora data in 26.6 format.

diff --git a/ChangeLog b/ChangeLog
index 6aab65c..52ceba8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 2019-05-16  Werner Lemberg  <wl@gnu.org>
 
+	[truetype] Use 26.6 format for storing unscaled CVT values.
+
+	If `CVAR' data is applied to variation fonts, fractional values are
+	possible.
+
+	* include/freetype/internal/tttypes.h (TT_FaceRec): Change type of
+	`cvt' from `FT_Short' to `FT_Int32'.
+
+	* src/truetype/ttgxvar.c (FT_fdot6ToFixed): New macro.
+	(tt_face_vary_cvt): Use it to update code to 26.6 format.
+
+	* src/truetype/ttobjs.c (tt_size_run_prep): Update code to 26.6
+	format.
+
+	* src/truetype/ttpload.c (tt_face_load_cvt): Stora data in 26.6
+	format.
+
+2019-05-16  Werner Lemberg  <wl@gnu.org>
+
 	* src/truetype/ttgload.c (load_truetype_glyph): Init `unrounded'.
 
 	This fixes linear advance width values for spacing glyphs.  Bug
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 5e9f40e..cb03368 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -1395,8 +1395,10 @@ FT_BEGIN_HEADER
    *
    *   cvt ::
    *     The face's original control value table.  Coordinates are expressed
-   *     in unscaled font units.  Comes from the 'cvt~' table.  Ignored for
-   *     Type 2 fonts.
+   *     in unscaled font units (in 26.6 format).  Comes from the 'cvt~'
+   *     table.  Ignored for Type 2 fonts.
+   *
+   *     If varied by the `CVAR' table, non-integer values are possible.
    *
    *   interpreter ::
    *     A pointer to the TrueType bytecode interpreters field is also used
@@ -1633,7 +1635,7 @@ FT_BEGIN_HEADER
 
     /* the original, unscaled, control value table */
     FT_ULong              cvt_size;
-    FT_Short*             cvt;
+    FT_Int32*             cvt;
 
     /* A pointer to the bytecode interpreter to use.  This is also */
     /* used to hook the debugger for the `ttdebug' utility.        */
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index eab4239..00b91f6 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -72,6 +72,8 @@
           ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
 #define FT_intToFixed( i )                      \
           ( (FT_Fixed)( (FT_ULong)(i) << 16 ) )
+#define FT_fdot6ToFixed( i )                      \
+          ( (FT_Fixed)( (FT_ULong)(i) << 10 ) )
 #define FT_fixedToInt( x )                                    \
           ( (FT_Short)( ( (FT_ULong)(x) + 0x8000U ) >> 16 ) )
 #define FT_fixedToFdot6( x )                              \
@@ -3367,9 +3369,9 @@
           {
             FT_TRACE7(( "      %d: %f -> %f\n",
                         j,
-                        ( FT_intToFixed( face->cvt[j] ) +
+                        ( FT_fdot6ToFixed( face->cvt[j] ) +
                           old_cvt_delta ) / 65536.0,
-                        ( FT_intToFixed( face->cvt[j] ) +
+                        ( FT_fdot6ToFixed( face->cvt[j] ) +
                           cvt_deltas[j] ) / 65536.0 ));
             count++;
           }
@@ -3409,9 +3411,9 @@
           {
             FT_TRACE7(( "      %d: %f -> %f\n",
                         pindex,
-                        ( FT_intToFixed( face->cvt[pindex] ) +
+                        ( FT_fdot6ToFixed( face->cvt[pindex] ) +
                           old_cvt_delta ) / 65536.0,
-                        ( FT_intToFixed( face->cvt[pindex] ) +
+                        ( FT_fdot6ToFixed( face->cvt[pindex] ) +
                           cvt_deltas[pindex] ) / 65536.0 ));
             count++;
           }
@@ -3436,7 +3438,7 @@
     FT_TRACE5(( "\n" ));
 
     for ( i = 0; i < face->cvt_size; i++ )
-      face->cvt[i] += FT_fixedToInt( cvt_deltas[i] );
+      face->cvt[i] += FT_fixedToFdot6( cvt_deltas[i] );
 
   FExit:
     FT_FRAME_EXIT();
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 98a9fa4..d2279f1 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -939,15 +939,18 @@
     FT_Error        error;
     FT_UInt         i;
 
+    /* unscaled CVT values are already stored in 26.6 format */
+    FT_Fixed  scale = size->ttmetrics.scale >> 6;
+
 
     /* Scale the cvt values to the new ppem.            */
     /* By default, we use the y ppem value for scaling. */
     FT_TRACE6(( "CVT values:\n" ));
     for ( i = 0; i < size->cvt_size; i++ )
     {
-      size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
-      FT_TRACE6(( "  %3d: %d (%f)\n",
-                  i, face->cvt[i], size->cvt[i] / 64.0 ));
+      size->cvt[i] = FT_MulFix( face->cvt[i], scale );
+      FT_TRACE6(( "  %3d: %f (%f)\n",
+                  i, face->cvt[i] / 64.0, size->cvt[i] / 64.0 ));
     }
     FT_TRACE6(( "\n" ));
 
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index e7718bf..bc954c2 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -352,12 +352,12 @@
       goto Exit;
 
     {
-      FT_Short*  cur   = face->cvt;
-      FT_Short*  limit = cur + face->cvt_size;
+      FT_Int32*  cur   = face->cvt;
+      FT_Int32*  limit = cur + face->cvt_size;
 
 
       for ( ; cur < limit; cur++ )
-        *cur = FT_GET_SHORT();
+        *cur = FT_GET_SHORT() * 64;
     }
 
     FT_FRAME_EXIT();