[woff2] Formatting; some comments.

This commit is contained in:
Werner Lemberg 2019-08-27 10:08:01 +02:00
parent 86803acd2a
commit 60c52f0edb
6 changed files with 283 additions and 181 deletions

View File

@ -478,7 +478,7 @@ if test x"$with_png" = xyes -o x"$with_png" = xauto; then
libpng_libsstaticconf="$LIBPNG_LIBS"
have_libpng="yes (LIBPNG_CFLAGS and LIBPNG_LIBS)"
else
# fall back to config script.
# fall back to config script
AC_MSG_CHECKING([for libpng-config])
if which libpng-config > /dev/null 2>&1; then
LIBPNG_CFLAGS=`libpng-config --cflags`
@ -547,7 +547,7 @@ fi
AC_ARG_WITH([brotli],
[AS_HELP_STRING([--with-brotli=@<:@yes|no|auto@:>@],
[Support decompression of WOFF2 streams @<:@default=auto@:>@])],
[support decompression of WOFF2 streams @<:@default=auto@:>@])],
[], [with_brotli=auto])
have_brotli=no
@ -576,7 +576,7 @@ if test x"$with_brotli" = xyes -o x"$with_brotli" = xauto; then
have_brotli="yes (BROTLI_CFLAGS and BROTLI_LIBS)"
else
# since Brotli is quite a new library we don't fall back to a
# different test;
# different test
:
fi
fi
@ -1032,7 +1032,7 @@ if test "x$PYTHON" != "xmissing"; then
fi
# entries in Requires.private are separated by commas;
# entries in Requires.private are separated by commas
REQUIRES_PRIVATE="$zlib_reqpriv, \
$bzip2_reqpriv, \
$libpng_reqpriv, \

View File

