Alexei Podtelezhnikov pushed to branch master-patch-ea68 at FreeType / FreeType
Commits:
-
a3f44aad
by Werner Lemberg at 2023-08-22T12:27:10+02:00
builds/toplevel.mk: Don't use `\#` in functions.
The behaviour changed in GNU make 4.3, where `#` (without the backslash)
would be necessary. Using a variable instead the code works with both older
and newer GNU make versions.
Fixes #1252.
-
97251fd5
by Alexei Podtelezhnikov at 2023-08-22T11:01:16+00:00
[base] Improve the matrix degeneracy check.
Also fixes #1251.
* src/base/ftcalc.c (FT_Matrix_Check): To avoid overflow, scale by shifting.
* include/freetype/internal/ftcalc.h (FT_Matrix_Check): Update description.
3 changed files:
Changes:
builds/toplevel.mk
... |
... |
@@ -201,21 +201,23 @@ include $(TOP_DIR)/builds/modules.mk |
201
|
201
|
# get FreeType version string, using a
|
202
|
202
|
# poor man's `sed' emulation with make's built-in string functions
|
203
|
203
|
#
|
|
204
|
+hash := \#
|
|
205
|
+
|
204
|
206
|
work := $(strip $(shell $(CAT) \
|
205
|
207
|
$(subst /,$(SEP),$(TOP_DIR)/include/freetype/freetype.h)))
|
206
|
208
|
work := $(subst |,x,$(work))
|
207
|
209
|
work := $(subst $(space),|,$(work))
|
208
|
|
-work := $(subst \#define|FREETYPE_MAJOR|,$(space),$(work))
|
|
210
|
+work := $(subst $(hash)define|FREETYPE_MAJOR|,$(space),$(work))
|
209
|
211
|
work := $(word 2,$(work))
|
210
|
212
|
major := $(subst |,$(space),$(work))
|
211
|
213
|
major := $(firstword $(major))
|
212
|
214
|
|
213
|
|
-work := $(subst \#define|FREETYPE_MINOR|,$(space),$(work))
|
|
215
|
+work := $(subst $(hash)define|FREETYPE_MINOR|,$(space),$(work))
|
214
|
216
|
work := $(word 2,$(work))
|
215
|
217
|
minor := $(subst |,$(space),$(work))
|
216
|
218
|
minor := $(firstword $(minor))
|
217
|
219
|
|
218
|
|
-work := $(subst \#define|FREETYPE_PATCH|,$(space),$(work))
|
|
220
|
+work := $(subst $(hash)define|FREETYPE_PATCH|,$(space),$(work))
|
219
|
221
|
work := $(word 2,$(work))
|
220
|
222
|
patch := $(subst |,$(space),$(work))
|
221
|
223
|
patch := $(firstword $(patch))
|
include/freetype/internal/ftcalc.h
... |
... |
@@ -332,9 +332,9 @@ FT_BEGIN_HEADER |
332
|
332
|
* Based on geometric considerations we use the following inequality to
|
333
|
333
|
* identify a degenerate matrix.
|
334
|
334
|
*
|
335
|
|
- * 50 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
|
|
335
|
+ * 32 * abs(xx*yy - xy*yx) < xx^2 + xy^2 + yx^2 + yy^2
|
336
|
336
|
*
|
337
|
|
- * Value 50 is heuristic.
|
|
337
|
+ * Value 32 is heuristic.
|
338
|
338
|
*/
|
339
|
339
|
FT_BASE( FT_Bool )
|
340
|
340
|
FT_Matrix_Check( const FT_Matrix* matrix );
|
src/base/ftcalc.c
... |
... |
@@ -749,65 +749,43 @@ |
749
|
749
|
FT_BASE_DEF( FT_Bool )
|
750
|
750
|
FT_Matrix_Check( const FT_Matrix* matrix )
|
751
|
751
|
{
|
752
|
|
- FT_Matrix m;
|
753
|
|
- FT_Fixed val[4];
|
754
|
|
- FT_Fixed nonzero_minval, maxval;
|
755
|
|
- FT_Fixed temp1, temp2;
|
756
|
|
- FT_UInt i;
|
|
752
|
+ FT_Fixed xx, xy, yx, yy;
|
|
753
|
+ FT_Fixed val;
|
|
754
|
+ FT_Int shift;
|
|
755
|
+ FT_ULong temp1, temp2;
|
757
|
756
|
|
758
|
757
|
|
759
|
758
|
if ( !matrix )
|
760
|
759
|
return 0;
|
761
|
760
|
|
762
|
|
- val[0] = FT_ABS( matrix->xx );
|
763
|
|
- val[1] = FT_ABS( matrix->xy );
|
764
|
|
- val[2] = FT_ABS( matrix->yx );
|
765
|
|
- val[3] = FT_ABS( matrix->yy );
|
766
|
|
-
|
767
|
|
- /*
|
768
|
|
- * To avoid overflow, we ensure that each value is not larger than
|
769
|
|
- *
|
770
|
|
- * int(sqrt(2^31 / 4)) = 23170 ;
|
771
|
|
- *
|
772
|
|
- * we also check that no value becomes zero if we have to scale.
|
773
|
|
- */
|
774
|
|
-
|
775
|
|
- maxval = 0;
|
776
|
|
- nonzero_minval = FT_LONG_MAX;
|
|
761
|
+ xx = matrix->xx;
|
|
762
|
+ xy = matrix->xy;
|
|
763
|
+ yx = matrix->yx;
|
|
764
|
+ yy = matrix->yy;
|
|
765
|
+ val = FT_ABS( xx ) | FT_ABS( xy ) | FT_ABS( yx ) | FT_ABS( yy );
|
777
|
766
|
|
778
|
|
- for ( i = 0; i < 4; i++ )
|
779
|
|
- {
|
780
|
|
- if ( val[i] > maxval )
|
781
|
|
- maxval = val[i];
|
782
|
|
- if ( val[i] && val[i] < nonzero_minval )
|
783
|
|
- nonzero_minval = val[i];
|
784
|
|
- }
|
785
|
|
-
|
786
|
|
- /* we only handle 32bit values */
|
787
|
|
- if ( maxval > 0x7FFFFFFFL )
|
|
767
|
+ /* we only handle non-zero 32-bit values */
|
|
768
|
+ if ( !val || val > 0x7FFFFFFFL )
|
788
|
769
|
return 0;
|
789
|
770
|
|
790
|
|
- if ( maxval > 23170 )
|
791
|
|
- {
|
792
|
|
- FT_Fixed scale = FT_DivFix( maxval, 23170 );
|
793
|
|
-
|
|
771
|
+ /* Scale matrix to avoid the temp1 overflow, which is */
|
|
772
|
+ /* more stringent than avoiding the temp2 overflow. */
|
794
|
773
|
|
795
|
|
- if ( !FT_DivFix( nonzero_minval, scale ) )
|
796
|
|
- return 0; /* value range too large */
|
|
774
|
+ shift = FT_MSB( val ) - 12;
|
797
|
775
|
|
798
|
|
- m.xx = FT_DivFix( matrix->xx, scale );
|
799
|
|
- m.xy = FT_DivFix( matrix->xy, scale );
|
800
|
|
- m.yx = FT_DivFix( matrix->yx, scale );
|
801
|
|
- m.yy = FT_DivFix( matrix->yy, scale );
|
|
776
|
+ if ( shift > 0 )
|
|
777
|
+ {
|
|
778
|
+ xx >>= shift;
|
|
779
|
+ xy >>= shift;
|
|
780
|
+ yx >>= shift;
|
|
781
|
+ yy >>= shift;
|
802
|
782
|
}
|
803
|
|
- else
|
804
|
|
- m = *matrix;
|
805
|
783
|
|
806
|
|
- temp1 = FT_ABS( m.xx * m.yy - m.xy * m.yx );
|
807
|
|
- temp2 = m.xx * m.xx + m.xy * m.xy + m.yx * m.yx + m.yy * m.yy;
|
|
784
|
+ temp1 = 32U * (FT_ULong)FT_ABS( xx * yy - xy * yx );
|
|
785
|
+ temp2 = (FT_ULong)( xx * xx ) + (FT_ULong)( xy * xy ) +
|
|
786
|
+ (FT_ULong)( yx * yx ) + (FT_ULong)( yy * yy );
|
808
|
787
|
|
809
|
|
- if ( temp1 == 0 ||
|
810
|
|
- temp2 / temp1 > 50 )
|
|
788
|
+ if ( temp1 <= temp2 )
|
811
|
789
|
return 0;
|
812
|
790
|
|
813
|
791
|
return 1;
|
|