static cairo_status_t cairo_truetype_font_write_head_table (cairo_truetype_font_t *font, unsigned long tag) { unsigned char *buffer; unsigned long size; cairo_status_t status; if (font->status) return font->status; size = 0; status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, tag, 0, NULL, &size); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); font->checksum_index = _cairo_array_num_elements (&font->output) + 8; status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, tag, 0, buffer, &size); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); /* set checkSumAdjustment to 0 for table checksum calcualtion */ *(uint32_t *)(buffer + 8) = 0; return CAIRO_STATUS_SUCCESS; }
static cairo_status_t cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font, unsigned long tag) { tt_maxp_t *maxp; unsigned long size; cairo_status_t status; if (font->status) return font->status; size = sizeof (tt_maxp_t); status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, tag, 0, (unsigned char *) maxp, &size); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs); return CAIRO_STATUS_SUCCESS; }
static cairo_status_t cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font, unsigned long tag) { cairo_status_t status; unsigned char *buffer; unsigned long size; if (font->status) return font->status; size = 0; status = font->backend->load_truetype_table(font->scaled_font_subset->scaled_font, tag, 0, NULL, &size); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, tag, 0, buffer, &size); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); return CAIRO_STATUS_SUCCESS; }
static cairo_status_t cairo_truetype_font_write_offset_table (cairo_truetype_font_t *font) { cairo_status_t status; unsigned char *table_buffer; size_t table_buffer_length; unsigned short search_range, entry_selector, range_shift; search_range = 1; entry_selector = 0; while (search_range * 2 <= font->num_tables) { search_range *= 2; entry_selector++; } search_range *= 16; range_shift = font->num_tables * 16 - search_range; cairo_truetype_font_write_be32 (font, SFNT_VERSION); cairo_truetype_font_write_be16 (font, font->num_tables); cairo_truetype_font_write_be16 (font, search_range); cairo_truetype_font_write_be16 (font, entry_selector); cairo_truetype_font_write_be16 (font, range_shift); /* Allocate space for the table directory. Each directory entry * will be filled in by cairo_truetype_font_update_entry() after * the table is written. */ table_buffer_length = font->num_tables * 16; status = cairo_truetype_font_allocate_write_buffer (font, table_buffer_length, &table_buffer); if (status) return status; return font->status; }
static cairo_status_t cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font, unsigned long tag) { unsigned long size; unsigned long long_entry_size; unsigned long short_entry_size; short *p; unsigned int i; tt_hhea_t hhea; int num_hmetrics; size = sizeof (tt_hhea_t); font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, TT_TAG_hhea, 0, (unsigned char*) &hhea, &size); if (font->status) return font->status; num_hmetrics = be16_to_cpu(hhea.num_hmetrics); for (i = 0; i < font->base.num_glyphs; i++) { long_entry_size = 2 * sizeof (int16_t); short_entry_size = sizeof (int16_t); font->status = cairo_truetype_font_allocate_write_buffer (font, long_entry_size, (unsigned char **) &p); if (font->status) return font->status; if (font->glyphs[i].parent_index < num_hmetrics) { if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, TT_TAG_hmtx, font->glyphs[i].parent_index * long_entry_size, (unsigned char *) p, &long_entry_size) != CAIRO_STATUS_SUCCESS) { font->status = CAIRO_INT_STATUS_UNSUPPORTED; return font->status; } } else { if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, TT_TAG_hmtx, (num_hmetrics - 1) * long_entry_size, (unsigned char *) p, &short_entry_size) != CAIRO_STATUS_SUCCESS) { font->status = CAIRO_INT_STATUS_UNSUPPORTED; return font->status; } font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, TT_TAG_hmtx, num_hmetrics * long_entry_size + (font->glyphs[i].parent_index - num_hmetrics) * short_entry_size, (unsigned char *) (p + 1), &short_entry_size); if (font->status) return font->status; } font->base.widths[i] = be16_to_cpu (p[0]); } return font->status; }
static cairo_status_t cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font, unsigned long tag) { cairo_status_t status; unsigned char *buffer; unsigned long size; size = 0; if (font->backend->load_truetype_table( font->scaled_font_subset->scaled_font, tag, 0, NULL, &size) != CAIRO_STATUS_SUCCESS) { font->status = CAIRO_INT_STATUS_UNSUPPORTED; return font->status; } status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); if (status) return status; status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, tag, 0, buffer, &size); if (status) return status; return CAIRO_STATUS_SUCCESS; }
static unsigned long cairo_truetype_font_align_output (cairo_truetype_font_t *font) { int length, aligned, pad; unsigned char *padding; length = _cairo_array_num_elements (&font->output); aligned = (length + 3) & ~3; pad = aligned - length; if (pad) { cairo_truetype_font_allocate_write_buffer (font, pad, &padding); memset (padding, 0, pad); } return aligned; }
static cairo_status_t cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag) { tt_hhea_t *hhea; unsigned long size; size = sizeof (tt_hhea_t); font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &hhea); if (font->status) return font->status; font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, tag, 0, (unsigned char *) hhea, &size); if (font->status) return font->status; hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs)); return font->status; }
static cairo_status_t cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font, unsigned long tag) { tt_maxp_t *maxp; unsigned long size; size = sizeof (tt_maxp_t); font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp); if (font->status) return font->status; font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, tag, 0, (unsigned char *) maxp, &size); if (font->status) return font->status; maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs); return font->status; }
static cairo_status_t cairo_truetype_font_align_output (cairo_truetype_font_t *font, unsigned long *aligned) { int length, pad; unsigned char *padding; length = _cairo_array_num_elements (&font->output); *aligned = (length + 3) & ~3; pad = *aligned - length; if (pad) { cairo_status_t status; status = cairo_truetype_font_allocate_write_buffer (font, pad, &padding); if (unlikely (status)) return status; memset (padding, 0, pad); } return CAIRO_STATUS_SUCCESS; }
static cairo_status_t cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font, unsigned long tag) { unsigned long start_offset, index, size, next; tt_head_t header; unsigned long begin, end; unsigned char *buffer; unsigned int i; union { unsigned char *bytes; uint16_t *short_offsets; uint32_t *long_offsets; } u; cairo_status_t status; if (font->status) return font->status; size = sizeof (tt_head_t); status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, TT_TAG_head, 0, (unsigned char*) &header, &size); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); if (be16_to_cpu (header.index_to_loc_format) == 0) size = sizeof (int16_t) * (font->num_glyphs_in_face + 1); else size = sizeof (int32_t) * (font->num_glyphs_in_face + 1); u.bytes = malloc (size); if (unlikely (u.bytes == NULL)) return _cairo_truetype_font_set_error (font, CAIRO_STATUS_NO_MEMORY); status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, TT_TAG_loca, 0, u.bytes, &size); if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); start_offset = _cairo_array_num_elements (&font->output); for (i = 0; i < font->base.num_glyphs; i++) { index = font->glyphs[i].parent_index; if (be16_to_cpu (header.index_to_loc_format) == 0) { begin = be16_to_cpu (u.short_offsets[index]) * 2; end = be16_to_cpu (u.short_offsets[index + 1]) * 2; } else { begin = be32_to_cpu (u.long_offsets[index]); end = be32_to_cpu (u.long_offsets[index + 1]); } /* quick sanity check... */ if (end < begin) { status = CAIRO_INT_STATUS_UNSUPPORTED; goto FAIL; } size = end - begin; status = cairo_truetype_font_align_output (font, &next); if (unlikely (status)) goto FAIL; status = cairo_truetype_font_check_boundary (font, next); if (unlikely (status)) goto FAIL; font->glyphs[i].location = next - start_offset; status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer); if (unlikely (status)) goto FAIL; if (size != 0) { status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, TT_TAG_glyf, begin, buffer, &size); if (unlikely (status)) goto FAIL; status = cairo_truetype_font_remap_composite_glyph (font, buffer, size); if (unlikely (status)) goto FAIL; } } status = cairo_truetype_font_align_output (font, &next); if (unlikely (status)) goto FAIL; font->glyphs[i].location = next - start_offset; status = font->status; FAIL: free (u.bytes); return _cairo_truetype_font_set_error (font, status); }