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

📄 cairo-type1-subset.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 2 页
字号:
    "oslash", "oe", "germandbls", 0, 0, 0, 0};static voiduse_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index){    const char *glyph_name;    if (index < 0 || index > 255)	return;    glyph_name = ps_standard_encoding[index];    if (glyph_name == NULL)	return;    index = cairo_type1_font_subset_lookup_glyph (font,						  glyph_name,						  strlen(glyph_name));    if (index < 0)	return;    cairo_type1_font_subset_use_glyph (font, index);}#define TYPE1_CHARSTRING_COMMAND_ESCAPE		(12)#define TYPE1_CHARSTRING_COMMAND_SEAC		(32 + 6)static voidcairo_type1_font_subset_look_for_seac(cairo_type1_font_subset_t *font,				      const char *name, int name_length,				      const char *encrypted_charstring, int encrypted_charstring_length){    unsigned char *charstring;    const unsigned char *end;    const unsigned char *p;    int stack[5], sp, value;    int command;    charstring = malloc (encrypted_charstring_length);    if (charstring == NULL)	return;    cairo_type1_font_subset_decrypt_charstring ((const unsigned char *)						encrypted_charstring,						encrypted_charstring_length,						charstring);    end = charstring + encrypted_charstring_length;    p = charstring + 4;    sp = 0;    while (p < end) {        if (*p < 32) {	    command = *p++;	    if (command == TYPE1_CHARSTRING_COMMAND_ESCAPE)		command = 32 + *p++;	    switch (command) {	    case TYPE1_CHARSTRING_COMMAND_SEAC:		/* The seac command takes five integer arguments.  The		 * last two are glyph indices into the PS standard		 * encoding give the names of the glyphs that this		 * glyph is composed from.  All we need to do is to		 * make sure those glyphs are present in the subset		 * under their standard names. */		use_standard_encoding_glyph (font, stack[3]);		use_standard_encoding_glyph (font, stack[4]);		sp = 0;		break;	    default:		sp = 0;		break;	    }        } else {            /* integer argument */	    p = cairo_type1_font_subset_decode_integer (p, &value);	    if (sp < 5)		stack[sp++] = value;        }    }    free (charstring);}static voidwrite_used_glyphs (cairo_type1_font_subset_t *font,		   const char *name, int name_length,		   const char *charstring, int charstring_length){    char buffer[256];    int length;    length = snprintf (buffer, sizeof buffer,		       "/%.*s %d %s ",		       name_length, name, charstring_length, font->rd);    cairo_type1_font_subset_write_encrypted (font, buffer, length);    cairo_type1_font_subset_write_encrypted (font,					     charstring, charstring_length);    length = snprintf (buffer, sizeof buffer, "%s\n", font->nd);    cairo_type1_font_subset_write_encrypted (font, buffer, length);}typedef void (*glyph_func_t) (cairo_type1_font_subset_t *font,			      const char *name, int name_length,			      const char *charstring, int charstring_length);static const char *cairo_type1_font_subset_for_each_glyph (cairo_type1_font_subset_t *font,					const char *dict_start,					const char *dict_end,					glyph_func_t func){    int charstring_length, name_length, glyph_index;    const char *p, *charstring, *name;    char *end;    /* We're looking at '/' in the name of the first glyph.  The glyph     * definitions are on the form:     *     *   /name 23 RD <23 binary bytes> ND     *     * or alternatively using -| and |- instead of RD and ND.     *     * We parse the glyph name and see if it is in the subset.  If it     * is, we call the specified callback with the glyph name and     * glyph data, otherwise we just skip it.  We need to parse     * through a glyph definition; we can't just find the next '/',     * since the binary data could contain a '/'.     */    p = dict_start;    while (*p == '/') {	name = p + 1;	p = skip_token (p, dict_end);	name_length = p - name;	charstring_length = strtol (p, &end, 10);	if (p == end) {	    font->status = CAIRO_INT_STATUS_UNSUPPORTED;	    return NULL;	}	/* Skip past -| or RD to binary data.  There is exactly one space	 * between the -| or RD token and the encrypted data, thus '+ 1'. */	charstring = skip_token (end, dict_end) + 1;	/* Skip binary data and |- or ND token. */	p = skip_token (charstring + charstring_length, dict_end);	while (p < dict_end && isspace(*p))	    p++;	/* In case any of the skip_token() calls above reached EOF, p will	 * be equal to dict_end. */	if (p == dict_end) {	    font->status = CAIRO_INT_STATUS_UNSUPPORTED;	    return NULL;	}	glyph_index = cairo_type1_font_subset_lookup_glyph (font,							    name, name_length);	if (font->glyphs[glyph_index].subset_index >= 0)	    func (font, name, name_length, charstring, charstring_length);    }    return p;}static const char *cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,					    const char                *name){    const char *p, *charstrings, *dict_start;    const char *closefile_token;    char buffer[32], *glyph_count_end;    int num_charstrings, length;    /* The private dict holds hint information, common subroutines and     * the actual glyph definitions (charstrings).     *     * FIXME: update this comment.     *     * What we do here is scan directly the /CharString token, which     * marks the beginning of the glyph definitions.  Then we parse     * through the glyph definitions and weed out the glyphs not in     * our subset.  Everything else before and after the glyph     * definitions is copied verbatim to the output.  It might be     * worthwile to figure out which of the common subroutines are     * used by the glyphs in the subset and get rid of the rest. */    /* FIXME: The /Subrs array contains binary data and could     * conceivably have "/CharStrings" in it, so we might need to skip     * this more cleverly. */    charstrings = find_token (font->cleartext, font->cleartext_end, "/CharStrings");    if (charstrings == NULL) {	font->status = CAIRO_INT_STATUS_UNSUPPORTED;	return NULL;    }    /* Scan past /CharStrings and the integer following it. */    p = charstrings + strlen ("/CharStrings");    num_charstrings = strtol (p, &glyph_count_end, 10);    if (p == glyph_count_end) {	font->status = CAIRO_INT_STATUS_UNSUPPORTED;	return NULL;    }    /* Look for a '/' which marks the beginning of the first glyph     * definition. */    for (p = glyph_count_end; p < font->cleartext_end; p++)	if (*p == '/')	    break;    if (p == font->cleartext_end) {	font->status = CAIRO_INT_STATUS_UNSUPPORTED;	return NULL;    }    dict_start = p;    if (cairo_type1_font_subset_get_glyph_names_and_widths (font))	return NULL;    /* Now that we have the private dictionary broken down in     * sections, do the first pass through the glyph definitions to     * figure out which subrs and othersubrs are use and which extra     * glyphs may be required by the seac operator. */    p = cairo_type1_font_subset_for_each_glyph (font,						dict_start,						font->cleartext_end,						cairo_type1_font_subset_look_for_seac);    closefile_token = find_token (p, font->cleartext_end, "closefile");    if (closefile_token == NULL) {	font->status = CAIRO_INT_STATUS_UNSUPPORTED;	return NULL;    }    if (cairo_type1_font_subset_get_glyph_names_and_widths (font))	return NULL;    /* We're ready to start outputting. First write the header,     * i.e. the public part of the font dict.*/    if (cairo_type1_font_subset_write_header (font, name))	return NULL;    font->base.header_size = _cairo_output_stream_get_position (font->output);    /* Start outputting the private dict.  First output everything up     * to the /CharStrings token. */    cairo_type1_font_subset_write_encrypted (font, font->cleartext,					     charstrings - font->cleartext);    /* Write out new charstring count */    length = snprintf (buffer, sizeof buffer,		       "/CharStrings %d", font->num_glyphs);    cairo_type1_font_subset_write_encrypted (font, buffer, length);    /* Write out text between the charstring count and the first     * charstring definition */    cairo_type1_font_subset_write_encrypted (font, glyph_count_end,					     dict_start - glyph_count_end);    /* Write out the charstring definitions for each of the glyphs in     * the subset. */    p = cairo_type1_font_subset_for_each_glyph (font,						dict_start,						font->cleartext_end,						write_used_glyphs);    /* Output what's left between the end of the glyph definitions and     * the end of the private dict to the output. */    cairo_type1_font_subset_write_encrypted (font, p,					     closefile_token - p + strlen ("closefile") + 1);    _cairo_output_stream_write (font->output, "\n", 1);    return p;}static cairo_status_tcairo_type1_font_subset_write_trailer(cairo_type1_font_subset_t *font){    const char *cleartomark_token;    int i;    static const char zeros[65] =	"0000000000000000000000000000000000000000000000000000000000000000\n";    /* Some fonts have conditional save/restore around the entire font     * dict, so we need to retain whatever postscript code that may     * come after 'cleartomark'. */    for (i = 0; i < 8; i++)	_cairo_output_stream_write (font->output, zeros, sizeof zeros);    cleartomark_token = find_token (font->type1_data, font->type1_end, "cleartomark");    if (cleartomark_token == NULL)	return font->status = CAIRO_INT_STATUS_UNSUPPORTED;    _cairo_output_stream_write (font->output, cleartomark_token,				font->type1_end - cleartomark_token);    return font->status;}static cairo_status_ttype1_font_write (void *closure, const unsigned char *data, unsigned int length){    cairo_type1_font_subset_t *font = closure;    font->status =	_cairo_array_append_multiple (&font->contents, data, length);    return font->status;}static cairo_status_tcairo_type1_font_subset_write (cairo_type1_font_subset_t *font,			       const char *name){    if (cairo_type1_font_subset_find_segments (font))	return font->status;    if (cairo_type1_font_subset_decrypt_eexec_segment (font))	return font->status;    /* Determine which glyph definition delimiters to use. */    if (find_token (font->cleartext, font->cleartext_end, "/-|") != NULL) {	font->rd = "-|";	font->nd = "|-";    } else if (find_token (font->cleartext, font->cleartext_end, "/RD") != NULL) {	font->rd = "RD";	font->nd = "ND";    } else {	/* Don't know *what* kind of font this is... */	return font->status = CAIRO_INT_STATUS_UNSUPPORTED;    }    font->eexec_key = private_dict_key;    font->hex_encode = TRUE;    font->hex_column = 0;    cairo_type1_font_subset_write_private_dict (font, name);    font->base.data_size = _cairo_output_stream_get_position (font->output) -	font->base.header_size;    cairo_type1_font_subset_write_trailer (font);    font->base.trailer_size =	_cairo_output_stream_get_position (font->output) -	font->base.header_size - font->base.data_size;    return font->status;}static cairo_status_tcairo_type1_font_subset_generate (void       *abstract_font,				  const char *name){    cairo_type1_font_subset_t *font = abstract_font;    cairo_ft_unscaled_font_t *ft_unscaled_font;    unsigned long ret;    ft_unscaled_font = (cairo_ft_unscaled_font_t *) font->base.unscaled_font;    font->face = _cairo_ft_unscaled_font_lock_face (ft_unscaled_font);    /* If anything fails below, it's out of memory. */    font->status = CAIRO_STATUS_NO_MEMORY;    font->type1_length = font->face->stream->size;    font->type1_data = malloc (font->type1_length);    if (font->type1_data == NULL)	goto fail;    if (font->face->stream->read) {	ret = font->face->stream->read (font->face->stream, 0,					(unsigned char *) font->type1_data,					font->type1_length);	if (ret != font->type1_length)	    goto fail;    } else {	memcpy (font->type1_data,		font->face->stream->base, font->type1_length);    }    if (_cairo_array_grow_by (&font->contents, 4096) != CAIRO_STATUS_SUCCESS)	goto fail;    font->output = _cairo_output_stream_create (type1_font_write, NULL, font);    if (font->output == NULL)	goto fail;    font->status = CAIRO_STATUS_SUCCESS;    cairo_type1_font_subset_write (font, name);    font->base.data = _cairo_array_index (&font->contents, 0); fail:    _cairo_ft_unscaled_font_unlock_face (ft_unscaled_font);    return font->status;}static voidcairo_type1_font_subset_destroy (void *abstract_font){    cairo_type1_font_subset_t *font = abstract_font;    int i;    /* If the subset generation failed, some of the pointers below may     * be NULL depending on at which point the error occurred. */    _cairo_array_fini (&font->contents);    free (font->type1_data);    if (font->glyphs != NULL)	for (i = 0; i < font->base.num_glyphs; i++) {	    free (font->glyphs[i].name);	}    _cairo_unscaled_font_destroy (font->base.unscaled_font);    free (font->base.base_font);    free (font->glyphs);    free (font);}cairo_status_t_cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,			  const char			*name,			  cairo_scaled_font_subset_t	*scaled_font_subset){    cairo_type1_font_subset_t *font;    cairo_status_t status;    unsigned long parent_glyph, length;    int i;    cairo_unscaled_font_t *unscaled_font;    /* 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;    unscaled_font = _cairo_ft_scaled_font_get_unscaled_font (scaled_font_subset->scaled_font);    status = _cairo_type1_font_subset_create (unscaled_font, &font);    if (status)	return status;    for (i = 0; i < scaled_font_subset->num_glyphs; i++) {	parent_glyph = scaled_font_subset->glyphs[i];	cairo_type1_font_subset_use_glyph (font, parent_glyph);    }    /* Pull in the .notdef glyph */    cairo_type1_font_subset_use_glyph (font, 0);    status = cairo_type1_font_subset_generate (font, name);    if (status)	goto fail1;    type1_subset->base_font = strdup (font->base.base_font);    if (type1_subset->base_font == NULL)	goto fail1;    type1_subset->widths = calloc (sizeof (int), font->num_glyphs);    if (type1_subset->widths == NULL)	goto fail2;    for (i = 0; i < font->base.num_glyphs; i++) {	if (font->glyphs[i].subset_index < 0)	    continue;	type1_subset->widths[font->glyphs[i].subset_index] =	    font->glyphs[i].width;    }    type1_subset->x_min = font->base.x_min;    type1_subset->y_min = font->base.y_min;    type1_subset->x_max = font->base.x_max;    type1_subset->y_max = font->base.y_max;    type1_subset->ascent = font->base.ascent;    type1_subset->descent = font->base.descent;    length = font->base.header_size + font->base.data_size +	font->base.trailer_size;    type1_subset->data = malloc (length);    if (type1_subset->data == NULL)	goto fail3;    memcpy (type1_subset->data,	    _cairo_array_index (&font->contents, 0), length);    type1_subset->header_length = font->base.header_size;    type1_subset->data_length = font->base.data_size;    type1_subset->trailer_length = font->base.trailer_size;    cairo_type1_font_subset_destroy (font);    return CAIRO_STATUS_SUCCESS; fail3:    free (type1_subset->widths); fail2:    free (type1_subset->base_font); fail1:    cairo_type1_font_subset_destroy (font);    return status;}void_cairo_type1_subset_fini (cairo_type1_subset_t *subset){    free (subset->base_font);    free (subset->widths);    free (subset->data);}

⌨️ 快捷键说明

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