[sfnt] 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 (SFNT_DRV_SRC): Add `sfwoff2.c'. * src/sfnt/sfnt.c: Include `sfwoff2.c'. * src/sfnt/sfobjs.c (sfnt_open_font): Check for `wOF2' tag and call `woff2_open_font'. * src/sfnt/sfwoff2.c, src/sfnt/sfwoff2.h: New files.
This commit is contained in:
parent
83dba0e9ec
commit
2fa573c1b0
18
ChangeLog
18
ChangeLog
|
@ -1,3 +1,21 @@
|
|||
2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
|
||||
|
||||
[sfnt] 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 (SFNT_DRV_SRC): Add `sfwoff2.c'.
|
||||
|
||||
* src/sfnt/sfnt.c: Include `sfwoff2.c'.
|
||||
|
||||
* src/sfnt/sfobjs.c (sfnt_open_font): Check for `wOF2' tag and call
|
||||
`woff2_open_font'.
|
||||
|
||||
* src/sfnt/sfwoff2.c, src/sfnt/sfwoff2.h: New files.
|
||||
|
||||
2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
|
||||
|
||||
Add structures for WOFF2.
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
Loading…
Reference in New Issue