⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-type1-subset.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 2 页
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2006 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"#include "cairo-output-stream-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_TYPE1_TABLES_Htypedef struct _cairo_type1_font_subset {    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;	long x_min, y_min, x_max, y_max;	long ascent, descent;	const char    *data;	unsigned long  header_size;	unsigned long  data_size;	unsigned long  trailer_size;    } base;    FT_Face face;    int num_glyphs;    struct {	int subset_index;	int width;	char *name;    } *glyphs;    cairo_output_stream_t *output;    cairo_array_t contents;    const char *rd, *nd;    char *type1_data;    unsigned int type1_length;    char *type1_end;    char *header_segment;    int header_segment_size;    char *eexec_segment;    int eexec_segment_size;    cairo_bool_t eexec_segment_is_ascii;    char *cleartext;    char *cleartext_end;    int header_size;    unsigned short eexec_key;    cairo_bool_t hex_encode;    int hex_column;    cairo_status_t status;} cairo_type1_font_subset_t;static cairo_status_t_cairo_type1_font_subset_create (cairo_unscaled_font_t      *unscaled_font,				 cairo_type1_font_subset_t **subset_return){    cairo_ft_unscaled_font_t *ft_unscaled_font;    FT_Face face;    PS_FontInfoRec font_info;    cairo_type1_font_subset_t *font;    int i, j;    ft_unscaled_font = (cairo_ft_unscaled_font_t *) unscaled_font;    face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);    if (FT_Get_PS_Font_Info(face, &font_info) != 0)	return CAIRO_INT_STATUS_UNSUPPORTED;    font = calloc (sizeof (cairo_type1_font_subset_t), 1);    if (font == NULL)	return CAIRO_STATUS_NO_MEMORY;    font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);    font->base.num_glyphs = face->num_glyphs;    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 fail1;    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->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]);    if (font->glyphs == NULL)	goto fail2;    font->num_glyphs = 0;    for (i = 0; i < face->num_glyphs; i++)	font->glyphs[i].subset_index = -1;    _cairo_array_init (&font->contents, sizeof (char));    _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);    *subset_return = font;    return CAIRO_STATUS_SUCCESS; fail2:    free (font->base.base_font); fail1:    free (font);    return CAIRO_STATUS_NO_MEMORY;}static intcairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph){    if (font->glyphs[glyph].subset_index >= 0)	return font->glyphs[glyph].subset_index;    font->glyphs[glyph].subset_index = font->num_glyphs;    font->num_glyphs++;    return font->glyphs[glyph].subset_index;}/* Magic constants for the type1 eexec encryption */static const unsigned short c1 = 52845, c2 = 22719;static const unsigned short private_dict_key = 55665;static const unsigned short charstring_key = 4330;static cairo_bool_tis_ps_delimiter(int c){    const static char delimiters[] = "()[]{}<>/% \t\r\n";    return strchr (delimiters, c) != NULL;}static const char *find_token (const char *buffer, const char *end, const char *token){    int i, length;    /* FIXME: find substring really must be find_token */    length = strlen (token);    for (i = 0; buffer + i < end - length + 1; i++)	if (memcmp (buffer + i, token, length) == 0)	    if ((i == 0 || token[0] == '/' || is_ps_delimiter(buffer[i - 1])) &&		(buffer + i == end - length || is_ps_delimiter(buffer[i + length])))		return buffer + i;    return NULL;}static cairo_status_tcairo_type1_font_subset_find_segments (cairo_type1_font_subset_t *font){    unsigned char *p;    const char *eexec_token;    int size;    p = (unsigned char *) font->type1_data;    font->type1_end = font->type1_data + font->type1_length;    if (p[0] == 0x80 && p[1] == 0x01) {	font->header_segment_size =	    p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);	font->header_segment = (char *) p + 6;	p += 6 + font->header_segment_size;	font->eexec_segment_size =	    p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);	font->eexec_segment = (char *) p + 6;	font->eexec_segment_is_ascii = (p[1] == 1);        p += 6 + font->eexec_segment_size;        while (p < (unsigned char *) (font->type1_end) && p[1] != 0x03) {            size = p[2] | (p[3] << 8) | (p[4] << 16) | (p[5] << 24);            p += 6 + size;        }        font->type1_end = (char *) p;    } else {	eexec_token = find_token ((char *) p, font->type1_end, "eexec");	if (eexec_token == NULL)	    return font->status = CAIRO_INT_STATUS_UNSUPPORTED;	font->header_segment_size = eexec_token - (char *) p + strlen ("eexec\n");	font->header_segment = (char *) p;	font->eexec_segment_size = font->type1_length - font->header_segment_size;	font->eexec_segment = (char *) p + font->header_segment_size;	font->eexec_segment_is_ascii = TRUE;    }    return CAIRO_STATUS_SUCCESS;}static cairo_status_tcairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,					 const char *name){    const char *start, *end, *segment_end;    int i;    segment_end = font->header_segment + font->header_segment_size;    start = find_token (font->header_segment, segment_end, "/FontName");    if (start == NULL)	return font->status = CAIRO_INT_STATUS_UNSUPPORTED;    _cairo_output_stream_write (font->output, font->header_segment,				start - font->header_segment);    _cairo_output_stream_printf (font->output, "/FontName /%s def", name);    end = find_token (start, segment_end, "def");    if (end == NULL)	return font->status = CAIRO_INT_STATUS_UNSUPPORTED;    end += 3;    start = find_token (end, segment_end, "/Encoding");    if (start == NULL)	return font->status = CAIRO_INT_STATUS_UNSUPPORTED;    _cairo_output_stream_write (font->output, end, start - end);    _cairo_output_stream_printf (font->output,				 "/Encoding 256 array\n"				 "0 1 255 {1 index exch /.notdef put} for\n");    for (i = 0; i < font->base.num_glyphs; i++) {	if (font->glyphs[i].subset_index < 0)	    continue;	_cairo_output_stream_printf (font->output,				     "dup %d /%s put\n",				     font->glyphs[i].subset_index,				     font->glyphs[i].name);    }    _cairo_output_stream_printf (font->output, "readonly def");    end = find_token (start, segment_end, "def");    if (end == NULL)	return font->status = CAIRO_INT_STATUS_UNSUPPORTED;    end += 3;    _cairo_output_stream_write (font->output, end, segment_end - end);    return font->status;}static inthex_to_int (int ch){    if (ch <= '9')	return ch - '0';    else if (ch <= 'F')	return ch - 'A' + 10;    else	return ch - 'a' + 10;}static voidcairo_type1_font_subset_write_encrypted (cairo_type1_font_subset_t *font,					 const char *data, unsigned int length){    const unsigned char *in, *end;    int c, p;    static const char hex_digits[16] = "0123456789abcdef";    char digits[3];    in = (const unsigned char *) data;    end = (const unsigned char *) data + length;    while (in < end) {	p = *in++;	c = p ^ (font->eexec_key >> 8);	font->eexec_key = (c + font->eexec_key) * c1 + c2;	if (font->hex_encode) {	    digits[0] = hex_digits[c >> 4];	    digits[1] = hex_digits[c & 0x0f];	    digits[2] = '\n';	    font->hex_column += 2;	    if (font->hex_column == 78) {		_cairo_output_stream_write (font->output, digits, 3);		font->hex_column = 0;	    } else {		_cairo_output_stream_write (font->output, digits, 2);	    }	} else {	    digits[0] = c;	    _cairo_output_stream_write (font->output, digits, 1);	}    }}static cairo_status_tcairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font){    unsigned short r = private_dict_key;    unsigned char *in, *end;    char *out;    int c, p;    in = (unsigned char *) font->eexec_segment;    end = (unsigned char *) in + font->eexec_segment_size;    font->cleartext = malloc (font->eexec_segment_size);    if (font->cleartext == NULL)	return font->status = CAIRO_STATUS_NO_MEMORY;    out = font->cleartext;    while (in < end) {	if (font->eexec_segment_is_ascii) {	    c = *in++;	    if (isspace (c))		continue;	    c = (hex_to_int (c) << 4) | hex_to_int (*in++);	} else {	    c = *in++;	}	p = c ^ (r >> 8);	r = (c + r) * c1 + c2;	*out++ = p;    }    font->cleartext_end = out;    return font->status;}static const char *skip_token (const char *p, const char *end){    while (p < end && isspace(*p))	p++;    while (p < end && !isspace(*p))	p++;    if (p == end)	return NULL;    return p;}static intcairo_type1_font_subset_lookup_glyph (cairo_type1_font_subset_t *font,				      const char *glyph_name, int length){    int i;    for (i = 0; i < font->base.num_glyphs; i++) {	if (font->glyphs[i].name &&	    strncmp (font->glyphs[i].name, glyph_name, length) == 0 &&	    font->glyphs[i].name[length] == '\0')	    return i;    }    return -1;}static cairo_status_tcairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *font){    int i;    char buffer[256];    FT_Error error;    /* Get glyph names and width using the freetype API */    for (i = 0; i < font->base.num_glyphs; i++) {	if (font->glyphs[i].name != NULL)	    continue;	error = FT_Load_Glyph (font->face, i,			       FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING |			       FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);	if (error != 0) {	    printf ("could not load glyph %d\n", i);	    return font->status = CAIRO_STATUS_NO_MEMORY;	}	font->glyphs[i].width = font->face->glyph->metrics.horiAdvance;	error = FT_Get_Glyph_Name(font->face, i, buffer, sizeof buffer);	if (error != 0) {	    printf ("could not get glyph name for glyph %d\n", i);	    return font->status = CAIRO_STATUS_NO_MEMORY;	}	font->glyphs[i].name = strdup (buffer);	if (font->glyphs[i].name == NULL)	    return font->status = CAIRO_STATUS_NO_MEMORY;    }    return CAIRO_STATUS_SUCCESS;}static voidcairo_type1_font_subset_decrypt_charstring (const unsigned char *in, int size, unsigned char *out){    unsigned short r = charstring_key;    int c, p, i;    for (i = 0; i < size; i++) {        c = *in++;	p = c ^ (r >> 8);	r = (c + r) * c1 + c2;	*out++ = p;    }}static const unsigned char *cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer){    if (*p <= 246) {        *integer = *p++ - 139;    } else if (*p <= 250) {        *integer = (p[0] - 247) * 256 + p[1] + 108;        p += 2;    } else if (*p <= 254) {        *integer = -(p[0] - 251) * 256 - p[1] - 108;        p += 2;    } else {        *integer = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];        p += 5;    }    return p;}static const char *ps_standard_encoding[256] = {    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/*   0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/*  16 */    "space", "exclam", "quotedbl", "numbersign",	/*  32 */    "dollar", "percent", "ampersand", "quoteright",    "parenleft", "parenright", "asterisk", "plus",    "comma", "hyphen", "period", "slash",    "zero", "one", "two", "three",			/*  48 */    "four", "five", "six", "seven", "eight",    "nine", "colon", "semicolon", "less",    "equal", "greater", "question", "at",    "A", "B", "C", "D", "E", "F", "G", "H",		/*  64 */    "I", "J", "K", "L", "M", "N", "O", "P",    "Q", "R", "S", "T", "U", "V", "W", "X",		/*  80 */    "Y", "Z", "bracketleft", "backslash",    "bracketright", "asciicircum", "underscore", "quoteleft",    "a", "b", "c", "d", "e", "f", "g", "h",		/*  96 */    "i", "j", "k", "l", "m", "n", "o", "p",    "q", "r", "s", "t", "u", "v", "w", "x",		/* 112 */    "y", "z", "braceleft", "bar",    "braceright", "asciitilde", 0, 0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 128 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 144 */    "exclamdown", "cent", "sterling", "fraction",    "yen", "florin", "section", "currency",    "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",    "guilsinglright", "fi", "fl", NULL,    "endash", "dagger", "daggerdbl", "periodcentered",	/* 160 */    NULL, "paragraph", "bullet", "quotesinglbase",    "quotedblbase", "quotedblright", "guillemotright", "ellipsis",    "perthousand", NULL, "questiondown", NULL,    "grave", "acute", "circumflex", "tilde",		/* 176 */    "macron", "breve", "dotaccent", "dieresis",    NULL, "ring", "cedilla", NULL,    "hungarumlaut", "ogonek", "caron", "emdash",    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 192 */    "AE", 0, "ordfeminine", 0, 0, 0, 0, "Lslash",	/* 208 */    "Oslash", "OE", "ordmasculine", 0, 0, 0, 0, 0,    "ae", 0, 0, 0, "dotlessi", 0, 0, "lslash",		/* 224 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -