mirror of
https://github.com/harfbuzz/harfbuzz.git
synced 2025-04-13 00:32:59 +00:00
[face] Add fallback implementation to hb_face_reference_blob
If referencing the face blob is not possible (e.g. not implemented by the font functions), use face builder to create a blob out of individual table blobs. Fixes https://github.com/harfbuzz/harfbuzz/issues/5036
This commit is contained in:
parent
9cf2ea3e8f
commit
4825e5e2b4
2 changed files with 108 additions and 3 deletions
|
@ -504,7 +504,37 @@ hb_face_reference_table (const hb_face_t *face,
|
|||
hb_blob_t *
|
||||
hb_face_reference_blob (hb_face_t *face)
|
||||
{
|
||||
return face->reference_table (HB_TAG_NONE);
|
||||
hb_blob_t *blob = face->reference_table (HB_TAG_NONE);
|
||||
|
||||
if (blob == hb_blob_get_empty ())
|
||||
{
|
||||
// If referencing the face blob is not possible (e.g. not implemented by the
|
||||
// font functions), use face builder to create a blob out of individual
|
||||
// table blobs.
|
||||
unsigned total_count = hb_face_get_table_tags (face, 0, nullptr, nullptr);
|
||||
if (total_count)
|
||||
{
|
||||
hb_tag_t tags[10];
|
||||
unsigned count = sizeof (tags) / sizeof (tags[0]);
|
||||
hb_face_t* builder = hb_face_builder_create ();
|
||||
|
||||
for (unsigned offset = 0; offset < total_count; offset += count)
|
||||
{
|
||||
hb_face_get_table_tags (face, offset, &count, tags);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
hb_blob_t *table = hb_face_reference_table (face, tags[i]);
|
||||
hb_face_builder_add_table (builder, tags[i], table);
|
||||
hb_blob_destroy (table);
|
||||
}
|
||||
}
|
||||
|
||||
blob = hb_face_reference_blob (builder);
|
||||
hb_face_destroy (builder);
|
||||
}
|
||||
}
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,11 +82,19 @@ free_up (void *user_data)
|
|||
(*freed)++;
|
||||
}
|
||||
|
||||
static hb_tag_t test_tags[] = {
|
||||
HB_TAG ('a','b','c','d'),
|
||||
HB_TAG ('e','f','g','h'),
|
||||
};
|
||||
|
||||
static hb_blob_t *
|
||||
get_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data HB_UNUSED)
|
||||
{
|
||||
if (tag == HB_TAG ('a','b','c','d'))
|
||||
return hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL);
|
||||
for (unsigned i = 0; i < sizeof (test_tags) / sizeof (test_tags[0]); i++)
|
||||
{
|
||||
if (test_tags[i] == tag)
|
||||
return hb_blob_create (test_data, sizeof (test_data), HB_MEMORY_MODE_READONLY, NULL, NULL);
|
||||
}
|
||||
|
||||
return hb_blob_get_empty ();
|
||||
}
|
||||
|
@ -119,6 +127,72 @@ test_face_createfortables (void)
|
|||
g_assert (freed);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
get_table_tags (const hb_face_t *face HB_UNUSED,
|
||||
unsigned int start_offset,
|
||||
unsigned int *table_count,
|
||||
hb_tag_t *table_tags,
|
||||
void *user_data)
|
||||
{
|
||||
unsigned count = sizeof (test_tags) / sizeof (test_tags[0]);
|
||||
unsigned end_offset;
|
||||
|
||||
if (!table_count)
|
||||
return count;
|
||||
|
||||
if (start_offset >= count)
|
||||
{
|
||||
*table_count = 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
end_offset = start_offset + *table_count;
|
||||
if (end_offset < start_offset)
|
||||
{
|
||||
*table_count = 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
end_offset = end_offset < count ? end_offset : count;
|
||||
|
||||
*table_count = end_offset - start_offset;
|
||||
|
||||
for (unsigned i = start_offset; i < end_offset; i++)
|
||||
table_tags[i - start_offset] = test_tags[i];
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
test_face_referenceblob (void)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
hb_face_t *face;
|
||||
int freed = 0;
|
||||
|
||||
face = hb_face_create_for_tables (get_table, &freed, free_up);
|
||||
hb_face_set_get_table_tags_func (face, get_table_tags, NULL, NULL);
|
||||
|
||||
blob = hb_face_reference_blob (face);
|
||||
hb_face_destroy (face);
|
||||
|
||||
g_assert (blob != hb_blob_get_empty ());
|
||||
|
||||
face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
g_assert (face != hb_face_get_empty ());
|
||||
g_assert_cmpuint (hb_face_get_table_tags (face, 0, NULL, NULL), ==, sizeof (test_tags) / sizeof (test_tags[0]));
|
||||
for (unsigned i = 0; i < sizeof (test_tags) / sizeof (test_tags[0]); i++)
|
||||
{
|
||||
hb_blob_t* table = hb_face_reference_table (face, test_tags[i]);
|
||||
g_assert (table != hb_blob_get_empty ());
|
||||
hb_blob_destroy (table);
|
||||
}
|
||||
|
||||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
static void
|
||||
_test_font_nil_funcs (hb_font_t *font)
|
||||
{
|
||||
|
@ -606,6 +680,7 @@ main (int argc, char **argv)
|
|||
hb_test_add (test_face_empty);
|
||||
hb_test_add (test_face_create);
|
||||
hb_test_add (test_face_createfortables);
|
||||
hb_test_add (test_face_referenceblob);
|
||||
|
||||
hb_test_add (test_fontfuncs_empty);
|
||||
hb_test_add (test_fontfuncs_nil);
|
||||
|
|
Loading…
Add table
Reference in a new issue