Commit 36d2eab05468d531cf8f51dce4cbca27e553b672

Werner Lemberg 2006-09-05T19:24:34

* src/truetype/ttpload.c (tt_face_load_hdmx): Handle `record_size' values which have the upper two bytes set to 0xFF instead of 0xFF (as it happens in at least two CJKV fonts, `HAN NOM A.ttf' and `HAN NOM B.ttf'). * src/smooth/ftgrays.c [GRAYS_USE_GAMMA]: Really remove all code. Formatting.

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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
diff --git a/ChangeLog b/ChangeLog
index 1ae251b..24ae9cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,28 @@
-2006-09-05  David Turner  <david@freetype.org>
+2006-09-05  Werner Lemberg  <wl@gnu.org>
+
+	* src/truetype/ttpload.c (tt_face_load_hdmx): Handle `record_size'
+	values which have the upper two bytes set to 0xFF instead of 0xFF
+	(as it happens in at least two CJKV fonts, `HAN NOM A.ttf' and
+	`HAN NOM B.ttf').
 
-        * src/smooth/ftgrays.c: minor source cleanups and optimization
+	* src/smooth/ftgrays.c [GRAYS_USE_GAMMA]: Really remove all code.
 
-        * src/smooth/ftgrays.c (gray_sweep): Avoid buffer overwrites
-        when to drawing the end of a bitmap scanline. The fun never ends ;-)
+2006-09-05  David Turner  <david@freetype.org>
 
+	Minor source cleanups and optimizations.
+
+	* src/smooth/ftgrays.c (GRAYS_COMPACT): Removed.
+	(TRaster): Remove `count_ex' and `count_ey'.
+	(gray_find_cell): Remove 2nd and 3rd argument.
+	(gray_alloc_cell): Merged with `gray_find_cell'.
+	(gray_record_cell): Simplify.
+	(gray_set_cell): Rewrite.
+	(gray_start_cell): Apply offsets to `ras.ex' and `ras.ey'.
+	(gray_render_span): Don't use FT_MEM_SET for small values.
+	(gray_dump_cells) [DEBUG_GRAYS]: New function.
+	(gray_sweep): Avoid buffer overwrites when to drawing the end of a
+	bitmap scanline.
+	(gray_convert_glyph): Fix speed-up.
 
 2006-09-04  David Turner  <david@freetype.org>
 
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 5a16571..fe8e24d 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -91,7 +91,7 @@
 #define FT_COMPONENT  trace_smooth
 
 
-#define ErrRaster_MemoryOverflow   -4
+#define ErrRaster_MemoryOverflow  -4
 
 
 #ifdef _STANDALONE_
@@ -160,6 +160,7 @@
   /* define this to dump debugging information */
 #define xxxDEBUG_GRAYS
 
+
   /* as usual, for the speed hungry :-) */
 
 #ifndef FT_STATIC_RASTER
@@ -207,6 +208,7 @@
 #define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )
 #endif
 
+
   /*************************************************************************/
   /*                                                                       */
   /*   TYPE DEFINITIONS                                                    */
@@ -225,7 +227,7 @@
 
 #if PIXEL_BITS <= 7
 
-  typedef int   TArea;
+  typedef int  TArea;
 
 #else /* PIXEL_BITS >= 8 */
 
@@ -233,7 +235,7 @@
 #if FT_UINT_MAX == 0xFFFFU
   typedef long  TArea;
 #else
-  typedef int  TArea;
+  typedef int   TArea;
 #endif
 
 #endif /* PIXEL_BITS >= 8 */
@@ -242,17 +244,17 @@
   /* maximal number of gray spans in a call to the span callback */
 #define FT_MAX_GRAY_SPANS  32
 
-typedef struct TCell_*   PCell;
 
-typedef struct TCell_
-{
-  int     x;
-  int     cover;
-  TArea   area;
-  PCell   next;
+  typedef struct TCell_*  PCell;
 
-} TCell;
+  typedef struct  TCell_
+  {
+    int    x;
+    int    cover;
+    TArea  area;
+    PCell  next;
 
+  } TCell;
 
 
   typedef struct  TRaster_
@@ -382,7 +384,7 @@ typedef struct TCell_
     int     x = ras.ex;
 
 
-    pcell = &ras.ycells[ ras.ey ];
+    pcell = &ras.ycells[ras.ey];
     for (;;)
     {
       cell = *pcell;
@@ -414,9 +416,10 @@ typedef struct TCell_
   static void
   gray_record_cell( RAS_ARG )
   {
-    if ( !ras.invalid && (ras.area | ras.cover) )
+    if ( !ras.invalid && ( ras.area | ras.cover ) )
     {
-      PCell   cell = gray_find_cell( RAS_VAR );
+      PCell  cell = gray_find_cell( RAS_VAR );
+
 
       cell->area  += ras.area;
       cell->cover += ras.cover;
@@ -463,7 +466,7 @@ typedef struct TCell_
     ras.ex      = ex;
     ras.ey      = ey;
     ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
-                              ex >= ras.count_ex );
+                              ex >= ras.count_ex           );
   }
 
 
@@ -472,11 +475,11 @@ typedef struct TCell_
   /* Start a new contour at a given cell.                                  */
   /*                                                                       */
   static void
-  gray_start_cell( RAS_ARG_  TCoord  ex,
-                             TCoord  ey )
+  gray_start_cell( RAS_ARG_ TCoord  ex,
+                            TCoord  ey )
   {
     if ( ex < ras.min_ex )
-      ex = (TCoord)(ras.min_ex - 1);
+      ex = (TCoord)( ras.min_ex - 1 );
 
     ras.area    = 0;
     ras.cover   = 0;
@@ -494,11 +497,11 @@ typedef struct TCell_
   /* Render a scanline as one or more cells.                               */
   /*                                                                       */
   static void
-  gray_render_scanline( RAS_ARG_  TCoord  ey,
-                                  TPos    x1,
-                                  TCoord  y1,
-                                  TPos    x2,
-                                  TCoord  y2 )
+  gray_render_scanline( RAS_ARG_ TCoord  ey,
+                                 TPos    x1,
+                                 TCoord  y1,
+                                 TPos    x2,
+                                 TCoord  y2 )
   {
     TCoord  ex1, ex2, fx1, fx2, delta;
     long    p, first, dx;
@@ -611,7 +614,7 @@ typedef struct TCell_
 
 
     ey1 = TRUNC( ras.last_ey );
-    ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
+    ey2 = TRUNC( to_y );     /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
     fy1 = (TCoord)( ras.y - ras.last_ey );
     fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
 
@@ -675,12 +678,14 @@ typedef struct TCell_
         ras.area  += area;
         ras.cover += delta;
         ey1       += incr;
+
         gray_set_cell( raster, ex, ey1 );
       }
 
       delta      = (int)( fy2 - ONE_PIXEL + first );
       ras.area  += (TArea)two_fx * delta;
       ras.cover += delta;
+
       goto End;
     }
 
@@ -807,7 +812,7 @@ typedef struct TCell_
     {
       /* we compute the mid-point directly in order to avoid */
       /* calling gray_split_conic()                          */
-      TPos   to_x, to_y, mid_x, mid_y;
+      TPos  to_x, to_y, mid_x, mid_y;
 
 
       to_x  = UPSCALE( to->x );
@@ -817,6 +822,7 @@ typedef struct TCell_
 
       gray_render_line( RAS_VAR_ mid_x, mid_y );
       gray_render_line( RAS_VAR_ to_x, to_y );
+
       return;
     }
 
@@ -878,6 +884,7 @@ typedef struct TCell_
         arc -= 2;
       }
     }
+
     return;
   }
 
@@ -1026,6 +1033,7 @@ typedef struct TCell_
         arc -= 3;
       }
     }
+
     return;
   }
 
@@ -1106,27 +1114,28 @@ typedef struct TCell_
 
       if ( coverage )
       {
-       /* for small-spans, it's faster to do it ourselves than
-        * calling memset. this is mainly due to the cost of the
-        * function call.
-        */
+        /* For small-spans it is faster to do it by ourselves than
+         * calling `memset'.  This is mainly due to the cost of the
+         * function call.
+         */
         if ( spans->len >= 8 )
           FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
         else
         {
           unsigned char*  q = p + spans->x;
 
+
           switch ( spans->len )
           {
-            case 7: *q++ = (unsigned char)coverage;
-            case 6: *q++ = (unsigned char)coverage;
-            case 5: *q++ = (unsigned char)coverage;
-            case 4: *q++ = (unsigned char)coverage;
-            case 3: *q++ = (unsigned char)coverage;
-            case 2: *q++ = (unsigned char)coverage;
-            case 1: *q   = (unsigned char)coverage;
-            default:
-               ;
+          case 7: *q++ = (unsigned char)coverage;
+          case 6: *q++ = (unsigned char)coverage;
+          case 5: *q++ = (unsigned char)coverage;
+          case 4: *q++ = (unsigned char)coverage;
+          case 3: *q++ = (unsigned char)coverage;
+          case 2: *q++ = (unsigned char)coverage;
+          case 1: *q   = (unsigned char)coverage;
+          default:
+            ;
           }
         }
       }
@@ -1140,9 +1149,9 @@ typedef struct TCell_
                        TPos    area,
                        int     acount )
   {
-    FT_Span*   span;
-    int        count;
-    int        coverage;
+    FT_Span*  span;
+    int       count;
+    int       coverage;
 
 
     /* compute the coverage line's coverage, depending on the    */
@@ -1176,13 +1185,13 @@ typedef struct TCell_
 
     if ( coverage )
     {
-      /* see if we can add this span to the current list */
+      /* see whether we can add this span to the current list */
       count = ras.num_gray_spans;
       span  = ras.gray_spans + count - 1;
       if ( count > 0                          &&
            ras.span_y == y                    &&
            (int)span->x + span->len == (int)x &&
-           span->coverage == coverage )
+           span->coverage == coverage         )
       {
         span->len = (unsigned short)( span->len + acount );
         return;
@@ -1225,6 +1234,7 @@ typedef struct TCell_
       span->x        = (short)x;
       span->len      = (unsigned short)acount;
       span->coverage = (unsigned char)coverage;
+
       ras.num_gray_spans++;
     }
   }
