Werner Lemberg pushed to branch master
at FreeType / FreeType
Commits:
-
15fef219
by Dominik Röttsches
at 2022-06-29T20:12:04+02:00
New function `FT_MulAddFix` to compute the sum of fixed-point products.
This function, based on the code of `FT_MulFix`, uses 64-bit precision
internally for intermediate computations.
* include/freetype/internal/ftcalc.h, base/ftcalc.c (FT_MulAddFix):
Implement it.
-
dece9535
by Dominik Röttsches
at 2022-06-29T20:27:11+02:00
[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`.
6 changed files:
Changes:
include/freetype/internal/ftcalc.h
... |
... |
@@ -278,6 +278,40 @@ FT_BEGIN_HEADER |
278
|
278
|
FT_Long c );
|
279
|
279
|
|
280
|
280
|
|
|
281
|
+ /**************************************************************************
|
|
282
|
+ *
|
|
283
|
+ * @function:
|
|
284
|
+ * FT_MulAddFix
|
|
285
|
+ *
|
|
286
|
+ * @description:
|
|
287
|
+ * Compute `(s[0] * f[0] + s[1] * f[1] + ...) / 0x10000`, where `s[n]` is
|
|
288
|
+ * usually a 16.16 scalar.
|
|
289
|
+ *
|
|
290
|
+ * @input:
|
|
291
|
+ * s ::
|
|
292
|
+ * The array of scalars.
|
|
293
|
+ * f ::
|
|
294
|
+ * The array of factors.
|
|
295
|
+ * count ::
|
|
296
|
+ * The number of entries in the array.
|
|
297
|
+ *
|
|
298
|
+ * @return:
|
|
299
|
+ * The result of `(s[0] * f[0] + s[1] * f[1] + ...) / 0x10000`.
|
|
300
|
+ *
|
|
301
|
+ * @note:
|
|
302
|
+ * This function is currently used for the scaled delta computation of
|
|
303
|
+ * variation stores. It internally uses 64-bit data types when
|
|
304
|
+ * available, otherwise it emulates 64-bit math by using 32-bit
|
|
305
|
+ * operations, which produce a correct result but most likely at a slower
|
|
306
|
+ * performance in comparison to the implementation base on `int64_t`.
|
|
307
|
+ *
|
|
308
|
+ */
|
|
309
|
+ FT_BASE( FT_Int32 )
|
|
310
|
+ FT_MulAddFix( FT_Fixed* s,
|
|
311
|
+ FT_Int32* f,
|
|
312
|
+ FT_UInt count );
|
|
313
|
+
|
|
314
|
+
|
281
|
315
|
/*
|
282
|
316
|
* A variant of FT_Matrix_Multiply which scales its result afterwards. The
|
283
|
317
|
* idea is that both `a' and `b' are scaled by factors of 10 so that the
|
include/freetype/internal/ftmmtypes.h
... |
... |
@@ -24,7 +24,7 @@ |
24
|
24
|
FT_BEGIN_HEADER
|
25
|
25
|
|
26
|
26
|
|
27
|
|
- typedef FT_Long FT_ItemVarDelta;
|
|
27
|
+ typedef FT_Int32 FT_ItemVarDelta;
|
28
|
28
|
|
29
|
29
|
typedef struct GX_ItemVarDataRec_
|
30
|
30
|
{
|
include/freetype/internal/services/svmm.h
... |
... |
@@ -109,7 +109,7 @@ FT_BEGIN_HEADER |
109
|
109
|
FT_ULong offset,
|
110
|
110
|
GX_ItemVarStore itemStore );
|
111
|
111
|
|
112
|
|
- typedef FT_Int
|
|
112
|
+ typedef FT_ItemVarDelta
|
113
|
113
|
(*FT_Var_Get_Item_Delta_Func)( FT_Face face,
|
114
|
114
|
GX_ItemVarStore itemStore,
|
115
|
115
|
FT_UInt outerIndex,
|
src/base/ftcalc.c
... |
... |
@@ -1085,4 +1085,64 @@ |
1085
|
1085
|
}
|
1086
|
1086
|
|
1087
|
1087
|
|
|
1088
|
+ FT_BASE_DEF( FT_Int32 )
|
|
1089
|
+ FT_MulAddFix( FT_Fixed* s,
|
|
1090
|
+ FT_Int32* f,
|
|
1091
|
+ FT_UInt count )
|
|
1092
|
+ {
|
|
1093
|
+ FT_UInt i;
|
|
1094
|
+ FT_Int64 temp;
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+#ifdef FT_INT64
|
|
1098
|
+
|
|
1099
|
+ for ( i = 0; i < count; ++i )
|
|
1100
|
+ temp += (FT_Int64)s[i] * f[i];
|
|
1101
|
+
|
|
1102
|
+ return temp >> 16;
|
|
1103
|
+
|
|
1104
|
+#else
|
|
1105
|
+
|
|
1106
|
+ temp.hi = 0;
|
|
1107
|
+ temp.lo = 0;
|
|
1108
|
+
|
|
1109
|
+ for ( i = 0; i < count; ++i )
|
|
1110
|
+ {
|
|
1111
|
+ FT_Int64 multResult;
|
|
1112
|
+
|
|
1113
|
+ FT_Int sign = 1;
|
|
1114
|
+ FT_UInt32 carry = 0;
|
|
1115
|
+
|
|
1116
|
+ FT_UInt32 scalar;
|
|
1117
|
+ FT_UInt32 factor;
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+ scalar = (FT_UInt32)s[i];
|
|
1121
|
+ factor = (FT_UInt32)f[i];
|
|
1122
|
+
|
|
1123
|
+ FT_MOVE_SIGN( s[i], scalar, sign );
|
|
1124
|
+ FT_MOVE_SIGN( f[i], factor, sign );
|
|
1125
|
+
|
|
1126
|
+ ft_multo64( scalar, factor, &multResult );
|
|
1127
|
+
|
|
1128
|
+ if ( sign < 0 )
|
|
1129
|
+ {
|
|
1130
|
+ /* Emulated `FT_Int64` negation. */
|
|
1131
|
+ carry = ( multResult.lo == 0 );
|
|
1132
|
+
|
|
1133
|
+ multResult.lo = ~multResult.lo + 1;
|
|
1134
|
+ multResult.hi = ~multResult.hi + carry;
|
|
1135
|
+ }
|
|
1136
|
+
|
|
1137
|
+ FT_Add64( &temp, &multResult, &temp );
|
|
1138
|
+ }
|
|
1139
|
+
|
|
1140
|
+ return (FT_Int32)( ( (FT_Int32)( temp.hi & 0xFFFF ) << 16 ) |
|
|
1141
|
+ ( temp.lo >> 16 ) );
|
|
1142
|
+
|
|
1143
|
+#endif /* !FT_INT64 */
|
|
1144
|
+
|
|
1145
|
+ }
|
|
1146
|
+
|
|
1147
|
+
|
1088
|
1148
|
/* END */ |
src/truetype/ttgxvar.c
... |
... |
@@ -939,19 +939,23 @@ |
939
|
939
|
}
|
940
|
940
|
|
941
|
941
|
|
942
|
|
- FT_LOCAL_DEF( FT_Int )
|
|
942
|
+ FT_LOCAL_DEF( FT_ItemVarDelta )
|
943
|
943
|
tt_var_get_item_delta( TT_Face face,
|
944
|
944
|
GX_ItemVarStore itemStore,
|
945
|
945
|
FT_UInt outerIndex,
|
946
|
946
|
FT_UInt innerIndex )
|
947
|
947
|
{
|
|
948
|
+ FT_Stream stream = FT_FACE_STREAM( face );
|
|
949
|
+ FT_Memory memory = stream->memory;
|
|
950
|
+ FT_Error error = FT_Err_Ok;
|
|
951
|
+
|
948
|
952
|
GX_ItemVarData varData;
|
949
|
953
|
FT_ItemVarDelta* deltaSet;
|
950
|
954
|
|
951
|
|
- FT_UInt master, j;
|
952
|
|
- FT_Fixed netAdjustment = 0; /* accumulated adjustment */
|
953
|
|
- FT_Fixed scaledDelta;
|
954
|
|
- FT_Fixed delta;
|
|
955
|
+ FT_UInt master, j;
|
|
956
|
+ FT_Fixed* scalars;
|
|
957
|
+ FT_ItemVarDelta returnValue;
|
|
958
|
+
|
955
|
959
|
|
956
|
960
|
/* OpenType 1.8.4+: No variation data for this item
|
957
|
961
|
* as indices have special value 0xFFFF. */
|
... |
... |
@@ -964,6 +968,9 @@ |
964
|
968
|
varData = &itemStore->varData[outerIndex];
|
965
|
969
|
deltaSet = &varData->deltaSet[varData->regionIdxCount * innerIndex];
|
966
|
970
|
|
|
971
|
+ if ( FT_QNEW_ARRAY( scalars, varData->regionIdxCount ) )
|
|
972
|
+ return 0;
|
|
973
|
+
|
967
|
974
|
/* outer loop steps through master designs to be blended */
|
968
|
975
|
for ( master = 0; master < varData->regionIdxCount; master++ )
|
969
|
976
|
{
|
... |
... |
@@ -1013,18 +1020,33 @@ |
1013
|
1020
|
FT_MulDiv( scalar,
|
1014
|
1021
|
axis->endCoord - face->blend->normalizedcoords[j],
|
1015
|
1022
|
axis->endCoord - axis->peakCoord );
|
1016
|
|
- } /* per-axis loop */
|
1017
|
1023
|
|
1018
|
|
- /* get the scaled delta for this region */
|
1019
|
|
- delta = FT_intToFixed( deltaSet[master] );
|
1020
|
|
- scaledDelta = FT_MulFix( scalar, delta );
|
|
1024
|
+ } /* per-axis loop */
|
1021
|
1025
|
|
1022
|
|
- /* accumulate the adjustments from each region */
|
1023
|
|
- netAdjustment = netAdjustment + scaledDelta;
|
|
1026
|
+ scalars[master] = scalar;
|
1024
|
1027
|
|
1025
|
1028
|
} /* per-region loop */
|
1026
|
1029
|
|
1027
|
|
- return FT_fixedToInt( netAdjustment );
|
|
1030
|
+
|
|
1031
|
+ /* Compute the scaled delta for this region.
|
|
1032
|
+ *
|
|
1033
|
+ * From: https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#item-variation-store-header-and-item-variation-data-subtables:
|
|
1034
|
+ *
|
|
1035
|
+ * `Fixed` is a 32-bit (16.16) type and, in the general case, requires
|
|
1036
|
+ * 32-bit deltas. As described above, the `DeltaSet` record can
|
|
1037
|
+ * accommodate deltas that are, logically, either 16-bit or 32-bit.
|
|
1038
|
+ * When scaled deltas are applied to `Fixed` values, the `Fixed` value
|
|
1039
|
+ * is treated like a 32-bit integer.
|
|
1040
|
+ *
|
|
1041
|
+ * `FT_MulAddFix` internally uses 64-bit precision; it thus can handle
|
|
1042
|
+ * deltas ranging from small 8-bit to large 32-bit values that are
|
|
1043
|
+ * applied to 16.16 `FT_Fixed` / OpenType `Fixed` values.
|
|
1044
|
+ */
|
|
1045
|
+ returnValue = FT_MulAddFix( scalars, deltaSet, varData->regionIdxCount );
|
|
1046
|
+
|
|
1047
|
+ FT_FREE( scalars );
|
|
1048
|
+
|
|
1049
|
+ return returnValue;
|
1028
|
1050
|
}
|
1029
|
1051
|
|
1030
|
1052
|
|
src/truetype/ttgxvar.h
... |
... |
@@ -391,7 +391,7 @@ FT_BEGIN_HEADER |
391
|
391
|
GX_ItemVarStore itemStore,
|
392
|
392
|
FT_ULong table_len );
|
393
|
393
|
|
394
|
|
- FT_LOCAL( FT_Int )
|
|
394
|
+ FT_LOCAL( FT_ItemVarDelta )
|
395
|
395
|
tt_var_get_item_delta( TT_Face face,
|
396
|
396
|
GX_ItemVarStore itemStore,
|
397
|
397
|
FT_UInt outerIndex,
|
|