From 5367e0ca016bc79096cb3b57217fc1326dc3b997 Mon Sep 17 00:00:00 2001 From: Nikhil Ramakrishnan Date: Mon, 5 Aug 2019 01:53:00 +0530 Subject: [PATCH] [sfnt] Support `face->num_faces' for WOFF2 fonts. Set correct value of `face->num_faces' for WOFF2 fonts. This is being handled separately because we only load the tables for the requested font face in `woff2_open_font' and create a single-face sfnt stream. The full discussion is at: https://lists.gnu.org/archive/html/freetype-devel/2019-08/msg00000.html * src/sfnt/sfobjs.c (sfnt_open_font): Add parameter `woff2_num_faces'. (sfnt_init_face): Introduce variable `woff2_num_faces', and change `face->root.num_faces' if `woff2_num_faces' is set. * src/sfnt/sfwoff2.c (woff2_open_font): Validate requested face index and handle negative face indices. * src/sfnt/sfwoff2.h (woff2_open_font): Add parameter `num_faces' to declaration. --- ChangeLog | 24 ++++++++++++++++++++++++ src/sfnt/sfobjs.c | 20 ++++++++++++++++---- src/sfnt/sfwoff2.c | 34 ++++++++++++++++++++++++++++------ src/sfnt/sfwoff2.h | 3 ++- 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 52087bee3..1a3e19012 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2019-08-27 Nikhil Ramakrishnan + + [sfnt] Support `face->num_faces' for WOFF2 fonts. + + Set correct value of `face->num_faces' for WOFF2 fonts. This is + being handled separately because we only load the tables for the + requested font face in `woff2_open_font' and create a single-face + sfnt stream. + + The full discussion is at: + + https://lists.gnu.org/archive/html/freetype-devel/2019-08/msg00000.html + + * src/sfnt/sfobjs.c (sfnt_open_font): Add parameter + `woff2_num_faces'. + (sfnt_init_face): Introduce variable `woff2_num_faces', and change + `face->root.num_faces' if `woff2_num_faces' is set. + + * src/sfnt/sfwoff2.c (woff2_open_font): Validate requested face + index and handle negative face indices. + + * src/sfnt/sfwoff2.h (woff2_open_font): Add parameter `num_faces' to + declaration. + 2019-08-27 Nikhil Ramakrishnan [woff2] Improve memory and error handling. diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index 7fe25ace7..f6da955ba 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -343,7 +343,8 @@ static FT_Error sfnt_open_font( FT_Stream stream, TT_Face face, - FT_Int* face_instance_index ) + FT_Int* face_instance_index, + FT_Long* woff2_num_faces ) { FT_Memory memory = stream->memory; FT_Error error; @@ -394,7 +395,10 @@ if ( FT_STREAM_SEEK( offset ) ) return error; - error = woff2_open_font( stream, face, face_instance_index ); + error = woff2_open_font( stream, + face, + face_instance_index, + woff2_num_faces ); if ( error ) return error; @@ -479,9 +483,10 @@ FT_Parameter* params ) { FT_Error error; - FT_Library library = face->root.driver->root.library; + FT_Library library = face->root.driver->root.library; SFNT_Service sfnt; FT_Int face_index; + FT_Long woff2_num_faces = 0; /* for now, parameters are unused */ @@ -532,7 +537,10 @@ FT_TRACE2(( "SFNT driver\n" )); - error = sfnt_open_font( stream, face, &face_instance_index ); + error = sfnt_open_font( stream, + face, + &face_instance_index, + &woff2_num_faces ); if ( error ) return error; @@ -707,6 +715,10 @@ face->root.num_faces = face->ttc_header.count; face->root.face_index = face_instance_index; + /* `num_faces' for a WOFF2 needs to be handled separately. */ + if( woff2_num_faces ) + face->root.num_faces = woff2_num_faces; + return error; } diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c index cda2b59a0..cbdaa8bf8 100644 --- a/src/sfnt/sfwoff2.c +++ b/src/sfnt/sfwoff2.c @@ -1535,11 +1535,12 @@ FT_LOCAL_DEF( FT_Error ) woff2_open_font( FT_Stream stream, TT_Face face, - FT_Int* face_instance_index ) + FT_Int* face_instance_index, + FT_Long* num_faces ) { FT_Memory memory = stream->memory; FT_Error error = FT_Err_Ok; - FT_Int face_index = *face_instance_index; + FT_Int face_index; WOFF2_HeaderRec woff2; WOFF2_InfoRec info; @@ -1594,6 +1595,7 @@ FT_ASSERT( stream == face->root.stream ); FT_ASSERT( FT_STREAM_POS() == 0 ); + face_index = FT_ABS( *face_instance_index ) & 0xFFFF; /* DEBUG - Remove later. */ FT_TRACE2(( "Face index = %ld\n", face_index )); @@ -1734,6 +1736,7 @@ FT_TRACE2(( "Table directory successfully parsed.\n" )); /* Check for and read collection directory. */ + woff2.num_fonts = 1; woff2.header_version = 0; if( woff2.flavor == TTAG_ttcf ){ FT_TRACE2(( "Font is a TTC, reading collection directory.\n" )); @@ -1848,12 +1851,28 @@ goto Exit; } + /* Validate requested face index. */ + *num_faces = woff2.num_fonts; + /* value -(N+1) requests information on index N */ + if ( *face_instance_index < 0 ) + face_index--; + + if( face_index >= woff2.num_fonts ) + { + if ( *face_instance_index >= 0 ) + { + error = FT_THROW( Invalid_Argument ); + goto Exit; + } + else + face_index = 0; + } + /* Only retain tables of the requested face in a TTC. */ - /* TODO Check whether it is OK for rest of the code to be unaware of the - fact that we're working with a TTC. */ if( woff2.header_version ) { WOFF2_TtcFont ttc_font = woff2.ttc_fonts + face_index; + /* Create a temporary array. */ if( FT_NEW_ARRAY( temp_indices, ttc_font->num_tables ) ) @@ -1989,8 +2008,11 @@ face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; - /* Set face_index to 0. */ - *face_instance_index = 0; + /* Set face_index. */ + if( *face_instance_index < 0 ) + *face_instance_index = -1; + else + *face_instance_index = 0; /* error = FT_THROW( Unimplemented_Feature ); */ /* DEBUG - Remove later */ diff --git a/src/sfnt/sfwoff2.h b/src/sfnt/sfwoff2.h index b4f1ac594..b1d46ad0d 100644 --- a/src/sfnt/sfwoff2.h +++ b/src/sfnt/sfwoff2.h @@ -64,7 +64,8 @@ FT_BEGIN_HEADER FT_LOCAL( FT_Error ) woff2_open_font( FT_Stream stream, TT_Face face, - FT_Int* face_index ); + FT_Int* face_index, + FT_Long* num_faces ); FT_END_HEADER