diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt index 4a5d1d87d..c20c79bb0 100644 --- a/docs/harfbuzz-sections.txt +++ b/docs/harfbuzz-sections.txt @@ -956,7 +956,9 @@ hb_subset_serialize_or_fail hb_subset_input_override_name_table hb_subset_cff_get_charstring_data +hb_subset_cff_get_charstrings_index hb_subset_cff2_get_charstring_data +hb_subset_cff2_get_charstrings_index
diff --git a/src/gen-def.py b/src/gen-def.py index 063f859ad..be4e68881 100755 --- a/src/gen-def.py +++ b/src/gen-def.py @@ -22,7 +22,9 @@ if '--experimental-api' not in sys.argv: """hb_shape_justify hb_subset_input_override_name_table hb_subset_cff_get_charstring_data +hb_subset_cff_get_charstrings_index hb_subset_cff2_get_charstring_data +hb_subset_cff2_get_charstrings_index """.splitlines () symbols = [x for x in symbols if x not in experimental_symbols] symbols = "\n".join (symbols) diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 5dc6cb240..d4a2b05b8 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -737,6 +737,27 @@ static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_inde return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, bytes.length); } +template +static hb_blob_t* get_charstrings_index(accel_t& accel) { + if (!accel.is_valid()) { + return hb_blob_get_empty (); + } + + const char* charstrings_start = (const char*) accel.charStrings; + unsigned charstrings_length = accel.charStrings->get_size(); + + hb_blob_t* cff_blob = accel.get_blob(); + uint32_t length; + const char* cff_data = hb_blob_get_data(cff_blob, &length) ; + + long int offset = charstrings_start - cff_data; + if (offset < 0 || offset > UINT32_MAX) { + return hb_blob_get_empty (); + } + + return hb_blob_create_sub_blob(cff_blob, (uint32_t) offset, charstrings_length); +} + /** * hb_subset_cff_get_charstring_data: * @face: A face object @@ -746,12 +767,25 @@ static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_inde * * XSince: EXPERIMENTAL **/ - HB_EXTERN hb_blob_t* - hb_subset_cff_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { return get_charstrings_data(*face->table.cff1, glyph_index); - } +} - /** +/** + * hb_subset_cff_get_charstrings_index: + * @face: A face object + * + * Returns the raw CFF CharStrings INDEX from the CFF table. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstrings_index (hb_face_t* face) { + return get_charstrings_index (*face->table.cff1); +} + +/** * hb_subset_cff2_get_charstring_data: * @face: A face object * @glyph_index: Glyph index to get data for. @@ -760,8 +794,21 @@ static hb_blob_t* get_charstrings_data(accel_t& accel, hb_codepoint_t glyph_inde * * XSince: EXPERIMENTAL **/ - HB_EXTERN hb_blob_t* - hb_subset_cff2_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstring_data(hb_face_t* face, hb_codepoint_t glyph_index) { return get_charstrings_data(*face->table.cff2, glyph_index); - } - #endif \ No newline at end of file +} + +/** + * hb_subset_cff2_get_charstrings_index: + * @face: A face object + * + * Returns the raw CFF2 CharStrings INDEX from the CFF2 table. + * + * XSince: EXPERIMENTAL + **/ +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstrings_index (hb_face_t* face) { + return get_charstrings_index (*face->table.cff2); +} +#endif \ No newline at end of file diff --git a/src/hb-subset.h b/src/hb-subset.h index e87c69c09..8d75c0671 100644 --- a/src/hb-subset.h +++ b/src/hb-subset.h @@ -234,8 +234,14 @@ hb_subset_input_override_name_table (hb_subset_input_t *input, HB_EXTERN hb_blob_t* hb_subset_cff_get_charstring_data (hb_face_t* face, hb_codepoint_t glyph_index); +HB_EXTERN hb_blob_t* +hb_subset_cff_get_charstrings_index (hb_face_t* face); + HB_EXTERN hb_blob_t* hb_subset_cff2_get_charstring_data (hb_face_t* face, hb_codepoint_t glyph_index); + +HB_EXTERN hb_blob_t* +hb_subset_cff2_get_charstrings_index (hb_face_t* face); #endif HB_EXTERN hb_face_t * diff --git a/test/api/test-subset.c b/test/api/test-subset.c index b22c76a24..8dd990dd6 100644 --- a/test/api/test-subset.c +++ b/test/api/test-subset.c @@ -248,6 +248,11 @@ const uint8_t CFF2[226] = { 0x10, 0x06 }; +const uint8_t CFF2_ONLY_CHARSTRINGS[12] = { + 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x05, + 0x20, 0x0A, 0x20, 0x0A +}; + static void test_subset_cff2_get_charstring_data (void) { @@ -291,6 +296,39 @@ test_subset_cff2_get_charstring_data (void) hb_blob_destroy (cs2); } +static void +test_subset_cff2_get_all_charstrings_data (void) +{ + const uint8_t maxp_data[6] = { + 0x00, 0x00, 0x50, 0x00, + 0x00, 0x02 // numGlyphs + }; + + hb_blob_t* cff2 = hb_blob_create ((const char*) CFF2, 226, HB_MEMORY_MODE_READONLY, 0, 0); + hb_blob_t* maxp = hb_blob_create ((const char*) maxp_data, 6, HB_MEMORY_MODE_READONLY, 0, 0); + hb_face_t* builder = hb_face_builder_create (); + hb_face_builder_add_table (builder, HB_TAG('C', 'F', 'F', '2'), cff2); + hb_face_builder_add_table (builder, HB_TAG('m', 'a', 'x', 'p'), maxp); + hb_blob_t* face_blob = hb_face_reference_blob (builder); + hb_face_t* face = hb_face_create (face_blob, 0); + + hb_blob_t* cs = hb_subset_cff2_get_charstrings_index (face); + hb_blob_destroy (cff2); + hb_blob_destroy (maxp); + hb_face_destroy (builder); + hb_blob_destroy (face_blob); + hb_face_destroy (face); + + unsigned int length; + const uint8_t* data = (const uint8_t*) hb_blob_get_data (cs, &length); + g_assert_cmpint (length, ==, 12); + for (int i = 0; i < 12; i++) { + g_assert_cmpint(data[i], ==, CFF2_ONLY_CHARSTRINGS[i]); + } + + hb_blob_destroy (cs); +} + static void test_subset_cff2_get_charstring_data_no_cff (void) { @@ -304,8 +342,7 @@ test_subset_cff2_get_charstring_data_no_cff (void) hb_face_destroy (builder); hb_blob_destroy (face_blob); hb_face_destroy (face); - hb_blob_destroy - (cs0); + hb_blob_destroy (cs0); } static void @@ -381,6 +418,7 @@ main (int argc, char **argv) #ifdef HB_EXPERIMENTAL_API hb_test_add (test_subset_cff2_get_charstring_data); + hb_test_add (test_subset_cff2_get_all_charstrings_data); hb_test_add (test_subset_cff2_get_charstring_data_no_cff); hb_test_add (test_subset_cff2_get_charstring_data_invalid_cff2); hb_test_add (test_subset_cff2_get_charstring_data_lifetime);