ref: 36d2eab05468d531cf8f51dce4cbca27e553b672
parent: 2066e0acd6e78520a4837e74a6d34aa41a2ce4d6
author: Werner Lemberg <[email protected]>
date: Tue Sep 5 15:24:34 EDT 2006
* 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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,28 @@
-2006-09-05 David Turner <[email protected]>
+2006-09-05 Werner Lemberg <[email protected]>
- * src/smooth/ftgrays.c: minor source cleanups and optimization
+ * 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 (gray_sweep): Avoid buffer overwrites
- when to drawing the end of a bitmap scanline. The fun never ends ;-)
+ * src/smooth/ftgrays.c [GRAYS_USE_GAMMA]: Really remove all code.
+2006-09-05 David Turner <[email protected]>
+
+ 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 <[email protected]>
--- 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 @@
int x = ras.ex;
- pcell = &ras.ycells[ ras.ey ];
+ pcell = &ras.ycells[ras.ey];
for (;;)
{
cell = *pcell;
@@ -414,10 +416,11 @@
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 @@
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 @@
/* 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 @@
/* 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 @@
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,6 +678,7 @@
ras.area += area;
ras.cover += delta;
ey1 += incr;
+
gray_set_cell( raster, ex, ey1 );
}
@@ -681,6 +685,7 @@
delta = (int)( fy2 - ONE_PIXEL + first );
ras.area += (TArea)two_fx * delta;
ras.cover += delta;
+
goto End;
}
@@ -807,7 +812,7 @@
{
/* 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 @@
gray_render_line( RAS_VAR_ mid_x, mid_y );
gray_render_line( RAS_VAR_ to_x, to_y );
+
return;
}
@@ -878,6 +884,7 @@
arc -= 2;
}
}
+
return;
}
@@ -1026,6 +1033,7 @@
arc -= 3;
}
}
+
return;
}
@@ -1106,10 +1114,10 @@
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
@@ -1116,17 +1124,18 @@
{
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 @@
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 @@
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 @@
span->x = (short)x;
span->len = (unsigned short)acount;
span->coverage = (unsigned char)coverage;
+
ras.num_gray_spans++;
}
}
@@ -1237,10 +1247,12 @@
{
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,9 +1392,12 @@
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;
point = outline->points + first;
@@ -1464,7 +1479,8 @@
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 @@
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 @@
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,9 +1518,12 @@
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 )
{
FT_Vector vec;
@@ -1689,13 +1710,13 @@
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 @@
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 @@
*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 @@
{
raster->memory = memory;
*araster = (FT_Raster)raster;
-
-#ifdef GRAYS_USE_GAMMA
- grays_init_gamma( raster );
-#endif
}
return error;
@@ -1878,9 +1891,9 @@
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;
--- 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 */