@@ -1237,10 +1247,12 @@ typedef struct TCell_
   {
     int  yindex;
 
+
     for ( yindex = 0; yindex < ras.ycount; yindex++ )
     {
       PCell  cell;
 
+
       printf( "%3d:", yindex );
 
       for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
@@ -1380,8 +1392,11 @@ typedef struct TCell_
       v_start = outline->points[first];
       v_last  = outline->points[last];
 
-      v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
-      v_last.x  = SCALED( v_last.x );  v_last.y  = SCALED( v_last.y );
+      v_start.x = SCALED( v_start.x );
+      v_start.y = SCALED( v_start.y );
+
+      v_last.x  = SCALED( v_last.x );
+      v_last.y  = SCALED( v_last.y );
 
       v_control = v_start;
 
@@ -1464,7 +1479,8 @@ typedef struct TCell_
 
               if ( tag == FT_CURVE_TAG_ON )
               {
-                error = func_interface->conic_to( &v_control, &vec, user );
+                error = func_interface->conic_to( &v_control, &vec,
+                                                  user );
                 if ( error )
                   goto Exit;
                 continue;
@@ -1476,7 +1492,8 @@ typedef struct TCell_
               v_middle.x = ( v_control.x + vec.x ) / 2;
               v_middle.y = ( v_control.y + vec.y ) / 2;
 
-              error = func_interface->conic_to( &v_control, &v_middle, user );
+              error = func_interface->conic_to( &v_control, &v_middle,
+                                                user );
               if ( error )
                 goto Exit;
 
@@ -1484,7 +1501,8 @@ typedef struct TCell_
               goto Do_Conic;
             }
 
-            error = func_interface->conic_to( &v_control, &v_start, user );
+            error = func_interface->conic_to( &v_control, &v_start,
+                                              user );
             goto Close;
           }
 
@@ -1500,8 +1518,11 @@ typedef struct TCell_
             point += 2;
             tags  += 2;
 
-            vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
-            vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
+            vec1.x = SCALED( point[-2].x );
+            vec1.y = SCALED( point[-2].y );
+
+            vec2.x = SCALED( point[-1].x );
+            vec2.y = SCALED( point[-1].y );
 
             if ( point <= limit )
             {
@@ -1689,13 +1710,13 @@ typedef struct TCell_
         ras.invalid   = 1;
         ras.min_ey    = band->min;
         ras.max_ey    = band->max;
-	ras.count_ey  = band->max - band->min;
+        ras.count_ey  = band->max - band->min;
 
         error = gray_convert_glyph_inner( RAS_VAR );
 
         if ( !error )
         {
-          gray_sweep( RAS_VAR_  &ras.target );
+          gray_sweep( RAS_VAR_ &ras.target );
           band--;
           continue;
         }
@@ -1703,13 +1724,13 @@ typedef struct TCell_
           return 1;
 
       ReduceBands:
-        /* render pool overflow, we will reduce the render band by half */
+        /* render pool overflow; we will reduce the render band by half */
         bottom = band->min;
         top    = band->max;
         middle = bottom + ( ( top - bottom ) >> 1 );
 
-        /* waoow! This is too complex for a single scanline, something */
-        /* must be really rotten here!                                 */
+        /* This is too complex for a single scanline; there must */
+        /* be some problems.                                     */
         if ( middle == bottom )
         {
 #ifdef DEBUG_GRAYS
@@ -1825,10 +1846,6 @@ typedef struct TCell_
     *araster = (FT_Raster)&the_raster;
     FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
 
-#ifdef GRAYS_USE_GAMMA
-    grays_init_gamma( (PRaster)*araster );
-#endif
-
     return 0;
   }
 
@@ -1855,10 +1872,6 @@ typedef struct TCell_
     {
       raster->memory = memory;
       *araster = (FT_Raster)raster;
-
-#ifdef GRAYS_USE_GAMMA
-      grays_init_gamma( raster );
-#endif
     }
 
     return error;
@@ -1878,9 +1891,9 @@ typedef struct TCell_
 
 
   static void
-  gray_raster_reset( FT_Raster    raster,
-                     char*        pool_base,
-                     long         pool_size )
+  gray_raster_reset( FT_Raster  raster,
+                     char*      pool_base,
+                     long       pool_size )
   {
     PRaster  rast = (PRaster)raster;
 
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index 6641fb7..0aa066b 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -562,7 +562,23 @@
     num_records = FT_NEXT_USHORT( p );
     record_size = FT_NEXT_ULONG( p );
 
-    if ( version != 0 || num_records > 255 || record_size > 0x40000 )
+    /* The maximum number of bytes in an hdmx device record is the */
+    /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is   */
+    /* the reason why `record_size' is a long (which we read as    */
+    /* unsigned long for convenience).  In practice, two bytes     */
+    /* sufficient to hold the size value.                          */
+    /*                                                             */
+    /* There are at least two fonts, HANNOM-A and HANNOM-B version */
+    /* 2.0 (2005), which get this wrong: The upper two bytes of    */
+    /* the size value are set to 0xFF instead of 0x00.  We catch   */
+    /* and fix this.                                               */
+
+    if ( record_size >= 0xFFFF0000UL )
+      record_size &= 0xFFFFU;
+
+    /* The limit for `num_records' is a heuristic value. */
+
+    if ( version != 0 || num_records > 255 || record_size > 0x10001L )
     {
       error = TT_Err_Invalid_File_Format;
       goto Fail;
@@ -638,12 +654,25 @@
 
     FT_FRAME_EXIT();
 
+    /* The maximum number of bytes in an hdmx device record is the */
+    /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is   */
+    /* the reason why `record_size' is a long.  In practice, two   */
+    /* bytes sufficient to hold the size value.                    */
+    /*                                                             */
+    /* There are at least two fonts, HANNOM-A and HANNOM-B version */
+    /* 2.0 (2005), which get this wrong: The upper two bytes of    */
+    /* the size value are set to 0xFF instead of 0x00.  We catch   */
+    /* and fix this.                                               */
+
+    if ( (FT_ULong)record_size >= 0xFFFF0000UL )
+      record_size = (FT_Long)( (FT_ULong)record_size & 0xFFFFU );
+
     if ( record_size < 0 || num_records < 0 )
       return TT_Err_Invalid_File_Format;
 
     /* Only recognize format 0 */
     if ( hdmx->version != 0 )
-      goto Exit;
+      return TT_Err_Invalid_File_Format;
 
     /* we can't use FT_QNEW_ARRAY here; otherwise tt_face_free_hdmx */
     /* could fail during deallocation                               */