From 60c52f0edbfaddcfcc87e01922fa5f7640e11cf5 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Tue, 27 Aug 2019 10:08:01 +0200 Subject: [PATCH] [woff2] Formatting; some comments. --- builds/unix/configure.raw | 8 +- include/freetype/internal/wofftypes.h | 6 +- src/sfnt/rules.mk | 28 +- src/sfnt/sfwoff2.c | 402 ++++++++++++++++---------- src/sfnt/sfwoff2.h | 8 +- src/sfnt/woff2tags.c | 12 +- 6 files changed, 283 insertions(+), 181 deletions(-) diff --git a/builds/unix/configure.raw b/builds/unix/configure.raw index 5a3504258..a98f3c6ad 100644 --- a/builds/unix/configure.raw +++ b/builds/unix/configure.raw @@ -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, \ diff --git a/include/freetype/internal/wofftypes.h b/include/freetype/internal/wofftypes.h index 381449b73..5741fbabb 100644 --- a/include/freetype/internal/wofftypes.h +++ b/include/freetype/internal/wofftypes.h @@ -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_ { diff --git a/src/sfnt/rules.mk b/src/sfnt/rules.mk index 09802a576..42b0352ca 100644 --- a/src/sfnt/rules.mk +++ b/src/sfnt/rules.mk @@ -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 diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c index 9099b43e2..fc4094d2c 100644 --- a/src/sfnt/sfwoff2.c +++ b/src/sfnt/sfwoff2.c @@ -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. */ diff --git a/src/sfnt/sfwoff2.h b/src/sfnt/sfwoff2.h index b1d46ad0d..679a8a2ff 100644 --- a/src/sfnt/sfwoff2.h +++ b/src/sfnt/sfwoff2.h @@ -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 diff --git a/src/sfnt/woff2tags.c b/src/sfnt/woff2tags.c index 45ef3fa32..47b11865e 100644 --- a/src/sfnt/woff2tags.c +++ b/src/sfnt/woff2tags.c @@ -15,11 +15,21 @@ * */ + #include #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 ) {