From 1b7f95bf708b622334521a210f145ddcc7aa5349 Mon Sep 17 00:00:00 2001 From: Nikhil Ramakrishnan Date: Wed, 12 Jun 2019 00:21:20 +0530 Subject: [PATCH] Read WOFF 2 header. Check for WOFF2 tag, call `woff2_open_font', and implement it to read header according to specification. * include/freetype/internal/fttrace.h: Add `sfwoff2.c'. * src/sfnt/rules.mk: Add `sfwoff2.c'. * src/sfnt/sfnt.c: Include `sfwoff2.c'. * src/sfnt/sfobjs.c: Check for `wOF2' tag and call `woff2_open_font'. * src/sfnt/sfwoff2.c, src/sfnt/sfwoff2.h: New files. --- include/freetype/internal/fttrace.h | 1 + src/sfnt/rules.mk | 1 + src/sfnt/sfnt.c | 1 + src/sfnt/sfobjs.c | 17 +++ src/sfnt/sfwoff2.c | 169 ++++++++++++++++++++++++++++ src/sfnt/sfwoff2.h | 41 +++++++ 6 files changed, 230 insertions(+) create mode 100644 src/sfnt/sfwoff2.c create mode 100644 src/sfnt/sfwoff2.h diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h index f5f959804..77e0e4190 100644 --- a/include/freetype/internal/fttrace.h +++ b/include/freetype/internal/fttrace.h @@ -49,6 +49,7 @@ FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */ FT_TRACE_DEF( sfdriver ) /* SFNT font driver (sfdriver.c) */ FT_TRACE_DEF( sfobjs ) /* SFNT object handler (sfobjs.c) */ FT_TRACE_DEF( sfwoff ) /* WOFF format handler (sfwoff.c) */ +FT_TRACE_DEF( sfwoff2 ) /* WOFF2 format handler (sfwoff2.c) */ FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */ FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */ FT_TRACE_DEF( ttcolr ) /* glyph layer table (ttcolr.c) */ diff --git a/src/sfnt/rules.mk b/src/sfnt/rules.mk index ee3314eac..a77b8ddd1 100644 --- a/src/sfnt/rules.mk +++ b/src/sfnt/rules.mk @@ -32,6 +32,7 @@ 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 \ diff --git a/src/sfnt/sfnt.c b/src/sfnt/sfnt.c index b4faf34a3..9fed618a6 100644 --- a/src/sfnt/sfnt.c +++ b/src/sfnt/sfnt.c @@ -23,6 +23,7 @@ #include "sfdriver.c" #include "sfobjs.c" #include "sfwoff.c" +#include "sfwoff2.c" #include "ttbdf.c" #include "ttcmap.c" #include "ttcolr.c" diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index 6edf3ae1d..b5a6523cf 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -22,6 +22,7 @@ #include "ttcmap.h" #include "ttkern.h" #include "sfwoff.h" +#include "sfwoff2.h" #include FT_INTERNAL_SFNT_H #include FT_INTERNAL_DEBUG_H #include FT_TRUETYPE_IDS_H @@ -385,6 +386,22 @@ goto retry; } + if ( tag == TTAG_wOF2 ) + { + FT_TRACE2(( "sfnt_open_font: file is a WOFF2; synthesizing SFNT\n" )); + + if ( FT_STREAM_SEEK( offset ) ) + return error; + + error = woff2_open_font( stream, face ); + if ( error ) + return error; + + /* Swap out stream and retry! */ + stream = face->root.stream; + goto retry; + } + if ( tag != 0x00010000UL && tag != TTAG_ttcf && tag != TTAG_OTTO && diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c new file mode 100644 index 000000000..e205b6679 --- /dev/null +++ b/src/sfnt/sfwoff2.c @@ -0,0 +1,169 @@ +/**************************************************************************** + * + * sfwoff2.c + * + * WOFF2 format management (base). + * + * Copyright (C) 2019 by + * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + +#include +#include "sfwoff2.h" +#include FT_TRUETYPE_TAGS_H +#include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_STREAM_H + + + /************************************************************************** + * + * The macro FT_COMPONENT is used in trace mode. It is an implicit + * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log + * messages during execution. + */ +#undef FT_COMPONENT +#define FT_COMPONENT sfwoff2 + + + static FT_Error + ReadBase128( FT_Stream stream, + FT_ULong* value ) + { + FT_ULong result = 0; + FT_Int i; + FT_Byte code; + FT_Byte* p = stream->cursor; + + for ( i = 0; i < 5; ++i ) { + code = 0; + code = FT_NEXT_BYTE( p ); + + /* Leading zeros are invalid. */ + if ( i == 0 && code == 0x80 ) { + return FT_THROW( Invalid_Table ); + } + + /* If any of top seven bits are set then we're about to overflow. */ + if ( result & 0xfe000000 ){ + return FT_THROW( Invalid_Table ); + } + + result = ( result << 7 ) | ( code & 0x7f ); + + /* Spin until most significant bit of data byte is false. */ + if ( (code & 0x80) == 0 ) { + *value = result; + return FT_Err_Ok; + } + } + /* Make sure not to exceed the size bound. */ + return FT_THROW( Invalid_Table ); + } + + + /* Replace `face->root.stream' with a stream containing the extracted */ + /* SFNT of a WOFF2 font. */ + + FT_LOCAL_DEF( FT_Error ) + woff2_open_font( FT_Stream stream, + TT_Face face ) + { + FT_Memory memory = stream->memory; + FT_Error error = FT_Err_Ok; + FT_Byte* p = stream->cursor; + FT_Byte* limit = stream->limit; + + WOFF2_HeaderRec woff2; + WOFF2_Table tables = NULL; + WOFF2_Table* indices = NULL; + + static const FT_Frame_Field woff2_header_fields[] = + { +#undef FT_STRUCTURE +#define FT_STRUCTURE WOFF2_HeaderRec + + FT_FRAME_START( 48 ), + FT_FRAME_ULONG ( signature ), + FT_FRAME_ULONG ( flavor ), + FT_FRAME_ULONG ( length ), + FT_FRAME_USHORT( num_tables ), + FT_FRAME_SKIP_BYTES( 2 + 4 ), + FT_FRAME_ULONG ( totalCompressedSize ), + FT_FRAME_SKIP_BYTES( 2 * 2 ), + FT_FRAME_ULONG ( metaOffset ), + FT_FRAME_ULONG ( metaLength ), + FT_FRAME_ULONG ( metaOrigLength ), + FT_FRAME_ULONG ( privOffset ), + FT_FRAME_ULONG ( privLength ), + FT_FRAME_END + }; + + FT_UNUSED( p ); + FT_UNUSED( limit ); + FT_UNUSED( tables ); + FT_UNUSED( indices ); + FT_UNUSED( memory ); + + /* DEBUG - Remove later */ + FT_TRACE2(("woff2_open_font: Received Data.\n")); + + FT_ASSERT( stream == face->root.stream ); + FT_ASSERT( FT_STREAM_POS() == 0 ); + + /* Read WOFF2 Header. */ + if ( FT_STREAM_READ_FIELDS( woff2_header_fields, &woff2 ) ) + return error; + + /* DEBUG - Remove later. */ + FT_TRACE2(("signature -> 0x%X\n", woff2.signature)); + FT_TRACE2(("flavor -> 0x%X\n", woff2.flavor)); + FT_TRACE2(("length -> %lu\n", woff2.length)); + FT_TRACE2(("num_tables -> %hu\n", woff2.num_tables)); + FT_TRACE2(("metaOffset -> %hu\n", woff2.metaOffset)); + FT_TRACE2(("metaLength -> %hu\n", woff2.metaLength)); + FT_TRACE2(("privOffset -> %hu\n", woff2.privOffset)); + FT_TRACE2(("privLength -> %hu\n", woff2.privLength)); + + /* Make sure we don't recurse back here. */ + if ( woff2.flavor == TTAG_wOF2 ) + return FT_THROW( Invalid_Table ); + + /* Miscellaneous checks. */ + if ( woff2.length != stream->size || + woff2.num_tables == 0 || + 48 + woff2.num_tables * 20UL >= woff2.length || + ( woff2.metaOffset == 0 && ( woff2.metaLength != 0 || + woff2.metaOrigLength != 0 ) ) || + ( woff2.metaLength != 0 && woff2.metaOrigLength == 0 ) || + ( woff2.metaOffset >= woff2.length ) || + ( woff2.length - woff2.metaOffset < woff2.metaLength ) || + ( woff2.privOffset == 0 && woff2.privLength != 0 ) || + ( woff2.privOffset >= woff2.length ) || + ( woff2.length - woff2.privOffset < woff2.privLength ) ) + { + FT_ERROR(( "woff_font_open: invalid WOFF2 header\n" )); + return FT_THROW( Invalid_Table ); + } + /* DEBUG - Remove later. */ + else{ + FT_TRACE2(("WOFF2 Header is valid.\n")); + } + + /* TODO Read table directory. */ + + error = FT_THROW( Unimplemented_Feature ); + goto Exit; + + Exit: + return error; + } + + +/* END */ diff --git a/src/sfnt/sfwoff2.h b/src/sfnt/sfwoff2.h new file mode 100644 index 000000000..5c3cc3d72 --- /dev/null +++ b/src/sfnt/sfwoff2.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * + * sfwoff2.h + * + * WOFFF2 format management (specification). + * + * Copyright (C) 2019 by + * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef SFWOFF2_H_ +#define SFWOFF2_H_ + + +#include +#include FT_INTERNAL_SFNT_H +#include FT_INTERNAL_OBJECTS_H + + +FT_BEGIN_HEADER + + + FT_LOCAL( FT_Error ) + woff2_open_font( FT_Stream stream, + TT_Face face ); + + +FT_END_HEADER + +#endif /* SFWOFF2_H_ */ + + +/* END */