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.
This commit is contained in:
Nikhil Ramakrishnan 2019-06-12 00:21:20 +05:30
parent c26c91aa39
commit 1b7f95bf70
6 changed files with 230 additions and 0 deletions

View File

@ -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) */

View File

@ -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 \

View File

@ -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"

View File

@ -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 &&

169
src/sfnt/sfwoff2.c Normal file
View File

@ -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 <ft2build.h>
#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 */

41
src/sfnt/sfwoff2.h Normal file
View File

@ -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 <ft2build.h>
#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 */