summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Röttsches <drott@chromium.org>2022-06-29 11:48:53 +0300
committerWerner Lemberg <wl@gnu.org>2022-06-29 20:27:11 +0200
commitdece9535164696777c1ae0000b399c470c306d6d (patch)
tree2380c0612dfb90e417c082ef734c871bf2bdbbf9
parent15fef219d6ed191ef09efad4d8a3a4f4d2b7158b (diff)
downloadfreetype2-dece9535164696777c1ae0000b399c470c306d6d.tar.gz
[truetype] Perform variation store delta computation with 64-bit precision.
* include/freetype/internal/ftmmtypes.h (FT_ItemVarDelta): Make type explicitly 32-bit. * include/freetype/internal/services/svmm.h (FT_Var_Get_Item_Delta_Func): Change return type to `FT_ItemVarDelta` * truetype/ttgxvar.h (tt_var_get_item_delta): Change return type to `FT_ItemVarDelta`. * truetype/ttgxvar.c (tt_var_get_item_delta): Store scalars and deltas to intermediate array, perform computation using new method `FT_MulAddFix`.
-rw-r--r--include/freetype/internal/ftmmtypes.h2
-rw-r--r--include/freetype/internal/services/svmm.h2
-rw-r--r--src/truetype/ttgxvar.c46
-rw-r--r--src/truetype/ttgxvar.h2
4 files changed, 37 insertions, 15 deletions
diff --git a/include/freetype/internal/ftmmtypes.h b/include/freetype/internal/ftmmtypes.h
index 44f7e74dd..570c7fdd1 100644
--- a/include/freetype/internal/ftmmtypes.h
+++ b/include/freetype/internal/ftmmtypes.h
@@ -24,7 +24,7 @@
FT_BEGIN_HEADER
- typedef FT_Long FT_ItemVarDelta;
+ typedef FT_Int32 FT_ItemVarDelta;
typedef struct GX_ItemVarDataRec_
{
diff --git a/include/freetype/internal/services/svmm.h b/include/freetype/internal/services/svmm.h
index 22ddc8c66..b67ea7c60 100644
--- a/include/freetype/internal/services/svmm.h
+++ b/include/freetype/internal/services/svmm.h
@@ -109,7 +109,7 @@ FT_BEGIN_HEADER
FT_ULong offset,
GX_ItemVarStore itemStore );
- typedef FT_Int
+ typedef FT_ItemVarDelta
(*FT_Var_Get_Item_Delta_Func)( FT_Face face,
GX_ItemVarStore itemStore,
FT_UInt outerIndex,
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 1bf9debb0..65fc7012c 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -939,19 +939,23 @@
}
- FT_LOCAL_DEF( FT_Int )
+ FT_LOCAL_DEF( FT_ItemVarDelta )
tt_var_get_item_delta( TT_Face face,
GX_ItemVarStore itemStore,
FT_UInt outerIndex,
FT_UInt innerIndex )
{
+ FT_Stream stream = FT_FACE_STREAM( face );
+ FT_Memory memory = stream->memory;
+ FT_Error error = FT_Err_Ok;
+
GX_ItemVarData varData;
FT_ItemVarDelta* deltaSet;
- FT_UInt master, j;
- FT_Fixed netAdjustment = 0; /* accumulated adjustment */
- FT_Fixed scaledDelta;
- FT_Fixed delta;
+ FT_UInt master, j;
+ FT_Fixed* scalars;
+ FT_ItemVarDelta returnValue;
+
/* OpenType 1.8.4+: No variation data for this item
* as indices have special value 0xFFFF. */
@@ -964,6 +968,9 @@
varData = &itemStore->varData[outerIndex];
deltaSet = &varData->deltaSet[varData->regionIdxCount * innerIndex];
+ if ( FT_QNEW_ARRAY( scalars, varData->regionIdxCount ) )
+ return 0;
+
/* outer loop steps through master designs to be blended */
for ( master = 0; master < varData->regionIdxCount; master++ )
{
@@ -1013,18 +1020,33 @@
FT_MulDiv( scalar,
axis->endCoord - face->blend->normalizedcoords[j],
axis->endCoord - axis->peakCoord );
- } /* per-axis loop */
- /* get the scaled delta for this region */
- delta = FT_intToFixed( deltaSet[master] );
- scaledDelta = FT_MulFix( scalar, delta );
+ } /* per-axis loop */
- /* accumulate the adjustments from each region */
- netAdjustment = netAdjustment + scaledDelta;
+ scalars[master] = scalar;
} /* per-region loop */
- return FT_fixedToInt( netAdjustment );
+
+ /* Compute the scaled delta for this region.
+ *
+ * From: https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables:
+ *
+ * `Fixed` is a 32-bit (16.16) type and, in the general case, requires
+ * 32-bit deltas. As described above, the `DeltaSet` record can
+ * accommodate deltas that are, logically, either 16-bit or 32-bit.
+ * When scaled deltas are applied to `Fixed` values, the `Fixed` value
+ * is treated like a 32-bit integer.
+ *
+ * `FT_MulAddFix` internally uses 64-bit precision; it thus can handle
+ * deltas ranging from small 8-bit to large 32-bit values that are
+ * applied to 16.16 `FT_Fixed` / OpenType `Fixed` values.
+ */
+ returnValue = FT_MulAddFix( scalars, deltaSet, varData->regionIdxCount );
+
+ FT_FREE( scalars );
+
+ return returnValue;
}
diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h
index 15c26373d..513c40b8a 100644
--- a/src/truetype/ttgxvar.h
+++ b/src/truetype/ttgxvar.h
@@ -391,7 +391,7 @@ FT_BEGIN_HEADER
GX_ItemVarStore itemStore,
FT_ULong table_len );
- FT_LOCAL( FT_Int )
+ FT_LOCAL( FT_ItemVarDelta )
tt_var_get_item_delta( TT_Face face,
GX_ItemVarStore itemStore,
FT_UInt outerIndex,