mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-08 06:48:03 +02:00
Add _cairo_truetype_index_to_ucs4()
for doing reverse cmap lookups on truetype/opentype fonts one glyph at a time.
This commit is contained in:
parent
95771d62c5
commit
2f99a294cd
2 changed files with 173 additions and 0 deletions
|
|
@ -554,4 +554,26 @@ _cairo_type2_charstrings_fini (cairo_type2_charstrings_t *charstrings);
|
|||
cairo_private cairo_int_status_t
|
||||
_cairo_truetype_create_glyph_to_unicode_map (cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
/**
|
||||
* _cairo_truetype_index_to_ucs4:
|
||||
* @scaled_font: the #cairo_scaled_font_t
|
||||
* @index: the glyph index
|
||||
* @ucs4: return value for the unicode value of the glyph
|
||||
*
|
||||
* If possible (depending on the format of the underlying
|
||||
* #cairo_scaled_font_t and the font backend in use) assign
|
||||
* the unicode character of the glyph to @ucs4.
|
||||
*
|
||||
* If mapping glyph indices to unicode is supported but the unicode
|
||||
* value of the specified glyph is not available, @ucs4 is set to -1.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS if successful,
|
||||
* %CAIRO_INT_STATUS_UNSUPPORTED if mapping glyph indices to unicode
|
||||
* is not supported. Possible errors include %CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long index,
|
||||
uint32_t *ucs4);
|
||||
|
||||
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -1318,3 +1318,154 @@ cleanup:
|
|||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long table_offset,
|
||||
unsigned long index,
|
||||
uint32_t *ucs4)
|
||||
{
|
||||
cairo_status_t status;
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
tt_segment_map_t *map;
|
||||
char buf[4];
|
||||
unsigned int num_segments, i;
|
||||
unsigned long size;
|
||||
uint16_t *start_code;
|
||||
uint16_t *end_code;
|
||||
uint16_t *delta;
|
||||
uint16_t *range_offset;
|
||||
uint16_t *glyph_array;
|
||||
uint16_t c;
|
||||
|
||||
backend = scaled_font->backend;
|
||||
size = 4;
|
||||
status = backend->load_truetype_table (scaled_font,
|
||||
TT_TAG_cmap, table_offset,
|
||||
(unsigned char *) &buf,
|
||||
&size);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* All table formats have the same first two words */
|
||||
map = (tt_segment_map_t *) buf;
|
||||
if (be16_to_cpu (map->format) != 4)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
size = be16_to_cpu (map->length);
|
||||
map = malloc (size);
|
||||
if (map == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
status = backend->load_truetype_table (scaled_font,
|
||||
TT_TAG_cmap, table_offset,
|
||||
(unsigned char *) map,
|
||||
&size);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
num_segments = be16_to_cpu (map->segCountX2)/2;
|
||||
end_code = map->endCount;
|
||||
start_code = &(end_code[num_segments + 1]);
|
||||
delta = &(start_code[num_segments]);
|
||||
range_offset = &(delta[num_segments]);
|
||||
glyph_array = &(range_offset[num_segments]);
|
||||
|
||||
/* search for glyph in segments
|
||||
* with rangeOffset=0 */
|
||||
for (i = 0; i < num_segments; i++) {
|
||||
c = index - be16_to_cpu (delta[i]);
|
||||
if (range_offset[i] == 0 &&
|
||||
c >= be16_to_cpu (start_code[i]) &&
|
||||
c <= be16_to_cpu (end_code[i]))
|
||||
{
|
||||
*ucs4 = c;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
/* search for glyph in segments with rangeOffset=1 */
|
||||
for (i = 0; i < num_segments; i++) {
|
||||
if (range_offset[i] != 0) {
|
||||
uint16_t *glyph_ids = &range_offset[i] + be16_to_cpu (range_offset[i])/2;
|
||||
int range_size = be16_to_cpu (end_code[i]) - be16_to_cpu (start_code[i]) + 1;
|
||||
uint16_t g_id_be = cpu_to_be16 (index);
|
||||
int j;
|
||||
|
||||
for (j = 0; j < range_size; j++) {
|
||||
if (glyph_ids[j] == g_id_be) {
|
||||
*ucs4 = be16_to_cpu (start_code[i]) + j;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* glyph not found */
|
||||
*ucs4 = -1;
|
||||
|
||||
found:
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
free (map);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_truetype_index_to_ucs4 (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long index,
|
||||
uint32_t *ucs4)
|
||||
{
|
||||
cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
tt_cmap_t *cmap;
|
||||
char buf[4];
|
||||
int num_tables, i;
|
||||
unsigned long size;
|
||||
|
||||
backend = scaled_font->backend;
|
||||
if (!backend->load_truetype_table)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
size = 4;
|
||||
status = backend->load_truetype_table (scaled_font,
|
||||
TT_TAG_cmap, 0,
|
||||
(unsigned char *) &buf,
|
||||
&size);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
cmap = (tt_cmap_t *) buf;
|
||||
num_tables = be16_to_cpu (cmap->num_tables);
|
||||
size = 4 + num_tables*sizeof(tt_cmap_index_t);
|
||||
cmap = malloc (size);
|
||||
if (cmap == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
status = backend->load_truetype_table (scaled_font,
|
||||
TT_TAG_cmap, 0,
|
||||
(unsigned char *) cmap,
|
||||
&size);
|
||||
if (status)
|
||||
goto cleanup;
|
||||
|
||||
/* Find a table with Unicode mapping */
|
||||
for (i = 0; i < num_tables; i++) {
|
||||
if (be16_to_cpu (cmap->index[i].platform) == 3 &&
|
||||
be16_to_cpu (cmap->index[i].encoding) == 1) {
|
||||
status = _cairo_truetype_reverse_cmap (scaled_font,
|
||||
be32_to_cpu (cmap->index[i].offset),
|
||||
index,
|
||||
ucs4);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free (cmap);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue