summaryrefslogtreecommitdiff
path: root/src/cairo-truetype-subset.c
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2008-06-29 19:31:47 +0930
committerAdrian Johnson <ajohnson@redneon.com>2008-06-29 19:31:47 +0930
commit2f99a294cd2367c4649428534b3429522448260c (patch)
tree20fcafb02ddf344fc1d0a015ce33ff56e9ccdc46 /src/cairo-truetype-subset.c
parent95771d62c57c081fe350e0d33326aaa6a27139da (diff)
Add _cairo_truetype_index_to_ucs4()
for doing reverse cmap lookups on truetype/opentype fonts one glyph at a time.
Diffstat (limited to 'src/cairo-truetype-subset.c')
-rw-r--r--src/cairo-truetype-subset.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index c3f0b056..5e4210eb 100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -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;
+}