@ -275,13 +275,13 @@ FT_BEGIN_HEADER
*
* @fields:
* x ::
* x-coordinate.
* x-coordinate of point.
*
* y ::
* y-coordinate.
* y-coordinate of point.
*
* on_curve ::
* Whether point is on-curve.
* Set if point is on-curve.
*/
typedef struct WOFF2_PointRec_
{

View File

@ -28,20 +28,20 @@ SFNT_COMPILE := $(CC) $(ANSIFLAGS) \
# SFNT driver sources (i.e., C files)
#
SFNT_DRV_SRC := $(SFNT_DIR)/pngshim.c \
$(SFNT_DIR)/sfdriver.c \
$(SFNT_DIR)/sfobjs.c \
$(SFNT_DIR)/sfwoff.c \
$(SFNT_DIR)/sfwoff2.c \
$(SFNT_DIR)/ttbdf.c \
$(SFNT_DIR)/ttcmap.c \
$(SFNT_DIR)/ttcolr.c \
$(SFNT_DIR)/ttcpal.c \
$(SFNT_DIR)/ttkern.c \
$(SFNT_DIR)/ttload.c \
$(SFNT_DIR)/ttmtx.c \
$(SFNT_DIR)/ttpost.c \
$(SFNT_DIR)/ttsbit.c \
SFNT_DRV_SRC := $(SFNT_DIR)/pngshim.c \
$(SFNT_DIR)/sfdriver.c \
$(SFNT_DIR)/sfobjs.c \
$(SFNT_DIR)/sfwoff.c \
$(SFNT_DIR)/sfwoff2.c \
$(SFNT_DIR)/ttbdf.c \
$(SFNT_DIR)/ttcmap.c \
$(SFNT_DIR)/ttcolr.c \
$(SFNT_DIR)/ttcpal.c \
$(SFNT_DIR)/ttkern.c \
$(SFNT_DIR)/ttload.c \
$(SFNT_DIR)/ttmtx.c \
$(SFNT_DIR)/ttpost.c \
$(SFNT_DIR)/ttsbit.c \
$(SFNT_DIR)/woff2tags.c
# SFNT driver headers

View File

@ -130,17 +130,17 @@
static const FT_Int wordCode = 253;
static const FT_Int lowestUCode = 253;
FT_Error error = FT_Err_Ok;
FT_Byte code;
FT_Byte result_byte = 0;
FT_UShort result_short = 0;
FT_Error error = FT_Err_Ok;
FT_Byte code;
FT_Byte result_byte = 0;
FT_UShort result_short = 0;
if ( FT_READ_BYTE( code ) )
return error;
if ( code == wordCode )
{
/* Read next two bytes and store FT_UShort value */
/* Read next two bytes and store `FT_UShort' value. */
if ( FT_READ_USHORT( result_short ) )
return error;
*value = result_short;
@ -201,11 +201,13 @@
return FT_Err_Ok;
}
}
/* Make sure not to exceed the size bound. */
return FT_THROW( Invalid_Table );
}
/* Extend memory of `dst_bytes' buffer and copy data from `src'. */
static FT_Error
write_buf( FT_Byte** dst_bytes,
FT_ULong* dst_size,
@ -248,6 +250,7 @@
}
/* Pad buffer to closest multiple of 4. */
static FT_Error
pad4( FT_Byte** sfnt_bytes,
FT_ULong* sfnt_size,
@ -277,6 +280,7 @@
}
/* Calculate table checksum of `buf'. */
static FT_Long
compute_ULong_sum( FT_Byte* buf,
FT_ULong size )
@ -288,10 +292,10 @@
for ( i = 0; i < aligned_size; i += 4 )
{
checksum += ( buf[i] << 24 ) | ( buf[i+1] << 16 ) |
( buf[i+2] << 8 ) | ( buf[i+3] << 0 );
}
checksum += ( buf[i ] << 24 ) |
( buf[i + 1] << 16 ) |
( buf[i + 2] << 8 ) |
( buf[i + 3] << 0 );
/* If size is not aligned to 4, treat as if it is padded with 0s. */
if ( size != aligned_size )
@ -301,6 +305,7 @@
v |= buf[i] << ( 24 - 8 * ( i & 3 ) );
checksum += v;
}
return checksum;
}
@ -317,8 +322,10 @@
BrotliDecoderResult result;
result = BrotliDecoderDecompress(
src_size, src, &uncompressed_size, dst);
result = BrotliDecoderDecompress( src_size,
src,
&uncompressed_size,
dst );
if ( result != BROTLI_DECODER_RESULT_SUCCESS ||
uncompressed_size != dst_size )
@ -344,7 +351,7 @@
FT_UShort num_tables,
FT_ULong tag )
{
FT_Int i;
FT_Int i;
for ( i = 0; i < num_tables; i++ )
@ -356,7 +363,7 @@
}
/* Read `numberOfHMetrics' from `hhea' table. */
/* Read `numberOfHMetrics' field from `hhea' table. */
static FT_Error
read_num_hmetrics( FT_Stream stream,
FT_ULong table_len,
@ -378,6 +385,7 @@
}
/* An auxiliary function for overflow-safe addition. */
static FT_Int
with_sign( FT_Byte flag,
FT_Int base_val )
@ -387,6 +395,7 @@
}
/* An auxiliary function for overflow-safe addition. */
static FT_Int
safe_int_addition( FT_Int a,
FT_Int b,
@ -401,6 +410,12 @@
}
/*
* Decode variable-length (flag, xCoordinate, yCoordinate) triplet for a
* simple glyph. See
*
* https://www.w3.org/TR/WOFF2/#triplet_decoding
*/
static FT_Error
triplet_decode( const FT_Byte* flags_in,
const FT_Byte* in,
@ -426,7 +441,7 @@
for ( i = 0; i < n_points; ++i )
{
FT_Byte flag = flags_in[i];
FT_Byte flag = flags_in[i];
FT_Bool on_curve = !( flag >> 7 );
@ -453,9 +468,10 @@
}
else if ( flag < 20 )
{
dx = with_sign( flag,
( ( ( flag - 10 ) & 14 ) << 7 ) + in[triplet_index] );
dy = 0;
dx = with_sign( flag,
( ( ( flag - 10 ) & 14 ) << 7 ) +
in[triplet_index] );
dy = 0;
}
else if ( flag < 84 )
{
@ -473,7 +489,7 @@
1 + ( ( b0 / 12 ) << 8 ) + in[triplet_index] );
dy = with_sign( flag >> 1,
1 + ( ( ( b0 % 12 ) >> 2 ) << 8 ) +
in[triplet_index + 1] );
in[triplet_index + 1] );
}
else if ( flag < 124 )
{
@ -487,11 +503,12 @@
{
dx = with_sign( flag,
( in[triplet_index] << 8 ) +
in[triplet_index + 1] );
in[triplet_index + 1] );
dy = with_sign( flag >> 1,
( in[triplet_index + 2] << 8 ) +
in[triplet_index + 3] );
in[triplet_index + 3] );
}
triplet_index += data_bytes;
if ( safe_int_addition( x, dx, &x ) )
@ -504,11 +521,13 @@
result[i].y = y;
result[i].on_curve = on_curve;
}
*in_bytes_used = triplet_index;
return FT_Err_Ok;
}
/* Store decoded points in glyph buffer. */
static FT_Error
store_points( FT_ULong n_points,
const WOFF2_Point points,
@ -536,9 +555,9 @@
{
const WOFF2_PointRec point = points[i];
FT_Int flag = point.on_curve ? GLYF_ON_CURVE : 0;
FT_Int dx = point.x - last_x;
FT_Int dy = point.y - last_y;
FT_Int flag = point.on_curve ? GLYF_ON_CURVE : 0;
FT_Int dx = point.x - last_x;
FT_Int dy = point.y - last_y;
if ( dx == 0 )
@ -579,10 +598,11 @@
return FT_THROW( Invalid_Table );
dst[flag_offset++] = flag;
repeat_count = 0;
repeat_count = 0;
}
last_x = point.x;
last_y = point.y;
last_x = point.x;
last_y = point.y;
last_flag = flag;
}
@ -604,12 +624,15 @@
y_offset = flag_offset + x_bytes;
last_x = 0;
last_y = 0;
for ( i = 0; i < n_points; ++i )
{
FT_Int dx = points[i].x - last_x;
FT_Int dy = points[i].y - last_y;
if ( dx == 0 ) {;}
if ( dx == 0 )
;
else if ( dx > -256 && dx < 256 )
dst[x_offset++] = FT_ABS( dx );
else
@ -621,7 +644,8 @@
last_x += dx;
if ( dy == 0 ) {;}
if ( dy == 0 )
;
else if ( dy > -256 && dy < 256 )
dst[y_offset++] = FT_ABS( dy );
else
@ -662,10 +686,12 @@
x_max = points[0].x;
y_max = points[0].y;
}
for ( i = 1; i < n_points; ++i )
{
FT_Int x = points[i].x;
FT_Int y = points[i].y;
FT_Int x = points[i].x;
FT_Int y = points[i].y;
x_min = FT_MIN( x, x_min );
y_min = FT_MIN( y, y_min );
@ -674,8 +700,9 @@
}
/* Write values to `glyf' record. */
offset = 2;
offset = 2;
pointer = dst + offset;
WRITE_SHORT( pointer, x_min );
WRITE_SHORT( pointer, y_min );
WRITE_SHORT( pointer, x_max );
@ -703,6 +730,7 @@
{
FT_ULong arg_size;
if ( FT_READ_USHORT( flags ) )
goto Exit;
we_have_inst |= ( flags & FLAG_WE_HAVE_INSTRUCTIONS ) != 0;
@ -732,6 +760,7 @@
}
/* Store loca values (provided by `reconstruct_glyf') to output stream. */
static FT_Error
store_loca( FT_ULong* loca_values,
FT_ULong loca_values_size,
@ -749,7 +778,7 @@
FT_Byte* loca_buf = NULL;
FT_Byte* dst = NULL;
FT_Int i = 0;
FT_Int i = 0;
FT_ULong loca_buf_size;
const FT_ULong offset_size = index_format ? 4 : 2;
@ -775,7 +804,7 @@
}
*checksum = compute_ULong_sum( loca_buf, loca_buf_size );
/* Write loca table to sfnt buffer. */
/* Write `loca' table to sfnt buffer. */
if ( WRITE_SFNT_BUF( loca_buf, loca_buf_size ) )
goto Fail;
@ -811,10 +840,10 @@
FT_Error error = FT_Err_Ok;
FT_Byte* sfnt = *sfnt_bytes;
/* Current position in stream */
/* current position in stream */
const FT_ULong pos = FT_STREAM_POS();
FT_UInt num_substreams = 7;
FT_UInt num_substreams = 7;
FT_UShort num_glyphs;
FT_UShort index_format;
@ -831,10 +860,10 @@
WOFF2_Substream substreams = NULL;
FT_ULong* loca_values = NULL;
FT_UShort* n_points_arr = NULL;
FT_Byte* glyph_buf = NULL;
WOFF2_Point points = NULL;
FT_ULong* loca_values = NULL;
FT_UShort* n_points_arr = NULL;
FT_Byte* glyph_buf = NULL;
WOFF2_Point points = NULL;
if ( FT_NEW_ARRAY( substreams, num_substreams ) )
@ -856,8 +885,8 @@
/* See https://www.w3.org/TR/WOFF2/#conform-mustRejectLoca */
/* index_format = 0 => Short version `loca'. */
/* index_format = 1 => Long version `loca'. */
expected_loca_length = ( index_format ? 4 : 2 ) *
( (FT_ULong)num_glyphs + 1 );
expected_loca_length = ( index_format ? 4 : 2 ) *
( (FT_ULong)num_glyphs + 1 );
if ( loca_table->dst_length != expected_loca_length )
goto Fail;
@ -887,11 +916,11 @@
if ( FT_NEW_ARRAY( loca_values, num_glyphs + 1 ) )
goto Fail;
points_size = 0;
points_size = 0;
bbox_bitmap_offset = substreams[BBOX_STREAM].offset;
/* Size of bboxBitmap = 4 * floor((numGlyphs + 31) / 32) */
bitmap_length = ( ( num_glyphs + 31 ) >> 5 ) << 2;
bitmap_length = ( ( num_glyphs + 31 ) >> 5 ) << 2;
substreams[BBOX_STREAM].offset += bitmap_length;
glyph_buf_size = WOFF2_DEFAULT_GLYPH_BUF;
@ -919,7 +948,7 @@
if ( bbox_bitmap & ( 0x80 >> ( i & 7 ) ) )
have_bbox = TRUE;
/* Read value from `nContourStream' */
/* Read value from `nContourStream'. */
if ( FT_STREAM_SEEK( substreams[N_CONTOUR_STREAM].offset ) ||
FT_READ_USHORT( n_contours ) )
goto Fail;
@ -927,7 +956,7 @@
if ( n_contours == 0xffff )
{
/* Composite glyph */
/* composite glyph */
FT_Bool have_instructions = FALSE;
FT_UShort instruction_size = 0;
FT_ULong composite_size;
@ -940,9 +969,9 @@
goto Fail;
if ( compositeGlyph_size( stream,
substreams[COMPOSITE_STREAM].offset,
&composite_size,
&have_instructions) )
substreams[COMPOSITE_STREAM].offset,
&composite_size,
&have_instructions) )
goto Fail;
if ( have_instructions )
@ -974,30 +1003,34 @@
if ( FT_STREAM_SEEK( substreams[BBOX_STREAM].offset ) ||
FT_STREAM_READ( glyph_buf + glyph_size, 8 ) )
goto Fail;
substreams[BBOX_STREAM].offset += 8;
glyph_size += 8;
glyph_size += 8;
if ( FT_STREAM_SEEK( substreams[COMPOSITE_STREAM].offset ) ||
FT_STREAM_READ( glyph_buf + glyph_size, composite_size ) )
goto Fail;
substreams[COMPOSITE_STREAM].offset += composite_size;
glyph_size += composite_size;
glyph_size += composite_size;
if ( have_instructions )
{
pointer = glyph_buf + glyph_size;
WRITE_USHORT( pointer, instruction_size );
glyph_size += 2;
if ( FT_STREAM_SEEK( substreams[INSTRUCTION_STREAM].offset ) ||
FT_STREAM_READ( glyph_buf + glyph_size, instruction_size ) )
goto Fail;
substreams[INSTRUCTION_STREAM].offset += instruction_size;
glyph_size += instruction_size;
glyph_size += instruction_size;
}
}
else if ( n_contours > 0 )
{
/* Simple glyph */
/* simple glyph */
FT_ULong total_n_points = 0;
FT_UShort n_points_contour;
FT_UInt j;
@ -1019,6 +1052,7 @@
if ( FT_STREAM_SEEK( substreams[N_POINTS_STREAM].offset ) )
goto Fail;
for ( j = 0; j < n_contours; ++j )
{
if ( READ_255USHORT( n_points_contour ) )
@ -1038,32 +1072,41 @@
flags_buf = stream->base + substreams[FLAG_STREAM].offset;
triplet_buf = stream->base + substreams[GLYPH_STREAM].offset;
triplet_size = substreams[GLYPH_STREAM].size -
( substreams[GLYPH_STREAM].offset -
substreams[GLYPH_STREAM].start );
triplet_size = substreams[GLYPH_STREAM].size -
( substreams[GLYPH_STREAM].offset -
substreams[GLYPH_STREAM].start );
triplet_bytes_used = 0;
/* Create array to store point information. */
points_size = total_n_points;
if ( FT_NEW_ARRAY( points, points_size ) )
goto Fail;
if ( triplet_decode( flags_buf, triplet_buf,
triplet_size, total_n_points,
points, &triplet_bytes_used ) )
if ( triplet_decode( flags_buf,
triplet_buf,
triplet_size,
total_n_points,
points,
&triplet_bytes_used ) )
goto Fail;
substreams[FLAG_STREAM].offset += flag_size;
substreams[GLYPH_STREAM].offset += triplet_bytes_used;
if ( FT_STREAM_SEEK( substreams[GLYPH_STREAM].offset ) ||
READ_255USHORT( instruction_size ) )
goto Fail;
substreams[GLYPH_STREAM].offset = FT_STREAM_POS();
if ( total_n_points >= ( 1 << 27 ) ||
instruction_size >= ( 1 << 30 ) )
goto Fail;
size_needed = 12 + ( 2 * n_contours ) + ( 5 * total_n_points )
+ instruction_size;
size_needed = 12 +
( 2 * n_contours ) +
( 5 * total_n_points ) +
instruction_size;
if ( glyph_buf_size < size_needed )
{
if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) )
@ -1092,8 +1135,10 @@
compute_bbox( total_n_points, points, glyph_buf, &x_min );
glyph_size = CONTOUR_OFFSET_END_POINT;
pointer = glyph_buf + glyph_size;
end_point = -1;
pointer = glyph_buf + glyph_size;
end_point = -1;
for ( contour_ix = 0; contour_ix < n_contours; ++contour_ix )
{
end_point += n_points_arr[contour_ix];
@ -1106,15 +1151,21 @@
WRITE_USHORT( pointer, instruction_size );
glyph_size += 2;
if ( FT_STREAM_SEEK( substreams[INSTRUCTION_STREAM].offset ) ||
FT_STREAM_READ( glyph_buf + glyph_size, instruction_size ) )
goto Fail;
substreams[INSTRUCTION_STREAM].offset += instruction_size;
glyph_size += instruction_size;
if ( store_points( total_n_points, points, n_contours,
instruction_size, glyph_buf,
glyph_buf_size, &glyph_size ) )
substreams[INSTRUCTION_STREAM].offset += instruction_size;
glyph_size += instruction_size;
if ( store_points( total_n_points,
points,
n_contours,
instruction_size,
glyph_buf,
glyph_buf_size,
&glyph_size ) )
goto Fail;
FT_FREE( points );
@ -1122,7 +1173,7 @@
}
else
{
/* Empty glyph. */
/* Empty glyph. */
/* Must not have a bbox. */
if ( have_bbox )
{
@ -1130,7 +1181,9 @@
goto Fail;
}
}
loca_values[i] = dest_offset - glyf_start;
if ( WRITE_SFNT_BUF( glyph_buf, glyph_size ) )
goto Fail;
@ -1146,12 +1199,18 @@
glyf_table->dst_length = dest_offset - glyf_table->dst_offset;
loca_table->dst_offset = dest_offset;
/* loca[n] will be equal the length of the `glyf' table. */
/* `loca[n]' will be equal to the length of the `glyf' table. */
loca_values[num_glyphs] = glyf_table->dst_length;
if ( store_loca( loca_values, num_glyphs + 1, index_format,
loca_checksum, &sfnt, sfnt_size,
&dest_offset, memory ) )
if ( store_loca( loca_values,
num_glyphs + 1,
index_format,
loca_checksum,
&sfnt,
sfnt_size,
&dest_offset,
memory ) )
goto Fail;
loca_table->dst_length = dest_offset - loca_table->dst_offset;
@ -1165,13 +1224,13 @@
*sfnt_bytes = sfnt;
*out_offset = dest_offset;
FT_FREE( substreams );
FT_FREE( loca_values );
FT_FREE( n_points_arr );
FT_FREE( glyph_buf );
FT_FREE( points );
FT_FREE( substreams );
FT_FREE( loca_values );
FT_FREE( n_points_arr );
FT_FREE( glyph_buf );
FT_FREE( points );
return error;
return error;
Fail:
if ( !error )
@ -1187,7 +1246,7 @@
}
/* Get `x_mins' for untransformed glyf table. */
/* Get `x_mins' for untransformed `glyf' table. */
static FT_Error
get_x_mins( FT_Stream stream,
WOFF2_Table* tables,
@ -1214,7 +1273,7 @@
TTAG_head );
/* Read `numGlyphs' from maxp table. */
/* Read `numGlyphs' field from `maxp' table. */
if ( FT_STREAM_SEEK( maxp_table->src_offset ) && FT_STREAM_SKIP( 8 ) )
return error;
@ -1223,7 +1282,7 @@
info->num_glyphs = num_glyphs;
/* Read `indexToLocFormat' from head table. */
/* Read `indexToLocFormat' field from `head' table. */
if ( FT_STREAM_SEEK( head_table->src_offset ) && FT_STREAM_SKIP( 50 ) )
return error;
@ -1232,7 +1291,7 @@
offset_size = index_format ? 4 : 2;
/* Create x_mins array. */
/* Create `x_mins' array. */
if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) )
return error;
@ -1326,7 +1385,7 @@
FT_NEW_ARRAY( lsbs, num_glyphs ) )
goto Fail;
/* Read `advanceWidth' stream. Always present. */
/* Read `advanceWidth' stream. Always present. */
for ( i = 0; i < num_hmetrics; i++ )
{
FT_UShort advance_width;
@ -1335,7 +1394,7 @@
if ( FT_READ_USHORT( advance_width ) )
goto Fail;
advance_widths[i] = advance_width;
advance_widths[i] = advance_width;
}
/* lsb values for proportional glyphs. */
@ -1355,7 +1414,7 @@
lsbs[i] = lsb;
}
/* lsb values for monospaced glyphs */
/* lsb values for monospaced glyphs. */
for ( i = num_hmetrics; i < num_glyphs; i++ )
{
FT_Short lsb;
@ -1390,10 +1449,10 @@
WRITE_SHORT( dst, lsbs[i] );
FT_TRACE6(( "%d ", lsbs[i] ));
}
FT_TRACE6(( "\n" ));
*checksum = compute_ULong_sum( hmtx_table, hmtx_table_size );
/* Write hmtx table to sfnt buffer. */
/* Write `hmtx' table to sfnt buffer. */
if ( WRITE_SFNT_BUF( hmtx_table, hmtx_table_size ) )
goto Fail;
@ -1421,13 +1480,13 @@
FT_ULong* sfnt_size,
FT_Memory memory )
{
FT_Error error = FT_Err_Ok;
FT_Stream stream = NULL;
FT_Byte* buf_cursor = NULL;
FT_Byte* table_entry = NULL;
FT_Error error = FT_Err_Ok;
FT_Stream stream = NULL;
FT_Byte* buf_cursor = NULL;
FT_Byte* table_entry = NULL;
/* We are reallocating memory for `sfnt', so its pointer may change. */
FT_Byte* sfnt = *sfnt_bytes;
FT_Byte* sfnt = *sfnt_bytes;
FT_UShort num_tables = woff2->num_tables;
FT_ULong dest_offset = 12 + num_tables * 16UL;
@ -1442,8 +1501,8 @@
FT_ULong table_entry_offset = 12;
WOFF2_Table head_table;
/* Few table checks before reconstruction. */
/* `glyf' must be present with `loca'. */
/* A few table checks before reconstruction. */
/* `glyf' must be present with `loca'. */
const WOFF2_Table glyf_table = find_table( indices, num_tables,
TTAG_glyf );
const WOFF2_Table loca_table = find_table( indices, num_tables,
@ -1453,7 +1512,7 @@
if ( ( !glyf_table && loca_table ) ||
( !loca_table && glyf_table ) )
{
FT_ERROR(( "Cannot have only one of glyf/loca.\n" ));
FT_ERROR(( "Both `glyph' and `loca' tables must be present.\n" ));
return FT_THROW( Invalid_Table );
}
@ -1462,10 +1521,11 @@
{
if ( ( glyf_table->flags & WOFF2_FLAGS_TRANSFORM ) !=
( loca_table->flags & WOFF2_FLAGS_TRANSFORM ) )
{
FT_ERROR(( "Transformation mismatch in glyf and loca." ));
return FT_THROW( Invalid_Table );
}
{
FT_ERROR(( "Transformation mismatch"
" between `glyf' and `loca' table." ));
return FT_THROW( Invalid_Table );
}
}
/* Create buffer for table entries. */
@ -1490,10 +1550,10 @@
FT_TRACE3(( "Seeking to %d with table size %d.\n",
table.src_offset, table.src_length ));
FT_TRACE3(( "Table tag: %c%c%c%c.\n",
(FT_Char)( table.Tag >> 24 ),
(FT_Char)( table.Tag >> 16 ),
(FT_Char)( table.Tag >> 8 ),
(FT_Char)( table.Tag ) ));
(FT_Char)( table.Tag >> 24 ),
(FT_Char)( table.Tag >> 16 ),
(FT_Char)( table.Tag >> 8 ),
(FT_Char)( table.Tag ) ));
if ( FT_STREAM_SEEK( table.src_offset ) )
return FT_THROW( Invalid_Table );
@ -1523,17 +1583,19 @@
/* Set checkSumAdjustment = 0 */
WRITE_ULONG( buf_cursor, 0 );
}
table.dst_offset = dest_offset;
checksum = compute_ULong_sum( transformed_buf + table.src_offset,
table.src_length );
table.dst_offset = dest_offset;
checksum = compute_ULong_sum( transformed_buf + table.src_offset,
table.src_length );
FT_TRACE4(( "Checksum = %09x.\n", checksum ));
if ( WRITE_SFNT_BUF( transformed_buf + table.src_offset,
table.src_length ) )
return FT_THROW( Invalid_Table );
}
else{
else
{
FT_TRACE3(( "This table is transformed.\n" ));
if ( table.Tag == TTAG_glyf )
@ -1541,42 +1603,57 @@
is_glyf_xform = TRUE;
table.dst_offset = dest_offset;
if ( reconstruct_glyf( stream, &table, &checksum,
loca_table, &loca_checksum,
&sfnt, sfnt_size, &dest_offset,
info, memory ) )
if ( reconstruct_glyf( stream,
&table,
&checksum,
loca_table,
&loca_checksum,
&sfnt,
sfnt_size,
&dest_offset,
info,
memory ) )
return FT_THROW( Invalid_Table );
FT_TRACE4(("Checksum = %09x.\n", checksum));
FT_TRACE4(( "Checksum = %09x.\n", checksum ));
}
else if ( table.Tag == TTAG_loca )
{
checksum = loca_checksum;
}
else if ( table.Tag == TTAG_hmtx )
{
/* If glyf is not transformed and hmtx is, handle separately. */
if ( !is_glyf_xform )
{
if ( get_x_mins(stream, indices, num_tables, info, memory) )
if ( get_x_mins( stream, indices, num_tables, info, memory ) )
return FT_THROW( Invalid_Table );
}
table.dst_offset = dest_offset;
if ( reconstruct_hmtx( stream, table.src_length,
info->num_glyphs, info->num_hmetrics,
info->x_mins, &checksum,
&sfnt, sfnt_size,
&dest_offset, memory ) )
if ( reconstruct_hmtx( stream,
table.src_length,
info->num_glyphs,
info->num_hmetrics,
info->x_mins,
&checksum,
&sfnt,
sfnt_size,
&dest_offset,
memory ) )
return FT_THROW( Invalid_Table );
}
else
{
/* Unknown transform */
/* Unknown transform. */
FT_ERROR(( "Unknown table transform.\n" ));
return FT_THROW( Invalid_Table );
}
}
font_checksum += checksum;
buf_cursor = &table_entry[0];
WRITE_ULONG( buf_cursor, table.Tag );
WRITE_ULONG( buf_cursor, checksum );
@ -1606,8 +1683,10 @@
if ( head_table->dst_length < 12 )
goto Fail;
}
buf_cursor = sfnt + head_table->dst_offset + 8;
buf_cursor = sfnt + head_table->dst_offset + 8;
font_checksum = 0xB1B0AFBA - font_checksum;
WRITE_ULONG( buf_cursor, font_checksum );
FT_TRACE2(( "Final checksum = %09x.\n", font_checksum ));
@ -1644,9 +1723,9 @@
FT_Int* face_instance_index,
FT_Long* num_faces )
{
FT_Memory memory = stream->memory;
FT_Error error = FT_Err_Ok;
FT_Int face_index;
FT_Memory memory = stream->memory;
FT_Error error = FT_Err_Ok;
FT_Int face_index;
WOFF2_HeaderRec woff2;
WOFF2_InfoRec info;
@ -1655,22 +1734,22 @@
WOFF2_Table* temp_indices = NULL;
WOFF2_Table last_table;
FT_Int nn;
FT_ULong j;
FT_ULong flags;
FT_UShort xform_version;
FT_ULong src_offset = 0;
FT_Int nn;
FT_ULong j;
FT_ULong flags;
FT_UShort xform_version;
FT_ULong src_offset = 0;
FT_UInt glyf_index;
FT_UInt loca_index;
FT_UInt64 file_offset;
FT_UInt glyf_index;
FT_UInt loca_index;
FT_UInt64 file_offset;
FT_Byte* sfnt = NULL;
FT_Stream sfnt_stream = NULL;
FT_Byte* sfnt_header;
FT_ULong sfnt_size;
FT_Byte* sfnt = NULL;
FT_Stream sfnt_stream = NULL;
FT_Byte* sfnt_header;
FT_ULong sfnt_size;
FT_Byte* uncompressed_buf = NULL;
FT_Byte* uncompressed_buf = NULL;
static const FT_Frame_Field woff2_header_fields[] =
{
@ -1793,6 +1872,7 @@
{
if ( READ_BASE128( table->TransformLength ) )
goto Exit;
if ( table->Tag == TTAG_loca && table->TransformLength )
{
FT_ERROR(( "woff2_open_font: Invalid loca `transformLength'.\n" ));
@ -1810,8 +1890,8 @@
table->src_offset = src_offset;
table->src_length = table->TransformLength;
src_offset += table->TransformLength;
table->flags = flags;
src_offset += table->TransformLength;
table->flags = flags;
FT_TRACE2(( " %c%c%c%c %08d %08d %08ld %08ld\n",
(FT_Char)( table->Tag >> 24 ),
@ -1830,8 +1910,9 @@
/* End of last table is uncompressed size. */
last_table = indices[woff2.num_tables - 1];
woff2.uncompressed_size = last_table->src_offset
+ last_table->src_length;
woff2.uncompressed_size = last_table->src_offset +
last_table->src_length;
if ( woff2.uncompressed_size < last_table->src_offset )
{
error = FT_THROW( Invalid_Table );
@ -1843,8 +1924,11 @@
/* Check for and read collection directory. */
woff2.num_fonts = 1;
woff2.header_version = 0;
if ( woff2.flavor == TTAG_ttcf ){
if ( woff2.flavor == TTAG_ttcf )
{
FT_TRACE2(( "Font is a TTC, reading collection directory.\n" ));
if ( FT_READ_ULONG( woff2.header_version ) )
goto Exit;
@ -1893,7 +1977,7 @@
if ( READ_255USHORT( table_index ) )
goto Exit;
FT_TRACE6(("%hu ", table_index));
FT_TRACE6(( "%hu ", table_index ));
ttc_font->table_indices[j] = table_index;
table = indices[table_index];
@ -1916,15 +2000,16 @@
}
}
}
/* Collection directory reading complete. */
FT_TRACE2(( "WOFF2 collection dirtectory is valid.\n" ));
}
woff2.compressed_offset = FT_STREAM_POS();
file_offset = ROUND4( woff2.compressed_offset +
woff2.totalCompressedSize );
file_offset = ROUND4( woff2.compressed_offset +
woff2.totalCompressedSize );
/* Few more checks before we start reading the tables. */
/* Some more checks before we start reading the tables. */
if ( file_offset > woff2.length )
{
error = FT_THROW( Invalid_Table );
@ -1997,6 +2082,7 @@
for ( nn = 0; nn < ttc_font->num_tables; nn++ )
indices[nn] = temp_indices[nn];
FT_FREE( temp_indices );
/* Change header values. */
@ -2061,15 +2147,22 @@
goto Exit;
/* Uncompress the stream. */
error = woff2_decompress( uncompressed_buf, woff2.uncompressed_size,
stream->cursor, woff2.totalCompressedSize );
error = woff2_decompress( uncompressed_buf,
woff2.uncompressed_size,
stream->cursor,
woff2.totalCompressedSize );
if ( error )
goto Exit;
FT_FRAME_EXIT();
error = reconstruct_font( uncompressed_buf, woff2.uncompressed_size,
indices, &woff2, &info, &sfnt, &sfnt_size,
error = reconstruct_font( uncompressed_buf,
woff2.uncompressed_size,
indices,
&woff2,
&info,
&sfnt,
&sfnt_size,
memory );
if ( error )
goto Exit;
@ -2085,8 +2178,8 @@
goto Exit;
}
/* reconstruct_font has done all the work. */
/* Swap out stream and return. */
/* `reconstruct_font' has done all the work. */
/* Swap out stream and return. */
FT_Stream_OpenMemory( sfnt_stream, sfnt, woff2.actual_sfnt_size );
sfnt_stream->memory = stream->memory;
sfnt_stream->close = stream_close;
@ -2095,8 +2188,7 @@
face->root.stream,
( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
face->root.stream = sfnt_stream;
face->root.stream = sfnt_stream;
face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
/* Set face_index to 0 or -1. */

View File

@ -28,20 +28,20 @@
FT_BEGIN_HEADER
/* Leave the first byte open to store flag_byte. */
/* Leave the first byte open to store `flag_byte'. */
#define WOFF2_FLAGS_TRANSFORM 1 << 8
#define WOFF2_SFNT_HEADER_SIZE 12
#define WOFF2_SFNT_ENTRY_SIZE 16
/* Suggested max size for output. */
/* Suggested maximum size for output. */
#define WOFF2_DEFAULT_MAX_SIZE 30 * 1024 * 1024
/* 98% of Google Fonts have no glyph above 5k bytes. */
#define WOFF2_DEFAULT_GLYPH_BUF 5120
/* Composite glyph flags */
/* See CompositeGlyph.java in `sfntly' for full definitions */
/* Composite glyph flags. */
/* See `CompositeGlyph.java' in `sfntly' for full definitions. */
#define FLAG_ARG_1_AND_2_ARE_WORDS 1 << 0
#define FLAG_WE_HAVE_A_SCALE 1 << 3
#define FLAG_MORE_COMPONENTS 1 << 5

View File

@ -15,11 +15,21 @@
*
*/
#include <ft2build.h>
#include "sfwoff.h"
#include FT_TRUETYPE_TAGS_H
/* Return tag from index in the order given in WOFF2 specification. */
/*
* Return tag from index in the order given in WOFF2 specification.
*
* See
*
* https://www.w3.org/TR/WOFF2/#table_dir_format
*
* for details.
*/
FT_LOCAL_DEF( FT_ULong )
woff2_known_tags( FT_Byte index )
{