[base] Overflow-resistant bitmap presetting. * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Implement it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
diff --git a/ChangeLog b/ChangeLog
index f38b201..0c1f2a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2018-08-30 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [base] Overflow-resistant bitmap presetting.
+
+ * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Implement it.
+
2018-08-29 Armin Hasitzka <prince.cherusker@gmail.com>
Fix numeric overflows.
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 87e4b25..fc0cf0d 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -342,6 +342,7 @@
}
+ /* overflow-resistant presetting of bitmap position and dimensions */
FT_BASE_DEF( void )
ft_glyphslot_preset_bitmap( FT_GlyphSlot slot,
FT_Render_Mode mode,
@@ -352,7 +353,7 @@
FT_Pixel_Mode pixel_mode;
- FT_BBox cbox;
+ FT_BBox cbox, pbox;
FT_Pos x_shift = 0;
FT_Pos y_shift = 0;
FT_Pos x_left, y_top;
@@ -372,10 +373,17 @@
/* taking into account the origin shift */
FT_Outline_Get_CBox( outline, &cbox );
- cbox.xMin += x_shift;
- cbox.yMin += y_shift;
- cbox.xMax += x_shift;
- cbox.yMax += y_shift;
+ /* rough estimte of pixel box */
+ pbox.xMin = ( cbox.xMin >> 6 ) + ( x_shift >> 6 );
+ pbox.yMin = ( cbox.yMin >> 6 ) + ( y_shift >> 6 );
+ pbox.xMax = ( cbox.xMax >> 6 ) + ( x_shift >> 6 );
+ pbox.yMax = ( cbox.yMax >> 6 ) + ( y_shift >> 6 );
+
+ /* tiny remainder box */
+ cbox.xMin = ( cbox.xMin & 63 ) + ( x_shift & 63 );
+ cbox.yMin = ( cbox.yMin & 63 ) + ( y_shift & 63 );
+ cbox.xMax = ( cbox.xMax & 63 ) + ( x_shift & 63 );
+ cbox.yMax = ( cbox.yMax & 63 ) + ( y_shift & 63 );
switch ( mode )
{
@@ -384,58 +392,63 @@
#if 1
/* undocumented but confirmed: bbox values get rounded */
/* unless the rounded box can collapse for a narrow glyph */
- if ( cbox.xMax - cbox.xMin < 64 )
+ if ( pbox.xMax - pbox.xMin == 0 )
{
cbox.xMin = ( cbox.xMin + cbox.xMax ) / 2 - 32;
cbox.xMax = cbox.xMin + 64;
}
+ else if ( pbox.xMax - pbox.xMin == 1 )
+ {
+ cbox.xMin = cbox.xMax = ( cbox.xMin + cbox.xMax ) / 2;
+ }
- cbox.xMin = FT_PIX_ROUND_LONG( cbox.xMin );
- cbox.xMax = FT_PIX_ROUND_LONG( cbox.xMax );
+ pbox.xMin += ( cbox.xMin + 32 ) >> 6;
+ pbox.xMax += ( cbox.xMax + 32 ) >> 6;
- if ( cbox.yMax - cbox.yMin < 64 )
+ if ( pbox.yMax - pbox.yMin == 0 )
{
cbox.yMin = ( cbox.yMin + cbox.yMax ) / 2 - 32;
cbox.yMax = cbox.yMin + 64;
}
+ else if ( pbox.yMax - pbox.yMin == 1 )
+ {
+ cbox.yMin = cbox.yMax = ( cbox.yMin + cbox.yMax ) / 2;
+ }
- cbox.yMin = FT_PIX_ROUND_LONG( cbox.yMin );
- cbox.yMax = FT_PIX_ROUND_LONG( cbox.yMax );
+ pbox.yMin += ( cbox.yMin + 32 ) >> 6;
+ pbox.yMax += ( cbox.yMax + 32 ) >> 6;
break;
#else
- goto Round;
+ goto Adjust;
#endif
case FT_RENDER_MODE_LCD:
pixel_mode = FT_PIXEL_MODE_LCD;
ft_lcd_padding( &cbox, slot, mode );
- goto Round;
+ goto Adjust;
case FT_RENDER_MODE_LCD_V:
pixel_mode = FT_PIXEL_MODE_LCD_V;
ft_lcd_padding( &cbox, slot, mode );
- goto Round;
+ goto Adjust;
case FT_RENDER_MODE_NORMAL:
case FT_RENDER_MODE_LIGHT:
default:
pixel_mode = FT_PIXEL_MODE_GRAY;
- Round:
- cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
- cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
- cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax );
- cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax );
+ Adjust:
+ pbox.xMin += cbox.xMin >> 6;
+ pbox.yMin += cbox.yMin >> 6;
+ pbox.xMax += ( cbox.xMax + 63 ) >> 6;
+ pbox.yMax += ( cbox.yMax + 63 ) >> 6;
}
- x_shift = SUB_LONG( x_shift, cbox.xMin );
- y_shift = SUB_LONG( y_shift, cbox.yMin );
-
- x_left = cbox.xMin >> 6;
- y_top = cbox.yMax >> 6;
+ x_left = pbox.xMin;
+ y_top = pbox.yMax;
- width = ( (FT_ULong)cbox.xMax - (FT_ULong)cbox.xMin ) >> 6;
- height = ( (FT_ULong)cbox.yMax - (FT_ULong)cbox.yMin ) >> 6;
+ width = pbox.xMax - pbox.xMin;
+ height = pbox.yMax - pbox.yMin;
switch ( pixel_mode )
{