diff --git a/src/Makefile.am b/src/Makefile.am index f490607..990e4ee --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,11 @@ font_subset_sources = \ cairo-font-subset.c \ cairo-font-subset-private.h \ - cairo-type1-subset.c \ cairo-scaled-font-subsets.c \ cairo-scaled-font-subsets-private.h +if CAIRO_HAS_FT_FONT +font_subset_sources += cairo-type1-subset.c +endif backend_pkgconfigs = diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c index dc21d14..e2f691a --- a/src/cairo-font-subset.c +++ b/src/cairo-font-subset.c @@ -33,17 +33,10 @@ * Kristian Høgsberg */ +#include #include "cairoint.h" #include "cairo-scaled-font-subsets-private.h" -/* XXX: Eventually, we need to handle other font backends */ -#include "cairo-ft-private.h" - -#include -#include FT_FREETYPE_H -#include FT_OUTLINE_H -#include FT_TRUETYPE_TAGS_H -#include FT_TRUETYPE_TABLES_H typedef struct ft_subset_glyph ft_subset_glyph_t; struct ft_subset_glyph { @@ -56,7 +49,6 @@ typedef struct _cairo_ft_font { cairo_scaled_font_subset_t *scaled_font_subset; struct { - cairo_unscaled_font_t *unscaled_font; unsigned int font_id; char *base_font; int num_glyphs; @@ -66,7 +58,8 @@ typedef struct _cairo_ft_font { } base; ft_subset_glyph_t *glyphs; - FT_Face face; + const cairo_scaled_font_backend_t *backend; + int num_glyphs_in_face; int checksum_index; cairo_array_t output; int *parent_to_subset; @@ -74,6 +67,92 @@ typedef struct _cairo_ft_font { } cairo_pdf_ft_font_t; + + +#define MAKE_TT_TAG(a, b, c, d) (a<<24 | b<<16 | c<<8 | d) +#define TT_TAG_cmap MAKE_TT_TAG('c','m','a','p') +#define TT_TAG_cvt MAKE_TT_TAG('c','v','t',' ') +#define TT_TAG_fpgm MAKE_TT_TAG('f','p','g','m') +#define TT_TAG_glyf MAKE_TT_TAG('g','l','y','f') +#define TT_TAG_head MAKE_TT_TAG('h','e','a','d') +#define TT_TAG_hhea MAKE_TT_TAG('h','h','e','a') +#define TT_TAG_hmtx MAKE_TT_TAG('h','m','t','x') +#define TT_TAG_loca MAKE_TT_TAG('l','o','c','a') +#define TT_TAG_maxp MAKE_TT_TAG('m','a','x','p') +#define TT_TAG_name MAKE_TT_TAG('n','a','m','e') +#define TT_TAG_prep MAKE_TT_TAG('p','r','e','p') + +/* All tt_* structs are big-endian */ +typedef struct tt_head { + long version; /* FIXED */ + long revision; /* FIXED */ + unsigned long checksum; + unsigned long magic; + unsigned short flags; + unsigned short units_per_em; + long created; + long modified; + short x_min; /* FWORD */ + short y_min; /* FWORD */ + short x_max; /* FWORD */ + short y_max; /* FWORD */ + unsigned short mac_style; + unsigned short lowest_rec_pppem; + short font_direction_hint; + short index_to_loc_format; + short glyph_data_format; +} tt_head_t; + +typedef struct tt_hhea { + long version; /* FIXED */ + short ascender; /* FWORD */ + short descender; /* FWORD */ + short line_gap; /* FWORD */ + unsigned short advance_max_width; /* UFWORD */ + short min_left_side_bearing; /* FWORD */ + short min_right_side_bearing; /* FWORD */ + short x_max_extent; /* FWORD */ + short caret_slope_rise; + short caret_slope_run; + short reserved[5]; + short metric_data_format; + unsigned short num_hmetrics; +} tt_hhea_t; + +typedef struct tt_maxp { + long version; /* FIXED */ + unsigned short num_glyphs; + unsigned short max_points; + unsigned short max_contours; + unsigned short max_composite_points; + unsigned short max_composite_contours; + unsigned short max_zones; + unsigned short max_twilight_points; + unsigned short max_storage; + unsigned short max_function_defs; + unsigned short max_instruction_defs; + unsigned short max_stack_elements; + unsigned short max_size_of_instructions; + unsigned short max_component_elements; + unsigned short max_component_depth; +} tt_maxp_t; + +typedef struct tt_name_record { + unsigned short platform; + unsigned short encoding; + unsigned short language; + unsigned short name; + unsigned short length; + unsigned short offset; +} tt_name_record_t; + +typedef struct tt_name { + unsigned short format; + unsigned short num_records; + unsigned short strings_offset; + tt_name_record_t records[1]; +} tt_name_t; + static int cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph); @@ -120,66 +199,102 @@ static cairo_status_t _cairo_pdf_ft_font_create (cairo_scaled_font_subset_t *scaled_font_subset, cairo_pdf_ft_font_t **font_return) { - cairo_unscaled_font_t *unscaled_font; - cairo_ft_unscaled_font_t *ft_unscaled_font; cairo_status_t status = CAIRO_STATUS_NO_MEMORY; cairo_pdf_ft_font_t *font; - FT_Face face; + const cairo_scaled_font_backend_t *backend; + tt_head_t head; + tt_hhea_t hhea; + tt_maxp_t maxp; + tt_name_t *name; + tt_name_record_t *record; unsigned long size; int i, j; - /* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */ - if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font)) + backend = scaled_font_subset->scaled_font->backend; + if (!backend->load_truetype_table) return CAIRO_INT_STATUS_UNSUPPORTED; - if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font); + size = sizeof(tt_head_t); + if (backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_head, 0, (unsigned char *) &head, + &size) != CAIRO_STATUS_SUCCESS) + return CAIRO_INT_STATUS_UNSUPPORTED; - ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font; + size = sizeof(tt_maxp_t); + if (backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_maxp, 0, (unsigned char *) &maxp, + &size) != CAIRO_STATUS_SUCCESS) + return CAIRO_INT_STATUS_UNSUPPORTED; - face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font); - if (face == NULL) - /* Assume out of memory */ - return CAIRO_STATUS_NO_MEMORY; + size = sizeof(tt_hhea_t); + if (backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_hhea, 0, (unsigned char *) &hhea, + &size) != CAIRO_STATUS_SUCCESS) + return CAIRO_INT_STATUS_UNSUPPORTED; - /* We currently only support freetype truetype fonts. */ size = 0; - if (!FT_IS_SFNT (face) || - FT_Load_Sfnt_Table (face, TTAG_glyf, 0, NULL, &size) != 0) + if (backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_name, 0, NULL, + &size) != CAIRO_STATUS_SUCCESS) return CAIRO_INT_STATUS_UNSUPPORTED; + name = malloc(size); + if (name == NULL) + return CAIRO_STATUS_NO_MEMORY; + backend->load_truetype_table (scaled_font_subset->scaled_font, + TT_TAG_name, 0, (unsigned char *) name, + &size); + +/* FIXME + if (_cairo_ft_scaled_font_is_vertical (scaled_font_subset->scaled_font)) + return CAIRO_INT_STATUS_UNSUPPORTED; */ font = malloc (sizeof (cairo_pdf_ft_font_t)); if (font == NULL) - return CAIRO_STATUS_NO_MEMORY; + goto fail0; + font->backend = backend; + font->num_glyphs_in_face = be16_to_cpu(maxp.num_glyphs); font->scaled_font_subset = scaled_font_subset; - - font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font); - + _cairo_array_init (&font->output, sizeof (char)); if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS) goto fail1; - - font->glyphs = calloc (face->num_glyphs + 1, sizeof (ft_subset_glyph_t)); + font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (ft_subset_glyph_t)); if (font->glyphs == NULL) goto fail2; - font->parent_to_subset = calloc (face->num_glyphs, sizeof (int)); + font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int)); if (font->parent_to_subset == NULL) goto fail3; font->base.num_glyphs = 0; - font->base.x_min = face->bbox.xMin; - font->base.y_min = face->bbox.yMin; - font->base.x_max = face->bbox.xMax; - font->base.y_max = face->bbox.yMax; - font->base.ascent = face->ascender; - font->base.descent = face->descender; - font->base.base_font = strdup (face->family_name); + font->base.x_min = be16_to_cpu (head.x_min); + font->base.y_min = be16_to_cpu (head.y_min); + font->base.x_max = be16_to_cpu (head.x_max); + font->base.y_max = be16_to_cpu (head.y_max); + font->base.ascent = be16_to_cpu (hhea.ascender); + font->base.descent = be16_to_cpu (hhea.descender); + + + font->base.base_font = NULL; + for (i = 0; i < be16_to_cpu(name->num_records); i++) { + record = &(name->records[i]); + if ((be16_to_cpu(record->platform) == 1) && + (be16_to_cpu(record->encoding) == 0) && + (be16_to_cpu(record->name) == 4)) { + font->base.base_font = malloc(be16_to_cpu(record->length) + 1); + if (font->base.base_font) { + strncpy(font->base.base_font, + ((char*)name) + be16_to_cpu(name->strings_offset) + be16_to_cpu(record->offset), + be16_to_cpu(record->length)); + font->base.base_font[be16_to_cpu(record->length)] = 0; + } + break; + } + } + if (font->base.base_font == NULL) - goto fail4; + goto fail4; for (i = 0, j = 0; font->base.base_font[j]; j++) { if (font->base.base_font[j] == ' ') @@ -188,11 +303,9 @@ _cairo_pdf_ft_font_create (cairo_scaled_ } font->base.base_font[i] = '\0'; - font->base.widths = calloc (face->num_glyphs, sizeof (int)); + font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int)); if (font->base.widths == NULL) - goto fail5; - - _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); + goto fail5; font->status = CAIRO_STATUS_SUCCESS; @@ -210,14 +323,14 @@ _cairo_pdf_ft_font_create (cairo_scaled_ _cairo_array_fini (&font->output); fail1: free (font); - + fail0: + free (name); return status; } static void cairo_pdf_ft_font_destroy (cairo_pdf_ft_font_t *font) { - _cairo_unscaled_font_destroy (font->base.unscaled_font); free (font->base.base_font); free (font->parent_to_subset); free (font->glyphs); @@ -321,11 +434,12 @@ cairo_pdf_ft_font_write_generic_table (c unsigned long size; size = 0; - FT_Load_Sfnt_Table (font->face, tag, 0, NULL, &size); + font->backend->load_truetype_table( font->scaled_font_subset->scaled_font, + tag, 0, NULL, &size); status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer); /* XXX: Need to check status here. */ - FT_Load_Sfnt_Table (font->face, tag, 0, buffer, &size); - + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + tag, 0, buffer, &size); return 0; } @@ -390,7 +504,7 @@ cairo_pdf_ft_font_write_glyf_table (cair { cairo_status_t status; unsigned long start_offset, index, size; - TT_Header *header; + tt_head_t header; unsigned long begin, end; unsigned char *buffer; int i; @@ -400,23 +514,27 @@ cairo_pdf_ft_font_write_glyf_table (cair unsigned long *long_offsets; } u; - header = FT_Get_Sfnt_Table (font->face, ft_sfnt_head); - if (header->Index_To_Loc_Format == 0) - size = sizeof (short) * (font->face->num_glyphs + 1); + size = sizeof (tt_head_t); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_head, 0, (unsigned char*) &header, &size); + + if (be16_to_cpu (header.index_to_loc_format) == 0) + size = sizeof (short) * (font->num_glyphs_in_face + 1); else - size = sizeof (long) * (font->face->num_glyphs + 1); + size = sizeof (long) * (font->num_glyphs_in_face + 1); u.bytes = malloc (size); if (u.bytes == NULL) { font->status = CAIRO_STATUS_NO_MEMORY; return font->status; } - FT_Load_Sfnt_Table (font->face, TTAG_loca, 0, u.bytes, &size); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_loca, 0, u.bytes, &size); start_offset = _cairo_array_num_elements (&font->output); for (i = 0; i < font->base.num_glyphs; i++) { index = font->glyphs[i].parent_index; - if (header->Index_To_Loc_Format == 0) { + 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; } @@ -433,7 +551,8 @@ cairo_pdf_ft_font_write_glyf_table (cair if (status) break; if (size != 0) { - FT_Load_Sfnt_Table (font->face, TTAG_glyf, begin, buffer, &size); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_glyf, begin, buffer, &size); cairo_pdf_ft_font_remap_composite_glyph (font, buffer); } } @@ -450,68 +569,29 @@ static int cairo_pdf_ft_font_write_head_table (cairo_pdf_ft_font_t *font, unsigned long tag) { - TT_Header *head; - - head = FT_Get_Sfnt_Table (font->face, ft_sfnt_head); - - cairo_pdf_ft_font_write_be32 (font, head->Table_Version); - cairo_pdf_ft_font_write_be32 (font, head->Font_Revision); - - font->checksum_index = _cairo_array_num_elements (&font->output); - cairo_pdf_ft_font_write_be32 (font, 0); - cairo_pdf_ft_font_write_be32 (font, head->Magic_Number); - - cairo_pdf_ft_font_write_be16 (font, head->Flags); - cairo_pdf_ft_font_write_be16 (font, head->Units_Per_EM); - - cairo_pdf_ft_font_write_be32 (font, head->Created[0]); - cairo_pdf_ft_font_write_be32 (font, head->Created[1]); - cairo_pdf_ft_font_write_be32 (font, head->Modified[0]); - cairo_pdf_ft_font_write_be32 (font, head->Modified[1]); - - cairo_pdf_ft_font_write_be16 (font, head->xMin); - cairo_pdf_ft_font_write_be16 (font, head->yMin); - cairo_pdf_ft_font_write_be16 (font, head->xMax); - cairo_pdf_ft_font_write_be16 (font, head->yMax); - - cairo_pdf_ft_font_write_be16 (font, head->Mac_Style); - cairo_pdf_ft_font_write_be16 (font, head->Lowest_Rec_PPEM); - - cairo_pdf_ft_font_write_be16 (font, head->Font_Direction); - cairo_pdf_ft_font_write_be16 (font, head->Index_To_Loc_Format); - cairo_pdf_ft_font_write_be16 (font, head->Glyph_Data_Format); + unsigned char *buffer; + unsigned long size; + size = 0; + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + tag, 0, NULL, &size); + font->checksum_index = _cairo_array_num_elements (&font->output) + 8; + font->status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer); + font->backend->load_truetype_table( font->scaled_font_subset->scaled_font, + tag, 0, buffer, &size); return font->status; } static int cairo_pdf_ft_font_write_hhea_table (cairo_pdf_ft_font_t *font, unsigned long tag) { - TT_HoriHeader *hhea; - - hhea = FT_Get_Sfnt_Table (font->face, ft_sfnt_hhea); - - cairo_pdf_ft_font_write_be32 (font, hhea->Version); - cairo_pdf_ft_font_write_be16 (font, hhea->Ascender); - cairo_pdf_ft_font_write_be16 (font, hhea->Descender); - cairo_pdf_ft_font_write_be16 (font, hhea->Line_Gap); - - cairo_pdf_ft_font_write_be16 (font, hhea->advance_Width_Max); - - cairo_pdf_ft_font_write_be16 (font, hhea->min_Left_Side_Bearing); - cairo_pdf_ft_font_write_be16 (font, hhea->min_Right_Side_Bearing); - cairo_pdf_ft_font_write_be16 (font, hhea->xMax_Extent); - cairo_pdf_ft_font_write_be16 (font, hhea->caret_Slope_Rise); - cairo_pdf_ft_font_write_be16 (font, hhea->caret_Slope_Run); - cairo_pdf_ft_font_write_be16 (font, hhea->caret_Offset); - - cairo_pdf_ft_font_write_be16 (font, 0); - cairo_pdf_ft_font_write_be16 (font, 0); - cairo_pdf_ft_font_write_be16 (font, 0); - cairo_pdf_ft_font_write_be16 (font, 0); - - cairo_pdf_ft_font_write_be16 (font, hhea->metric_Data_Format); - cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs); + tt_hhea_t *hhea; + unsigned long size; + size = sizeof (tt_hhea_t); + font->status = cairo_pdf_ft_font_allocate_write_buffer (font, size, (unsigned char **) &hhea); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + tag, 0, (unsigned char *) hhea, &size); + hhea->num_hmetrics = cpu_to_be16 (font->base.num_glyphs); return font->status; } @@ -520,19 +600,44 @@ cairo_pdf_ft_font_write_hmtx_table (cair unsigned long tag) { cairo_status_t status; - unsigned long entry_size; + unsigned long size; + unsigned long long_entry_size; + unsigned long short_entry_size; short *p; int i; + tt_hhea_t hhea; + int num_hmetrics; + + size = sizeof(tt_hhea_t); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_hhea, 0, (unsigned char*) &hhea, &size); + num_hmetrics = be16_to_cpu(hhea.num_hmetrics); for (i = 0; i < font->base.num_glyphs; i++) { - entry_size = 2 * sizeof (short); - status = cairo_pdf_ft_font_allocate_write_buffer (font, entry_size, + long_entry_size = 2 * sizeof (short); + short_entry_size = sizeof (short); + status = cairo_pdf_ft_font_allocate_write_buffer (font, long_entry_size, (unsigned char **) &p); - /* XXX: Need to check status here. */ - FT_Load_Sfnt_Table (font->face, TTAG_hmtx, - font->glyphs[i].parent_index * entry_size, - (FT_Byte *) p, &entry_size); - font->base.widths[i] = be16_to_cpu (p[0]); + if (font->glyphs[i].parent_index < num_hmetrics) { + 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); + } + else + { + 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); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_hmtx, + (num_hmetrics - 1) * long_entry_size + + (font->glyphs[i].parent_index - num_hmetrics) + * short_entry_size, + (unsigned char *) (p+1), &short_entry_size); + } + font->base.widths[i] = be16_to_cpu (p[0]); } return font->status; @@ -543,11 +648,14 @@ cairo_pdf_ft_font_write_loca_table (cair unsigned long tag) { int i; - TT_Header *header; + tt_head_t header; + unsigned long size; - header = FT_Get_Sfnt_Table (font->face, ft_sfnt_head); + size = sizeof(tt_head_t); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + TT_TAG_head, 0, (unsigned char*) &header, &size); - if (header->Index_To_Loc_Format == 0) { + if (be16_to_cpu (header.index_to_loc_format) == 0) { for (i = 0; i < font->base.num_glyphs + 1; i++) cairo_pdf_ft_font_write_be16 (font, font->glyphs[i].location / 2); } @@ -563,26 +671,14 @@ static int cairo_pdf_ft_font_write_maxp_table (cairo_pdf_ft_font_t *font, unsigned long tag) { - TT_MaxProfile *maxp; - - maxp = FT_Get_Sfnt_Table (font->face, ft_sfnt_maxp); - - cairo_pdf_ft_font_write_be32 (font, maxp->version); - cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs); - cairo_pdf_ft_font_write_be16 (font, maxp->maxPoints); - cairo_pdf_ft_font_write_be16 (font, maxp->maxContours); - cairo_pdf_ft_font_write_be16 (font, maxp->maxCompositePoints); - cairo_pdf_ft_font_write_be16 (font, maxp->maxCompositeContours); - cairo_pdf_ft_font_write_be16 (font, maxp->maxZones); - cairo_pdf_ft_font_write_be16 (font, maxp->maxTwilightPoints); - cairo_pdf_ft_font_write_be16 (font, maxp->maxStorage); - cairo_pdf_ft_font_write_be16 (font, maxp->maxFunctionDefs); - cairo_pdf_ft_font_write_be16 (font, maxp->maxInstructionDefs); - cairo_pdf_ft_font_write_be16 (font, maxp->maxStackElements); - cairo_pdf_ft_font_write_be16 (font, maxp->maxSizeOfInstructions); - cairo_pdf_ft_font_write_be16 (font, maxp->maxComponentElements); - cairo_pdf_ft_font_write_be16 (font, maxp->maxComponentDepth); + tt_maxp_t *maxp; + unsigned long size; + size = sizeof(tt_maxp_t); + font->status = cairo_pdf_ft_font_allocate_write_buffer (font, size, (unsigned char **) &maxp); + font->backend->load_truetype_table (font->scaled_font_subset->scaled_font, + tag, 0, (unsigned char *) maxp, &size); + maxp->num_glyphs = cpu_to_be16(font->base.num_glyphs); return font->status; } @@ -597,17 +693,17 @@ static const table_t truetype_tables[] = * Remapping composite glyphs will reference the sub glyphs the * composite glyph is made up of. That needs to be done first so * we have all the glyphs in the subset before going further. */ - { TTAG_glyf, cairo_pdf_ft_font_write_glyf_table }, - { TTAG_cmap, cairo_pdf_ft_font_write_cmap_table }, - { TTAG_cvt, cairo_pdf_ft_font_write_generic_table }, - { TTAG_fpgm, cairo_pdf_ft_font_write_generic_table }, - { TTAG_head, cairo_pdf_ft_font_write_head_table }, - { TTAG_hhea, cairo_pdf_ft_font_write_hhea_table }, - { TTAG_hmtx, cairo_pdf_ft_font_write_hmtx_table }, - { TTAG_loca, cairo_pdf_ft_font_write_loca_table }, - { TTAG_maxp, cairo_pdf_ft_font_write_maxp_table }, - { TTAG_name, cairo_pdf_ft_font_write_generic_table }, - { TTAG_prep, cairo_pdf_ft_font_write_generic_table }, + { TT_TAG_glyf, cairo_pdf_ft_font_write_glyf_table }, + { TT_TAG_cmap, cairo_pdf_ft_font_write_cmap_table }, + { TT_TAG_cvt, cairo_pdf_ft_font_write_generic_table }, + { TT_TAG_fpgm, cairo_pdf_ft_font_write_generic_table }, + { TT_TAG_head, cairo_pdf_ft_font_write_head_table }, + { TT_TAG_hhea, cairo_pdf_ft_font_write_hhea_table }, + { TT_TAG_hmtx, cairo_pdf_ft_font_write_hmtx_table }, + { TT_TAG_loca, cairo_pdf_ft_font_write_loca_table }, + { TT_TAG_maxp, cairo_pdf_ft_font_write_maxp_table }, + { TT_TAG_name, cairo_pdf_ft_font_write_generic_table }, + { TT_TAG_prep, cairo_pdf_ft_font_write_generic_table }, }; static cairo_status_t @@ -635,9 +731,9 @@ cairo_pdf_ft_font_write_offset_table (ca cairo_pdf_ft_font_write_be16 (font, entry_selector); cairo_pdf_ft_font_write_be16 (font, range_shift); - /* XXX: Why are we allocating a table here and then ignoring the - * returned buffer? This should result in garbage in the output - * file, correct? Is this just unfinished code? -cworth. */ + /* Allocate space for the table directory. Each directory entry + * will be filled in by cairo_pdf_ft_font_update_entry() after + * the table is written. */ table_buffer_length = ARRAY_LENGTH (truetype_tables) * 16; status = cairo_pdf_ft_font_allocate_write_buffer (font, table_buffer_length, &table_buffer); @@ -680,22 +776,12 @@ cairo_pdf_ft_font_update_entry (cairo_pd } static cairo_status_t -cairo_pdf_ft_font_generate (void *abstract_font, +cairo_pdf_ft_font_generate (cairo_pdf_ft_font_t *font, const char **data, unsigned long *length) { - cairo_ft_unscaled_font_t *ft_unscaled_font; - cairo_pdf_ft_font_t *font = abstract_font; unsigned long start, end, next, checksum, *checksum_location; int i; - /* XXX: It would be cleaner to do something besides this cast - * here. Perhaps cairo_pdf_ft_font_t should just have the - * cairo_ft_unscaled_font_t rather than having the generic - * cairo_unscaled_font_t in the base class? */ - ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font; - - font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font); - if (cairo_pdf_ft_font_write_offset_table (font)) goto fail; @@ -723,9 +809,6 @@ cairo_pdf_ft_font_generate (void *abstra *length = _cairo_array_num_elements (&font->output); fail: - _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); - font->face = NULL; - return font->status; } @@ -809,4 +892,3 @@ _cairo_truetype_subset_fini (cairo_truet free (subset->widths); free (subset->data); } - diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 18aa68c..4e3eede --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -1990,6 +1990,30 @@ _cairo_ft_show_glyphs (void *abs return CAIRO_INT_STATUS_UNSUPPORTED; } +static cairo_int_status_t +_cairo_ft_load_truetype_table (void *abstract_font, + unsigned long tag, + long offset, + unsigned char *buffer, + unsigned long *length) +{ + cairo_ft_scaled_font_t *scaled_font = abstract_font; + cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; + FT_Face face; + cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; + + face = _cairo_ft_unscaled_font_lock_face (unscaled); + if (!face) + return CAIRO_STATUS_NO_MEMORY; + + if (FT_IS_SFNT (face) && + FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0) + status = CAIRO_STATUS_SUCCESS; + + _cairo_ft_unscaled_font_unlock_face (unscaled); + return status; +} + const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { CAIRO_FONT_TYPE_FT, _cairo_ft_scaled_font_create_toy, @@ -1998,6 +2022,7 @@ const cairo_scaled_font_backend_t cairo_ NULL, /* text_to_glyphs */ _cairo_ft_ucs4_to_index, _cairo_ft_show_glyphs, + _cairo_ft_load_truetype_table, }; /* cairo_ft_font_face_t */ diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index aaf71c7..0f19ed1 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -40,7 +40,7 @@ #include "cairoint.h" #include "cairo-pdf.h" #include "cairo-pdf-test.h" #include "cairo-scaled-font-subsets-private.h" -#include "cairo-ft-private.h" #include "cairo-paginated-surface-private.h" #include "cairo-path-fixed-private.h" #include "cairo-output-stream-private.h" @@ -1586,6 +1586,7 @@ _cairo_pdf_surface_write_pages (cairo_pd "endobj\r\n"); } +#if CAIRO_HAS_FT_FONT static cairo_status_t _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface, cairo_scaled_font_subset_t *font_subset) @@ -1694,6 +1695,7 @@ _cairo_pdf_surface_emit_type1_font_subse return CAIRO_STATUS_SUCCESS; } +#endif static cairo_status_t _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, @@ -2026,10 +2028,12 @@ _cairo_pdf_surface_emit_font_subset (cai cairo_pdf_surface_t *surface = closure; cairo_status_t status; +#if CAIRO_HAS_FT_FONT status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; - +#endif + status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c old mode 100644 new mode 100755 index 3856aa2..6a14a6a --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -43,9 +43,10 @@ #include "cairo-ps-test.h" #include "cairo-scaled-font-subsets-private.h" #include "cairo-paginated-surface-private.h" #include "cairo-meta-surface-private.h" -#include "cairo-ft-private.h" #include "cairo-output-stream-private.h" +#include #include #include @@ -385,6 +386,7 @@ _cairo_ps_surface_emit_header (cairo_ps_ } } +#if CAIRO_HAS_FT_FONT static cairo_status_t _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface, cairo_scaled_font_subset_t *font_subset) @@ -414,6 +416,7 @@ _cairo_ps_surface_emit_type1_font_subset return CAIRO_STATUS_SUCCESS; } +#endif static cairo_status_t _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface, @@ -663,10 +666,12 @@ _cairo_ps_surface_emit_font_subset (cair cairo_ps_surface_t *surface = closure; cairo_status_t status; +#if CAIRO_HAS_FT_FONT status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; - +#endif + status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return; diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index b391506..e58d310 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -42,7 +42,7 @@ #include "cairoint.h" #include "cairo-svg.h" #include "cairo-svg-test.h" #include "cairo-path-fixed-private.h" -#include "cairo-ft-private.h" #include "cairo-meta-surface-private.h" #include "cairo-paginated-surface-private.h" #include "cairo-scaled-font-subsets-private.h" diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index 39c9522..5ca5653 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1220,6 +1220,33 @@ _cairo_win32_scaled_font_show_glyphs (vo } } +static cairo_int_status_t +_cairo_win32_scaled_font_load_truetype_table (void *abstract_font, + unsigned long tag, + long offset, + unsigned char *buffer, + unsigned long *length) +{ + HDC hdc; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + cairo_win32_scaled_font_t *scaled_font = abstract_font; + hdc = _get_global_font_dc (); + if (!hdc) + return CAIRO_STATUS_NO_MEMORY; + + tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24; + status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); + + *length = GetFontData (hdc, tag, offset, buffer, *length); + if (*length == GDI_ERROR) { + status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_load_truetype_table:GetFontData"); + } + _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); + + return status; +} + static cairo_fixed_t _cairo_fixed_from_FIXED (FIXED f) { @@ -1363,6 +1390,7 @@ const cairo_scaled_font_backend_t cairo_ _cairo_win32_scaled_font_text_to_glyphs, NULL, /* ucs4_to_index */ _cairo_win32_scaled_font_show_glyphs, + _cairo_win32_scaled_font_load_truetype_table, }; /* cairo_win32_font_face_t */ diff --git a/src/cairoint.h b/src/cairoint.h index 4eb0c3c..c491c90 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -574,6 +574,12 @@ struct _cairo_scaled_font_backend { const cairo_glyph_t *glyphs, int num_glyphs); + cairo_int_status_t + (*load_truetype_table)(void *scaled_font, + unsigned long tag, + long offset, + unsigned char *buffer, + unsigned long *length); }; struct _cairo_font_face_backend {