📄 cairo-font-subset.c
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2004 Red Hat, Inc * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL") or, at your option, under the terms of the Mozilla * Public License Version 1.1 (the "MPL"). If you do not alter this * notice, a recipient may use your version of this file under either * the MPL or the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * You should have received a copy of the MPL along with this library * in the file COPYING-MPL-1.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL or the MPL for * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * The Initial Developer of the Original Code is Red Hat, Inc. * * Contributor(s): * Kristian Høgsberg <krh@redhat.com> */#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 <ft2build.h>#include FT_FREETYPE_H#include FT_OUTLINE_H#include FT_TRUETYPE_TAGS_H#include FT_TRUETYPE_TABLES_Htypedef struct ft_subset_glyph ft_subset_glyph_t;struct ft_subset_glyph { int parent_index; unsigned long location;};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; int *widths; long x_min, y_min, x_max, y_max; long ascent, descent; } base; ft_subset_glyph_t *glyphs; FT_Face face; int checksum_index; cairo_array_t output; int *parent_to_subset; cairo_status_t status;} cairo_pdf_ft_font_t;static intcairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph);#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )#define SFNT_VERSION 0x00010000#ifdef WORDS_BIGENDIAN#define cpu_to_be16(v) (v)#define be16_to_cpu(v) (v)#define cpu_to_be32(v) (v)#define be32_to_cpu(v) (v)#elsestatic inline unsigned shortcpu_to_be16(unsigned short v){ return (v << 8) | (v >> 8);}static inline unsigned shortbe16_to_cpu(unsigned short v){ return cpu_to_be16 (v);}static inline unsigned longcpu_to_be32(unsigned long v){ return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);}static inline unsigned longbe32_to_cpu(unsigned long v){ return cpu_to_be32 (v);}#endifstatic 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; 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)) 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); ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font; face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font); if (face == NULL) /* Assume out of memory */ return CAIRO_STATUS_NO_MEMORY; /* 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) return CAIRO_INT_STATUS_UNSUPPORTED; font = malloc (sizeof (cairo_pdf_ft_font_t)); if (font == NULL) return CAIRO_STATUS_NO_MEMORY; 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)); if (font->glyphs == NULL) goto fail2; font->parent_to_subset = calloc (face->num_glyphs, 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); if (font->base.base_font == NULL) goto fail4; for (i = 0, j = 0; font->base.base_font[j]; j++) { if (font->base.base_font[j] == ' ') continue; font->base.base_font[i++] = font->base.base_font[j]; } font->base.base_font[i] = '\0'; font->base.widths = calloc (face->num_glyphs, sizeof (int)); if (font->base.widths == NULL) goto fail5; _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font); font->status = CAIRO_STATUS_SUCCESS; *font_return = font; return CAIRO_STATUS_SUCCESS; fail5: free (font->base.base_font); fail4: free (font->parent_to_subset); fail3: free (font->glyphs); fail2: _cairo_array_fini (&font->output); fail1: free (font); return status;}static voidcairo_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); _cairo_array_fini (&font->output); free (font);}static cairo_status_tcairo_pdf_ft_font_allocate_write_buffer (cairo_pdf_ft_font_t *font, size_t length, unsigned char **buffer){ cairo_status_t status; status = _cairo_array_allocate (&font->output, length, (void **) buffer); if (status) return status; return CAIRO_STATUS_SUCCESS;}static cairo_status_tcairo_pdf_ft_font_write (cairo_pdf_ft_font_t *font, const void *data, size_t length){ cairo_status_t status; status = _cairo_array_append_multiple (&font->output, data, length); if (status) return status; return CAIRO_STATUS_SUCCESS;}static voidcairo_pdf_ft_font_write_be16 (cairo_pdf_ft_font_t *font, unsigned short value){ unsigned short be16_value; be16_value = cpu_to_be16 (value); cairo_pdf_ft_font_write (font, &be16_value, sizeof be16_value);}static voidcairo_pdf_ft_font_write_be32 (cairo_pdf_ft_font_t *font, unsigned long value){ unsigned long be32_value; be32_value = cpu_to_be32 (value); cairo_pdf_ft_font_write (font, &be32_value, sizeof be32_value);}static unsigned longcairo_pdf_ft_font_align_output (cairo_pdf_ft_font_t *font){ int length, aligned, pad; unsigned char *ignored; length = _cairo_array_num_elements (&font->output); aligned = (length + 3) & ~3; pad = aligned - length; if (pad) cairo_pdf_ft_font_allocate_write_buffer (font, pad, &ignored); return aligned;}static intcairo_pdf_ft_font_write_cmap_table (cairo_pdf_ft_font_t *font, unsigned long tag){ int i; cairo_pdf_ft_font_write_be16 (font, 0); cairo_pdf_ft_font_write_be16 (font, 1); cairo_pdf_ft_font_write_be16 (font, 1); cairo_pdf_ft_font_write_be16 (font, 0); cairo_pdf_ft_font_write_be32 (font, 12); /* Output a format 6 encoding table. */ cairo_pdf_ft_font_write_be16 (font, 6); cairo_pdf_ft_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1)); cairo_pdf_ft_font_write_be16 (font, 0); cairo_pdf_ft_font_write_be16 (font, 1); /* First glyph */ cairo_pdf_ft_font_write_be16 (font, font->base.num_glyphs - 1); for (i = 1; i < font->base.num_glyphs; i++) cairo_pdf_ft_font_write_be16 (font, i); return font->status;}static intcairo_pdf_ft_font_write_generic_table (cairo_pdf_ft_font_t *font, unsigned long tag){ cairo_status_t status; unsigned char *buffer; unsigned long size; size = 0; FT_Load_Sfnt_Table (font->face, 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); return 0;}typedef struct composite_glyph composite_glyph_t;struct composite_glyph { unsigned short flags; unsigned short index; unsigned short args[7]; /* 1 to 7 arguments depending on value of flags */};typedef struct glyph_data glyph_data_t;struct glyph_data { short num_contours; char data[8]; composite_glyph_t glyph;};/* composite_glyph_t flags */#define ARG_1_AND_2_ARE_WORDS 0x0001#define WE_HAVE_A_SCALE 0x0008#define MORE_COMPONENTS 0x0020#define WE_HAVE_AN_X_AND_Y_SCALE 0x0040#define WE_HAVE_A_TWO_BY_TWO 0x0080static voidcairo_pdf_ft_font_remap_composite_glyph (cairo_pdf_ft_font_t *font, unsigned char *buffer){ glyph_data_t *glyph_data; composite_glyph_t *composite_glyph; int num_args; int has_more_components; unsigned short flags; unsigned short index; glyph_data = (glyph_data_t *) buffer; if ((short)be16_to_cpu (glyph_data->num_contours) >= 0) return; composite_glyph = &glyph_data->glyph; do { flags = be16_to_cpu (composite_glyph->flags); has_more_components = flags & MORE_COMPONENTS; index = cairo_pdf_ft_font_use_glyph (font, be16_to_cpu (composite_glyph->index)); composite_glyph->index = cpu_to_be16 (index); num_args = 1; if (flags & ARG_1_AND_2_ARE_WORDS) num_args += 1; if (flags & WE_HAVE_A_SCALE) num_args += 1; else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) num_args += 2; else if (flags & WE_HAVE_A_TWO_BY_TWO) num_args += 3; composite_glyph = (composite_glyph_t *) &(composite_glyph->args[num_args]); } while (has_more_components);}static intcairo_pdf_ft_font_write_glyf_table (cairo_pdf_ft_font_t *font, unsigned long tag){ cairo_status_t status; unsigned long start_offset, index, size; TT_Header *header; unsigned long begin, end; unsigned char *buffer; int i; union { unsigned char *bytes; unsigned short *short_offsets; 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); else size = sizeof (long) * (font->face->num_glyphs + 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -