📄 cairo-font-subset.c
字号:
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); 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) { 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]); } size = end - begin; font->glyphs[i].location = cairo_pdf_ft_font_align_output (font) - start_offset; status = cairo_pdf_ft_font_allocate_write_buffer (font, size, &buffer); if (status) break; if (size != 0) { FT_Load_Sfnt_Table (font->face, TTAG_glyf, begin, buffer, &size); cairo_pdf_ft_font_remap_composite_glyph (font, buffer); } } font->glyphs[i].location = cairo_pdf_ft_font_align_output (font) - start_offset; free (u.bytes); return font->status;}static intcairo_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); 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); return font->status;}static intcairo_pdf_ft_font_write_hmtx_table (cairo_pdf_ft_font_t *font, unsigned long tag){ cairo_status_t status; unsigned long entry_size; short *p; int i; 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, (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]); } return font->status;}static intcairo_pdf_ft_font_write_loca_table (cairo_pdf_ft_font_t *font, unsigned long tag){ int i; TT_Header *header; header = FT_Get_Sfnt_Table (font->face, ft_sfnt_head); if (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); } else { for (i = 0; i < font->base.num_glyphs + 1; i++) cairo_pdf_ft_font_write_be32 (font, font->glyphs[i].location); } return font->status;}static intcairo_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); return font->status;}typedef struct table table_t;struct table { unsigned long tag; int (*write) (cairo_pdf_ft_font_t *font, unsigned long tag);};static const table_t truetype_tables[] = { /* As we write out the glyf table we remap composite glyphs. * 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 },};static cairo_status_tcairo_pdf_ft_font_write_offset_table (cairo_pdf_ft_font_t *font){ cairo_status_t status; unsigned char *table_buffer; size_t table_buffer_length; unsigned short search_range, entry_selector, range_shift; int num_tables; num_tables = ARRAY_LENGTH (truetype_tables); search_range = 1; entry_selector = 0; while (search_range * 2 <= num_tables) { search_range *= 2; entry_selector++; } search_range *= 16; range_shift = num_tables * 16 - search_range; cairo_pdf_ft_font_write_be32 (font, SFNT_VERSION); cairo_pdf_ft_font_write_be16 (font, num_tables); cairo_pdf_ft_font_write_be16 (font, search_range); 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. */ table_buffer_length = ARRAY_LENGTH (truetype_tables) * 16; status = cairo_pdf_ft_font_allocate_write_buffer (font, table_buffer_length, &table_buffer); if (status) return status; return font->status;}static unsigned longcairo_pdf_ft_font_calculate_checksum (cairo_pdf_ft_font_t *font, unsigned long start, unsigned long end){ unsigned long *padded_end; unsigned long *p; unsigned long checksum; char *data; checksum = 0; data = _cairo_array_index (&font->output, 0); p = (unsigned long *) (data + start); padded_end = (unsigned long *) (data + ((end + 3) & ~3)); while (p < padded_end) checksum += *p++; return checksum;}static voidcairo_pdf_ft_font_update_entry (cairo_pdf_ft_font_t *font, int index, unsigned long tag, unsigned long start, unsigned long end){ unsigned long *entry; entry = _cairo_array_index (&font->output, 12 + 16 * index); entry[0] = cpu_to_be32 (tag); entry[1] = cpu_to_be32 (cairo_pdf_ft_font_calculate_checksum (font, start, end)); entry[2] = cpu_to_be32 (start); entry[3] = cpu_to_be32 (end - start);}static cairo_status_tcairo_pdf_ft_font_generate (void *abstract_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; start = cairo_pdf_ft_font_align_output (font); end = start; end = 0; for (i = 0; i < ARRAY_LENGTH (truetype_tables); i++) { if (truetype_tables[i].write (font, truetype_tables[i].tag)) goto fail; end = _cairo_array_num_elements (&font->output); next = cairo_pdf_ft_font_align_output (font); cairo_pdf_ft_font_update_entry (font, i, truetype_tables[i].tag, start, end); start = next; } checksum = 0xb1b0afba - cairo_pdf_ft_font_calculate_checksum (font, 0, end); checksum_location = _cairo_array_index (&font->output, font->checksum_index); *checksum_location = cpu_to_be32 (checksum); *data = _cairo_array_index (&font->output, 0); *length = _cairo_array_num_elements (&font->output); fail: _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); font->face = NULL; return font->status;}static intcairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph){ if (font->parent_to_subset[glyph] == 0) { font->parent_to_subset[glyph] = font->base.num_glyphs; font->glyphs[font->base.num_glyphs].parent_index = glyph; font->base.num_glyphs++; } return font->parent_to_subset[glyph];}cairo_status_t_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset, cairo_scaled_font_subset_t *font_subset){ cairo_pdf_ft_font_t *font; cairo_status_t status; const char *data = NULL; /* squelch bogus compiler warning */ unsigned long parent_glyph, length = 0; /* squelch bogus compiler warning */ int i; status = _cairo_pdf_ft_font_create (font_subset, &font); if (status) return status; for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) { parent_glyph = font->scaled_font_subset->glyphs[i]; cairo_pdf_ft_font_use_glyph (font, parent_glyph); } status = cairo_pdf_ft_font_generate (font, &data, &length); if (status) goto fail1; truetype_subset->base_font = strdup (font->base.base_font); if (truetype_subset->base_font == NULL) goto fail1; truetype_subset->widths = calloc (sizeof (int), font->base.num_glyphs); if (truetype_subset->widths == NULL) goto fail2; for (i = 0; i < font->base.num_glyphs; i++) truetype_subset->widths[i] = font->base.widths[i]; truetype_subset->x_min = font->base.x_min; truetype_subset->y_min = font->base.y_min; truetype_subset->x_max = font->base.x_max; truetype_subset->y_max = font->base.y_max; truetype_subset->ascent = font->base.ascent; truetype_subset->descent = font->base.descent; truetype_subset->data = malloc (length); if (truetype_subset->data == NULL) goto fail3; memcpy (truetype_subset->data, data, length); truetype_subset->data_length = length; cairo_pdf_ft_font_destroy (font); return CAIRO_STATUS_SUCCESS; fail3: free (truetype_subset->widths); fail2: free (truetype_subset->base_font); fail1: cairo_pdf_ft_font_destroy (font); return status;}void_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset){ free (subset->base_font); free (subset->widths); free (subset->data);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -