[cairo-commit] 21 commits - src/cairo-font-subset.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-scaled-font-subsets-private.h src/cairo-type1-subset.c src/Makefile.am

Carl Worth cworth at kemper.freedesktop.org
Tue Jun 13 15:56:01 PDT 2006


 src/Makefile.am                         |   13 
 src/cairo-font-subset.c                 |  168 +++--
 src/cairo-pdf-surface.c                 |  267 +++++++-
 src/cairo-ps-surface.c                  |  442 ++++++++-----
 src/cairo-scaled-font-subsets-private.h |   85 ++
 src/cairo-type1-subset.c                | 1040 ++++++++++++++++++++++++++++++++
 6 files changed, 1788 insertions(+), 227 deletions(-)

New commits:
diff-tree 1d18af9f5adb0ce2e01bc42578fe117c4e924ce8 (from parents)
Merge: c7b194c59544ff441d1e83827242667c0e86dc5a 27e9e3cecd354475047ac268d5ef52eba3f041f1
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Jun 13 15:51:57 2006 -0700

    Merge branch 'type1-subsetting' into cairo
    
    Conflicts:
    
    	src/cairo-ps-surface.c

diff --cc src/cairo-ps-surface.c
index ed6bcca,1506909..00e0468
@@@ -80,11 -81,123 +80,122 @@@
      cairo_array_t dsc_page_setup_comments;
  
      cairo_array_t *dsc_comment_target;
 -    
 +
  } cairo_ps_surface_t;
  
 -#define PS_SURFACE_DPI_DEFAULT		300.0
  #define PS_SURFACE_MAX_GLYPHS_PER_FONT	256
  
+ /* A word wrap stream can be used as a filter to do word wrapping on
+  * top of an existing output stream. The word wrapping is quite
+  * simple, using isspace to determine characters that separate
+  * words. Any word that will cause the column count exceeed the given
+  * max_column will have a '\n' character emitted before it.
+  *
+  * The stream is careful to maintain integrity for words that cross
+  * the boundary from one call to write to the next.
+  *
+  * Note: This stream does not guarantee that the output will never
+  * exceed max_column. In particular, if a single word is larger than
+  * max_column it will not be broken up.
+  */
+ typedef struct _word_wrap_stream {
+     cairo_output_stream_t *output;
+     int max_column;
+     int column;
+     cairo_bool_t last_write_was_space;
+ } word_wrap_stream_t;
+ 
+ static int
+ _count_word_up_to (const unsigned char *s, int length)
+ {
+     int word = 0;
+ 
+     while (length--) {
+ 	if (! isspace (*s++))
+ 	    word++;
+ 	else
+ 	    return word;
+     }
+ 
+     return word;
+ }
+ 
+ static cairo_status_t
+ _word_wrap_stream_write (void			*closure,
+ 			 const unsigned char	*data,
+ 			 unsigned int		 length)
+ {
+     word_wrap_stream_t *stream = closure;
+     cairo_bool_t newline;
+     int word;
+ 
+     while (length) {
+ 	if (isspace (*data)) {
+ 	    newline =  (*data == '\n' || *data == '\r');
+ 	    if (! newline && stream->column >= stream->max_column) {
+ 		_cairo_output_stream_printf (stream->output, "\n");
+ 		stream->column = 0;
+ 	    }
+ 	    _cairo_output_stream_write (stream->output, data, 1);
+ 	    data++;
+ 	    length--;
+ 	    if (newline)
+ 		stream->column = 0;
+ 	    else
+ 		stream->column++;
+ 	    stream->last_write_was_space = TRUE;
+ 	} else {
+ 	    word = _count_word_up_to (data, length);
+ 	    /* Don't wrap if this word is a continuation of a word
+ 	     * from a previous call to write. */
+ 	    if (stream->column + word >= stream->max_column &&
+ 		stream->last_write_was_space)
+ 	    {
+ 		_cairo_output_stream_printf (stream->output, "\n");
+ 		stream->column = 0;
+ 	    }
+ 	    _cairo_output_stream_write (stream->output, data, word);
+ 	    data += word;
+ 	    length -= word;
+ 	    stream->column += word;
+ 	    stream->last_write_was_space = FALSE;
+ 	}
+     }
+ 
+     return _cairo_output_stream_get_status (stream->output);
+ }
+ 
+ static cairo_status_t
+ _word_wrap_stream_close (void *closure)
+ {
+     cairo_status_t status;
+     word_wrap_stream_t *stream = closure;
+ 
+     status = _cairo_output_stream_get_status (stream->output);
+ 
+     free (stream);
+ 
+     return status;
+ }
+ 
+ static cairo_output_stream_t *
+ _word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
+ {
+     word_wrap_stream_t *stream;
+ 
+     stream = malloc (sizeof (word_wrap_stream_t));
+     if (stream == NULL)
+ 	return (cairo_output_stream_t *) &cairo_output_stream_nil;
+ 
+     stream->output = output;
+     stream->max_column = max_column;
+     stream->column = 0;
+     stream->last_write_was_space = FALSE;
+ 
+     return _cairo_output_stream_create (_word_wrap_stream_write,
+ 					_word_wrap_stream_close, stream);
+ }
+ 
  static cairo_status_t
  _cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
  {
@@@ -298,77 -481,16 +461,72 @@@
  				 -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
  				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
  				 -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
 -    
 +
-     status = _cairo_path_fixed_interpret (scaled_glyph->path,
- 					  CAIRO_DIRECTION_FORWARD,
- 					  _cairo_ps_surface_path_move_to,
- 					  _cairo_ps_surface_path_line_to,
- 					  _cairo_ps_surface_path_curve_to,
- 					  _cairo_ps_surface_path_close_path,
- 					  surface->final_stream);
+     status = _cairo_ps_surface_emit_path (surface->final_stream,
+ 					  scaled_glyph->path);
 -					  
 -    
 +
      _cairo_output_stream_printf (surface->final_stream,
  				 "F\n");
 -    
 +
 +    return CAIRO_STATUS_SUCCESS;
 +}
 +
 +static cairo_int_status_t
 +_cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t	*surface,
 +					  cairo_scaled_font_t	*scaled_font,
 +					  unsigned long	 glyph_index)
 +{
 +    cairo_scaled_glyph_t *scaled_glyph;
 +    cairo_status_t status;
 +
 +    status = _cairo_scaled_glyph_lookup (scaled_font,
 +					 glyph_index,
 +					 CAIRO_SCALED_GLYPH_INFO_METRICS|
 +					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
 +					 &scaled_glyph);
 +
 +    _cairo_output_stream_printf (surface->final_stream,
 +				 "0 0 %f %f %f %f setcachedevice\n",
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
 +				 - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
 +				 - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
 +
 +    /* XXX: Should be painting the surface from scaled_glyph here, not just a filled rectangle. */
 +    _cairo_output_stream_printf (surface->final_stream,
 +				 "%f %f %f %f rectfill\n",
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
 +				 - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.y) - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y));
 +
 +    return CAIRO_STATUS_SUCCESS;
 +}
 +
 +static void
 +_cairo_ps_surface_emit_glyph (cairo_ps_surface_t	*surface,
 +			      cairo_scaled_font_t	*scaled_font,
 +			      unsigned long		 scaled_font_glyph_index,
 +			      unsigned int		 subset_glyph_index)
 +{
 +    cairo_status_t	    status;
 +
 +    _cairo_output_stream_printf (surface->final_stream,
 +				 "\t\t{ %% %d\n", subset_glyph_index);
 +
 +    status = _cairo_ps_surface_emit_outline_glyph_data (surface,
 +							scaled_font,
 +							scaled_font_glyph_index);
 +    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 +	status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
 +							   scaled_font,
 +							   scaled_font_glyph_index);
 +
      _cairo_output_stream_printf (surface->final_stream,
  				 "\t\t}\n");
 +
 +    if (status)
 +	_cairo_surface_set_error (&surface->base, status);
  }
  
  static cairo_status_t
@@@ -1004,18 -1051,15 +1055,11 @@@
  {
      cairo_status_t status;
      cairo_ps_surface_t *surface = abstract_surface;
-     cairo_output_stream_t *final_stream, *word_wrap;
 -    cairo_output_stream_t *final_stream;
      int i, num_comments;
      char **comments;
  
--    /* Save final_stream to be restored later. */
--    final_stream = surface->final_stream;
--
-     word_wrap = _word_wrap_stream_create (final_stream, 79);
-     surface->final_stream = word_wrap;
- 
      _cairo_ps_surface_emit_header (surface);
 -    
 +
      _cairo_ps_surface_emit_font_subsets (surface);
  
      _cairo_ps_surface_emit_body (surface);
diff --cc src/cairo-type1-subset.c
index 0000000,99367c0..703529c
mode 000000,100644..100644
@@@ -1,0 -1,1040 +1,1040 @@@
+ /* 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 at 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_TYPE1_TABLES_H
+ 
+ typedef 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 
++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 int
+ cairo_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_t
+ is_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_t
+ cairo_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 = 
++	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_t
+ cairo_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 int
+ hex_to_int (int ch)
+ {
+     if (ch <= '9')
+ 	return ch - '0';
+     else if (ch <= 'F')
+ 	return ch - 'A' + 10;
+     else
+ 	return ch - 'a' + 10;
+ }
+ 
+ static void
+ cairo_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_t
+ cairo_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 int
+ cairo_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_t
+ cairo_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 void
+ cairo_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 */
+     "oslash", "oe", "germandbls", 0, 0, 0, 0
+ };
+ 
+ static void
+ use_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 void
+ cairo_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 void
+ write_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).  
++     * 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_t
+ cairo_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_t
+ type1_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_t
+ cairo_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_t
+ cairo_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 void
+ cairo_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);
+ }
+ 
diff-tree c7b194c59544ff441d1e83827242667c0e86dc5a (from parents)
Merge: 4b063c607208935fad040d481d42085c4ed6e64d 127fab4695ef849364e755e10c2b960add78782b
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Jun 13 15:46:14 2006 -0700

    Merge branch 'truetype-subsetting' into cairo
    
    Conflicts:
    
    	src/Makefile.am
    	src/cairo-font-subset.c
    	src/cairo-pdf-surface.c
    	src/cairo-ps-surface.c

diff --cc src/Makefile.am
index 2968228,bf1068a..59d1531
@@@ -1,14 -6,14 +6,14 @@@
  
  if CAIRO_HAS_PS_SURFACE
  libcairo_ps_headers = cairo-ps.h
- libcairo_ps_sources = cairo-ps-surface.c cairo-ps-test.h cairo-scaled-font-subsets.c cairo-scaled-font-subsets-private.h
- libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h
 -libcairo_ps_sources = cairo-ps-surface.c
++libcairo_ps_sources = cairo-ps-surface.c cairo-ps-test.h
+ libcairo_font_subset_sources =	$(font_subset_sources)
  endif
  
  if CAIRO_HAS_PDF_SURFACE
  libcairo_pdf_headers = cairo-pdf.h
 -libcairo_pdf_sources = cairo-pdf-surface.c
 +libcairo_pdf_sources = cairo-pdf-surface.c cairo-pdf-test.h
- libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h
+ libcairo_font_subset_sources =	$(font_subset_sources)
  endif
  
  if CAIRO_HAS_PNG_FUNCTIONS
@@@ -17,7 -22,8 +22,8 @@@
  
  if CAIRO_HAS_SVG_SURFACE
  libcairo_svg_headers = cairo-svg.h
 -libcairo_svg_sources = cairo-svg-surface.c
 +libcairo_svg_sources = cairo-svg-surface.c cairo-svg-test.h
+ libcairo_font_subset_sources =	$(font_subset_sources)
  endif
  
  if CAIRO_HAS_TEST_SURFACES
diff --cc src/cairo-pdf-surface.c
index e365b77,3ab2d89..a5e5beb
@@@ -1579,13 -1663,116 +1579,115 @@@
  				 "endobj\r\n");
  }
  
+ static cairo_status_t
+ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
+ 					      cairo_scaled_font_subset_t	*font_subset)
+ {
+     cairo_pdf_resource_t stream, descriptor, subset_resource;
+     cairo_status_t status;
+     cairo_pdf_font_t font;
+     cairo_truetype_subset_t subset;
+     unsigned long compressed_length;
+     char *compressed;
+     int i;
+ 
+     status = _cairo_truetype_subset_init (&subset, font_subset);
+     if (status)
+ 	return status;
+ 
+     compressed = compress_dup (subset.data, subset.data_length,
+ 			       &compressed_length);
+     if (compressed == NULL) {
+ 	_cairo_truetype_subset_fini (&subset);
+ 	return CAIRO_STATUS_NO_MEMORY;
+     }
+ 
+     stream = _cairo_pdf_surface_new_object (surface);
+     _cairo_output_stream_printf (surface->output,
+ 				 "%d 0 obj\r\n"
+ 				 "<< /Filter /FlateDecode\r\n"
+ 				 "   /Length %lu\r\n"
+ 				 "   /Length1 %lu\r\n"
+ 				 ">>\r\n"
+ 				 "stream\r\n",
+ 				 stream.id,
+ 				 compressed_length,
+ 				 subset.data_length);
+     _cairo_output_stream_write (surface->output, compressed, compressed_length);
+     _cairo_output_stream_printf (surface->output,
+ 				 "\r\n"
+ 				 "endstream\r\n"
+ 				 "endobj\r\n");
+     free (compressed);
+ 
+     descriptor = _cairo_pdf_surface_new_object (surface);
+     _cairo_output_stream_printf (surface->output,
+ 				 "%d 0 obj\r\n"
+ 				 "<< /Type /FontDescriptor\r\n"
+ 				 "   /FontName /7%s\r\n"
+ 				 "   /Flags 4\r\n"
+ 				 "   /FontBBox [ %ld %ld %ld %ld ]\r\n"
+ 				 "   /ItalicAngle 0\r\n"
+ 				 "   /Ascent %ld\r\n"
+ 				 "   /Descent %ld\r\n"
+ 				 "   /CapHeight 500\r\n"
+ 				 "   /StemV 80\r\n"
+ 				 "   /StemH 80\r\n"
+ 				 "   /FontFile2 %u 0 R\r\n"
+ 				 ">>\r\n"
+ 				 "endobj\r\n",
+ 				 descriptor.id,
+ 				 subset.base_font,
+ 				 subset.x_min,
+ 				 subset.y_min,
+ 				 subset.x_max,
+ 				 subset.y_max,
+ 				 subset.ascent,
+ 				 subset.descent,
+ 				 stream.id);
+ 
+     subset_resource = _cairo_pdf_surface_new_object (surface);
+     _cairo_output_stream_printf (surface->output,
+ 				 "%d 0 obj\r\n"
+ 				 "<< /Type /Font\r\n"
+ 				 "   /Subtype /TrueType\r\n"
+ 				 "   /BaseFont /%s\r\n"
+ 				 "   /FirstChar 0\r\n"
+ 				 "   /LastChar %d\r\n"
+ 				 "   /FontDescriptor %d 0 R\r\n"
+ 				 "   /Widths [",
+ 				 subset_resource.id,
+ 				 subset.base_font,
+ 				 font_subset->num_glyphs,
+ 				 descriptor.id);
+ 
+     for (i = 0; i < font_subset->num_glyphs; i++)
+ 	_cairo_output_stream_printf (surface->output,
+ 				     " %d",
+ 				     subset.widths[i]);
+ 
+     _cairo_output_stream_printf (surface->output,
+ 				 " ]\r\n"
+ 				 ">>\r\n"
+ 				 "endobj\r\n");
+ 
+     font.font_id = font_subset->font_id;
+     font.subset_id = font_subset->subset_id;
+     font.subset_resource = subset_resource;
+     _cairo_array_append (&surface->fonts, &font);
+ 
+     _cairo_truetype_subset_fini (&subset);
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
 -static void
 -_cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t	*surface,
 -			       cairo_scaled_font_t	*scaled_font,
 -			       unsigned long		 scaled_font_glyph_index,
 -			       unsigned int		 subset_glyph_index,
 -			       cairo_pdf_resource_t	*glyph_ret)
 +static cairo_int_status_t
 +_cairo_pdf_surface_emit_outline_glyph_data (cairo_pdf_surface_t	*surface,
 +					    cairo_scaled_font_t	*scaled_font,
 +					    unsigned long	 glyph_index)
  {
      cairo_scaled_glyph_t *scaled_glyph;
 +    pdf_path_info_t info;
      cairo_status_t status;
  
      status = _cairo_scaled_glyph_lookup (scaled_font,
diff --cc src/cairo-ps-surface.c
index 6553bce,eaf4924..ed6bcca
@@@ -209,16 -211,84 +209,83 @@@
      }
  }
  
+ static cairo_status_t
+ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t		*surface,
+ 					     cairo_scaled_font_subset_t	*font_subset)
+ 
+ 
+ {
+     cairo_truetype_subset_t subset;
+     cairo_status_t status;
+     int i;
+ 
+     status = _cairo_truetype_subset_init (&subset, font_subset);
+     if (status)
+ 	return status;
+ 
+     /* FIXME: Figure out document structure convention for fonts */
+ 
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "%% _cairo_ps_surface_emit_truetype_font_subset\n");
+ 
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "11 dict begin\n"
+ 				 "/FontType 42 def\n"
+ 				 "/FontName /CairoFont-%d-%d def\n"
+ 				 "/PaintType 0 def\n"
+ 				 "/FontMatrix [ 1 0 0 1 0 0 ] def\n"
+ 				 "/FontBBox [ 0 0 0 0 ] def\n"
+ 				 "/Encoding 256 array def\n"
+ 				 "0 1 255 { Encoding exch /.notdef put } for\n",
+ 				 font_subset->font_id,
+ 				 font_subset->subset_id);
+ 
+     /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
+ 
+     for (i = 1; i < font_subset->num_glyphs; i++)
+ 	_cairo_output_stream_printf (surface->final_stream,
+ 				     "Encoding %d /g%d put\n", i, i);
+ 
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "/CharStrings %d dict dup begin\n"
+ 				 "/.notdef 0 def\n",
+ 				 font_subset->num_glyphs);
+ 
+     for (i = 1; i < font_subset->num_glyphs; i++)
+ 	_cairo_output_stream_printf (surface->final_stream,
+ 				     "/g%d %d def\n", i, i);
+ 
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "end readonly def\n");
+ 
+     /* FIXME: We need to break up fonts bigger than 64k so we don't
+      * exceed string size limitation.  At glyph boundaries.  Stupid
+      * postscript. */
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 "/sfnts [<");
+ 
+     _cairo_output_stream_write_hex_string (surface->final_stream,
+ 					   subset.data, subset.data_length);
+ 
+     _cairo_output_stream_printf (surface->final_stream,
+ 				 ">] def\n"
+ 				 "FontName currentdict end definefont pop\n");
+ 
+     _cairo_truetype_subset_fini (&subset);
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
 -static void
 -_cairo_ps_surface_emit_glyph (cairo_ps_surface_t	*surface,
 -			      cairo_scaled_font_t	*scaled_font,
 -			      unsigned long		 scaled_font_glyph_index,
 -			      unsigned int		 subset_glyph_index)
 +static cairo_int_status_t
 +_cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t	*surface,
 +					   cairo_scaled_font_t	*scaled_font,
 +					   unsigned long	 glyph_index)
  {
 -    cairo_scaled_glyph_t    *scaled_glyph;
 -    cairo_status_t	    status;
 +    cairo_scaled_glyph_t *scaled_glyph;
 +    cairo_status_t status;
  
      status = _cairo_scaled_glyph_lookup (scaled_font,
 -					 scaled_font_glyph_index,
 +					 glyph_index,
  					 CAIRO_SCALED_GLYPH_INFO_METRICS|
  					 CAIRO_SCALED_GLYPH_INFO_PATH,
  					 &scaled_glyph);
@@@ -239,76 -326,21 +306,78 @@@
  					  _cairo_ps_surface_path_curve_to,
  					  _cairo_ps_surface_path_close_path,
  					  surface->final_stream);
 -    
 +
      _cairo_output_stream_printf (surface->final_stream,
  				 "F\n");
 -    
 +
 +    return CAIRO_STATUS_SUCCESS;
 +}
 +
 +static cairo_int_status_t
 +_cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t	*surface,
 +					  cairo_scaled_font_t	*scaled_font,
 +					  unsigned long	 glyph_index)
 +{
 +    cairo_scaled_glyph_t *scaled_glyph;
 +    cairo_status_t status;
 +
 +    status = _cairo_scaled_glyph_lookup (scaled_font,
 +					 glyph_index,
 +					 CAIRO_SCALED_GLYPH_INFO_METRICS|
 +					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
 +					 &scaled_glyph);
 +
 +    _cairo_output_stream_printf (surface->final_stream,
 +				 "0 0 %f %f %f %f setcachedevice\n",
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
 +				 - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
 +				 - _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
 +
 +    /* XXX: Should be painting the surface from scaled_glyph here, not just a filled rectangle. */
 +    _cairo_output_stream_printf (surface->final_stream,
 +				 "%f %f %f %f rectfill\n",
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
 +				 - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) - _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
 +				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.y) - _cairo_fixed_to_double (scaled_glyph->bbox.p2.y));
 +
 +    return CAIRO_STATUS_SUCCESS;
 +}
 +
 +static void
 +_cairo_ps_surface_emit_glyph (cairo_ps_surface_t	*surface,
 +			      cairo_scaled_font_t	*scaled_font,
 +			      unsigned long		 scaled_font_glyph_index,
 +			      unsigned int		 subset_glyph_index)
 +{
 +    cairo_status_t	    status;
 +
 +    _cairo_output_stream_printf (surface->final_stream,
 +				 "\t\t{ %% %d\n", subset_glyph_index);
 +
 +    status = _cairo_ps_surface_emit_outline_glyph_data (surface,
 +							scaled_font,
 +							scaled_font_glyph_index);
 +    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 +	status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
 +							   scaled_font,
 +							   scaled_font_glyph_index);
 +
      _cairo_output_stream_printf (surface->final_stream,
  				 "\t\t}\n");
 +
 +    if (status)
 +	_cairo_surface_set_error (&surface->base, status);
  }
  
- static void
- _cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
- 				    void			*closure)
+ static cairo_status_t
+ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
+ 					  cairo_scaled_font_subset_t	*font_subset)
+ 
+ 
  {
-     cairo_ps_surface_t *surface = closure;
+     cairo_matrix_t matrix;
      int i;
  
      _cairo_output_stream_printf (surface->final_stream,
@@@ -319,15 -351,21 +388,21 @@@
  				 font_subset->font_id,
  				 font_subset->subset_id);
  
+     matrix = font_subset->scaled_font->scale;
+     cairo_matrix_invert (&matrix);
      _cairo_output_stream_printf (surface->final_stream,
  				 "\t/FontType\t3\n"
- 				 "\t/FontMatrix\t[1 0 0 1 0 0]\n"
+ 				 "\t/FontMatrix\t[%f %f %f %f 0 0]\n"
  				 "\t/Encoding\t[0]\n"
  				 "\t/FontBBox\t[0 0 10 10]\n"
- 				 "\t/Glyphs [\n");
+ 				 "\t/Glyphs [\n",
+ 				 matrix.xx,
+ 				 matrix.yx,
+ 				 -matrix.xy,
+ 				 -matrix.yy);
  
      for (i = 0; i < font_subset->num_glyphs; i++) {
 -	_cairo_ps_surface_emit_glyph (surface, 
 +	_cairo_ps_surface_emit_glyph (surface,
  				      font_subset->scaled_font,
  				      font_subset->glyphs[i], i);
      }
diff --cc src/cairo-scaled-font-subsets-private.h
index f8b5ac8,a0b0dbc..b649989
@@@ -179,4 -179,45 +179,45 @@@
  				    cairo_scaled_font_subset_callback_func_t	 font_subset_callback,
  				    void					*closure);
  
+ 
+ typedef struct _cairo_truetype_subset {
+     char *base_font;
+     int *widths;
+     long x_min, y_min, x_max, y_max;
+     long ascent, descent;
+     char *data;
+     unsigned long data_length;
+ } cairo_truetype_subset_t;
+ 
+ /**
+  * _cairo_truetype_subset_init:
+  * @truetype_subset: a #cairo_truetype_subset_t to initialize
+  * @font_subset: the #cairo_scaled_font_subset_t to initialize from
+  *
+  * If possible (depending on the format of the underlying
+  * cairo_scaled_font_t and the font backend in use) generate a
+  * truetype file corresponding to @font_subset and initialize
+  * @truetype_subset with information about the subset and the truetype
+  * data.
+  *
+  * Return value: CAIRO_STATUS_SUCCESS if successful,
+  * CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
+  * truetype file, or an non-zero value indicating an error.  Possible
+  * errors include CAIRO_STATUS_NO_MEMORY.
+  **/
+ cairo_private cairo_status_t
+ _cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
+ 			     cairo_scaled_font_subset_t	*font_subset);
 -			     
++
+ /**
+  * _cairo_truetype_subset_fini:
+  * @truetype_subset: a #cairo_truetype_subset_t
+  *
+  * Free all resources associated with @truetype_subset.  After this
+  * call, @truetype_subset should not be used again without a
+  * subsequent call to _cairo_truetype_subset_init() again first.
+  **/
+ cairo_private void
+ _cairo_truetype_subset_fini (cairo_truetype_subset_t *truetype_subset);
+ 
  #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
diff-tree 27e9e3cecd354475047ac268d5ef52eba3f041f1 (from fb7ae2a28e46895f764754c6961cb99989be7a04)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Fri May 19 02:17:35 2006 -0400

    Handle seac charstring commands correctly.
    
     - Include PS standard encoding table so we can map from standard
       encoding indices to glyph names and then make sure to include the
       glyph of that name.
     - Cut out verbose debugging code.
     - Fix a couple of bugs in glyph name to index lookup code.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 4dcc7a3..99367c0 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -394,21 +394,20 @@ skip_token (const char *p, const char *e
     return p;
 }
 
-static cairo_bool_t
-cairo_type1_font_subset_contains_glyph (cairo_type1_font_subset_t *font,
-					const char *glyph_name, int length)
+static int
+cairo_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].subset_index < -1)
-	    continue;
 	if (font->glyphs[i].name &&
-	    strncmp (font->glyphs[i].name, glyph_name, length) == 0)
-	    return TRUE;
+	    strncmp (font->glyphs[i].name, glyph_name, length) == 0 &&
+	    font->glyphs[i].name[length] == '\0')
+	    return i;
     }
 
-    return FALSE;
+    return -1;
 }
 
 static cairo_status_t
@@ -420,8 +419,6 @@ cairo_type1_font_subset_get_glyph_names_
 
     /* Get glyph names and width using the freetype API */
     for (i = 0; i < font->base.num_glyphs; i++) {
-	if (font->glyphs[i].subset_index < 0)
-	    continue;
 	if (font->glyphs[i].name != NULL)
 	    continue;
 
@@ -463,7 +460,6 @@ cairo_type1_font_subset_decrypt_charstri
     }
 }
 
-
 static const unsigned char *
 cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer)
 {
@@ -473,103 +469,81 @@ cairo_type1_font_subset_decode_integer (
         *integer = (p[0] - 247) * 256 + p[1] + 108;
         p += 2;
     } else if (*p <= 254) {
-        *integer = (p[0] - 251) * 256 - p[1] - 108;
+        *integer = -(p[0] - 251) * 256 - p[1] - 108;
         p += 2;
     } else {
-        *integer = (p[1] << 24) |
-                 (p[2] << 16) |
-                 (p[3] << 8) |
-                  p[4];
+        *integer = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
         p += 5;
     }
 
     return p;
 }
 
-#ifdef DEBUG_GLYPH_COMMANDS
-typedef struct _charstring_command charstring_command_t;
-struct _charstring_command {
-    const char *name;
-    int args;
-};
-
-charstring_command_t charstring_commands[] = {
-    {},				/* 0 */
-    { "hstem", 2 },
-    {},
-    { "vstem", 2 },
-    { "vmoveto", 1 },
-    { "rlineto", 2 },		/* 5 */
-    { "hlineto", 1 },
-    { "vlineto", 1 },
-    { "rcurveto", 6 },
-    { "closepath", 0 },
-    { "callsubr", 0 },		/* 10 */
-    { "return", 0 },
-    {},
-    { "hsbw", 2 },
-    { "endchar", 0 },
-    {}, {}, {}, {}, {},		/* 15 */
-    {},				/* 20 */
-    { "rmoveto", 2 },
-    { "hmoveto", 1 },
-    {}, {},
-    {}, {}, {}, {}, {},		/* 25 */
-    { "vhcurveto", 4 },		/* 30 */
-    { "hvcurveto", 4 },
-
-    /* two byte codes */
-    { "dotsection", 0 },	/* 0 */
-    { "vstem3", 6 },
-    { "hstem3", 6 },
-    {}, {},
-    {},				/* 5 */
-    { "seac", 5 },
-    { "sbw", 4 },
-    {}, {},
-    {}, {},			/* 10 */
-    { "div", 2 },
-    {}, {},
-    {},				/* 15 */
-    { "callothersubr", 0 },
-    { "pop", 0 },
-    {}, {},
-    {}, {}, {}, {}, {},		/* 20 */
-    {}, {}, {}, {}, {},		/* 25 */
-    {}, {}, {}, 		/* 30 */
-    { "setcurrentpoint", 2 }
+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 */
+    "oslash", "oe", "germandbls", 0, 0, 0, 0
 };
 
-static const char *
-get_command_name (int command)
+static void
+use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
 {
-    static char buffer[100];
+    const char *glyph_name;
 
-    int num_commands = sizeof (charstring_commands) / sizeof (charstring_commands[0]);
+    if (index < 0 || index > 255)
+	return;
 
-    if (command >= 0 && command < num_commands &&
-	charstring_commands[command].name != NULL)
-	return charstring_commands[command].name;
+    glyph_name = ps_standard_encoding[index];
+    if (glyph_name == NULL)
+	return;
 
-    sprintf (buffer, "<invalid %d>", command);
-    return buffer;
+    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);
 }
-#endif
-
-#define TYPE1_CHARSTRING_COMMAND_RLINETO	(5)
-#define TYPE1_CHARSTRING_COMMAND_HLINETO	(6)
-#define TYPE1_CHARSTRING_COMMAND_CLOSEPATH	(9)
-#define TYPE1_CHARSTRING_COMMAND_CALLSUBR	(10)
-#define TYPE1_CHARSTRING_COMMAND_HSBW		(13)
-#define TYPE1_CHARSTRING_COMMAND_ENDCHAR	(14)
-#define TYPE1_CHARSTRING_COMMAND_HMOVETO	(22)
-#define TYPE1_CHARSTRING_COMMAND_HVCURVETO	(31)
 
+#define TYPE1_CHARSTRING_COMMAND_ESCAPE		(12)
 #define TYPE1_CHARSTRING_COMMAND_SEAC		(32 + 6)
-#define TYPE1_CHARSTRING_COMMAND_SBW		(32 + 7)
-#define TYPE1_CHARSTRING_COMMAND_DIV		(32 + 12)
-#define TYPE1_CHARSTRING_COMMAND_CALLOTHERSUBR	(32 + 16)
-#define TYPE1_CHARSTRING_COMMAND_POP		(32 + 17)
 
 static void
 cairo_type1_font_subset_look_for_seac(cairo_type1_font_subset_t *font,
@@ -579,68 +553,54 @@ cairo_type1_font_subset_look_for_seac(ca
     unsigned char *charstring;
     const unsigned char *end;
     const unsigned char *p;
-    int current_int;
-    int last_int;
+    int stack[5], sp, value;
     int command;
-    int count;
 
     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;
-    current_int = -1;
-    last_int = -1;
-    count = 0;
+    sp = 0;
+
     while (p < end) {
         if (*p < 32) {
 	    command = *p++;
-	    if (command == 12)
-		command = 32 + *p++;
 
-#ifdef DEBUG_GLYPH_COMMANDS
-	    printf ("%s ", get_command_name(command));
-#endif
+	    if (command == TYPE1_CHARSTRING_COMMAND_ESCAPE)
+		command = 32 + *p++;
 
 	    switch (command) {
 	    case TYPE1_CHARSTRING_COMMAND_SEAC:
-		if (last_int >= font->base.num_glyphs ||
-		    current_int >= font->base.num_glyphs) {
-#ifdef DEBUG_GLYPH_COMMANDS
-		    printf ("*** composite glyph out of bounds\n");
-#endif
-		    break;
-		}
-
-		cairo_type1_font_subset_use_glyph (font, last_int);
-		cairo_type1_font_subset_use_glyph (font, current_int);
+		/* 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;
 
-	    case TYPE1_CHARSTRING_COMMAND_CALLOTHERSUBR:
-		break;
-	    case TYPE1_CHARSTRING_COMMAND_CALLSUBR:
+	    default:
+		sp = 0;
 		break;
 	    }
         } else {
             /* integer argument */
-	    count++;
-            last_int = current_int;
-            p = cairo_type1_font_subset_decode_integer (p, &current_int);
-
-#ifdef DEBUG_GLYPH_COMMANDS
-	    printf ("%d ", current_int);
-#endif
+	    p = cairo_type1_font_subset_decode_integer (p, &value);
+	    if (sp < 5)
+		stack[sp++] = value;
         }
     }
 
-#ifdef DEBUG_GLYPH_COMMANDS
-    printf ("\n");
-#endif
-
     free (charstring);
 }
 
@@ -672,7 +632,7 @@ cairo_type1_font_subset_for_each_glyph (
 					const char *dict_end,
 					glyph_func_t func)
 {
-    int charstring_length, name_length;
+    int charstring_length, name_length, glyph_index;
     const char *p, *charstring, *name;
     char *end;
 
@@ -719,7 +679,9 @@ cairo_type1_font_subset_for_each_glyph (
 	    return NULL;
 	}
 
-	if (cairo_type1_font_subset_contains_glyph (font, name, name_length))
+	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);
     }
 
diff-tree fb7ae2a28e46895f764754c6961cb99989be7a04 (from 1d2b60454fb1e7a1e4b7614029f02dfb0e33acb3)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Thu May 18 21:01:20 2006 -0400

    Remember to call cairo_type1_font_subset_destroy().

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index cae1da5..4dcc7a3 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -1054,6 +1054,8 @@ _cairo_type1_subset_init (cairo_type1_su
     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:
diff-tree 1d2b60454fb1e7a1e4b7614029f02dfb0e33acb3 (from 6d53687058dc35bb1abd1f9552f43fccad61474f)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Thu May 18 20:50:36 2006 -0400

    Consolidate a few arrays into a array of structs.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index d6cfb13..cae1da5 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -53,7 +53,6 @@ typedef struct _cairo_type1_font_subset 
 	unsigned int font_id;
 	char *base_font;
 	int num_glyphs;
-	int *widths;
 	long x_min, y_min, x_max, y_max;
 	long ascent, descent;
 
@@ -66,8 +65,12 @@ typedef struct _cairo_type1_font_subset 
 
     FT_Face face;
     int num_glyphs;
-    int *glyph_set;
-    char **glyph_names;
+
+    struct {
+	int subset_index;
+	int width;
+	char *name;
+    } *glyphs;
 
     cairo_output_stream_t *output;
     cairo_array_t contents;
@@ -137,13 +140,13 @@ _cairo_type1_font_subset_create (cairo_u
     }
     font->base.base_font[i] = '\0';
 
-    font->glyph_set = calloc (face->num_glyphs, sizeof font->glyph_set[0]);
-    if (font->glyph_set == NULL)
+    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->glyph_set[i] = -1;
+	font->glyphs[i].subset_index = -1;
 
     _cairo_array_init (&font->contents, sizeof (char));
 
@@ -164,10 +167,13 @@ _cairo_type1_font_subset_create (cairo_u
 static int
 cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph)
 {
-    font->glyph_set[glyph] = font->num_glyphs;
+    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 glyph;
+    return font->glyphs[glyph].subset_index;
 }
 
 /* Magic constants for the type1 eexec encryption */
@@ -272,12 +278,12 @@ cairo_type1_font_subset_write_header (ca
 				 "/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->glyph_set[i] < 0)
+	if (font->glyphs[i].subset_index < 0)
 	    continue;
 	_cairo_output_stream_printf (font->output,
 				     "dup %d /%s put\n",
-				     font->glyph_set[i],
-				     font->glyph_names[i]);
+				     font->glyphs[i].subset_index,
+				     font->glyphs[i].name);
     }
     _cairo_output_stream_printf (font->output, "readonly def");
 
@@ -395,10 +401,10 @@ cairo_type1_font_subset_contains_glyph (
     int i;
 
     for (i = 0; i < font->base.num_glyphs; i++) {
-	if (font->glyph_set[i] < -1)
+	if (font->glyphs[i].subset_index < -1)
 	    continue;
-	if (font->glyph_names[i] &&
-	    strncmp (font->glyph_names[i], glyph_name, length) == 0)
+	if (font->glyphs[i].name &&
+	    strncmp (font->glyphs[i].name, glyph_name, length) == 0)
 	    return TRUE;
     }
 
@@ -412,21 +418,11 @@ cairo_type1_font_subset_get_glyph_names_
     char buffer[256];
     FT_Error error;
 
-    if (font->glyph_names == NULL) {
-	font->glyph_names = calloc (font->base.num_glyphs, sizeof (char *));
-	if (font->glyph_names == NULL)
-	    return font->status = CAIRO_STATUS_NO_MEMORY;
-	
-	font->base.widths = calloc (font->face->num_glyphs, sizeof (int));
-	if (font->base.widths == NULL)
-	    return font->status = CAIRO_STATUS_NO_MEMORY;
-    }
-
     /* Get glyph names and width using the freetype API */
     for (i = 0; i < font->base.num_glyphs; i++) {
-	if (font->glyph_set[i] < 0)
+	if (font->glyphs[i].subset_index < 0)
 	    continue;
-	if (font->glyph_names[i] != NULL)
+	if (font->glyphs[i].name != NULL)
 	    continue;
 
 	error = FT_Load_Glyph (font->face, i,
@@ -437,7 +433,7 @@ cairo_type1_font_subset_get_glyph_names_
 	    return font->status = CAIRO_STATUS_NO_MEMORY;
 	}
 
-	font->base.widths[i] = font->face->glyph->metrics.horiAdvance;
+	font->glyphs[i].width = font->face->glyph->metrics.horiAdvance;
 
 	error = FT_Get_Glyph_Name(font->face, i, buffer, sizeof buffer);
 	if (error != 0) {
@@ -445,8 +441,8 @@ cairo_type1_font_subset_get_glyph_names_
 	    return font->status = CAIRO_STATUS_NO_MEMORY;
 	}
 
-	font->glyph_names[i] = strdup (buffer);
-	if (font->glyph_names[i] == NULL)
+	font->glyphs[i].name = strdup (buffer);
+	if (font->glyphs[i].name == NULL)
 	    return font->status = CAIRO_STATUS_NO_MEMORY;
     }
 
@@ -978,17 +974,15 @@ cairo_type1_font_subset_destroy (void *a
     _cairo_array_fini (&font->contents);
 
     free (font->type1_data);
-    if (font->glyph_names != NULL)
-	for (i = 0; i < font->base.num_glyphs; i++)
-	    free (font->glyph_names[i]);
-
-    free (font->base.widths);
-    free (font->glyph_names);
+    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->glyph_set);
+    free (font->glyphs);
     free (font);
 }
 
@@ -1030,11 +1024,15 @@ _cairo_type1_subset_init (cairo_type1_su
     if (type1_subset->base_font == NULL)
 	goto fail1;
 
-    type1_subset->widths = calloc (sizeof (int), font->base.num_glyphs);
+    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++)
-	type1_subset->widths[i] = font->base.widths[i];
+    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;
diff-tree 6d53687058dc35bb1abd1f9552f43fccad61474f (from d09d95a3231d9137c00da72e5bf56fe246671e15)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Thu May 18 20:03:53 2006 -0400

    Look for /-| or /RD tokens to determine the charstring delimiter tokens.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index b167b40..d6cfb13 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -72,6 +72,8 @@ typedef struct _cairo_type1_font_subset 
     cairo_output_stream_t *output;
     cairo_array_t contents;
 
+    const char *rd, *nd;
+
     char *type1_data;
     unsigned int type1_length;
     char *type1_end;
@@ -173,18 +175,25 @@ static const unsigned short c1 = 52845, 
 static const unsigned short private_dict_key = 55665;
 static const unsigned short charstring_key = 4330;
 
+static cairo_bool_t
+is_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 || isspace(buffer[i - 1])) &&
-		(buffer + i == end - length || isspace(buffer[i + length])))
+	    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;
@@ -648,11 +657,13 @@ write_used_glyphs (cairo_type1_font_subs
     int length;
 
     length = snprintf (buffer, sizeof buffer,
-		       "/%.*s %d RD ", name_length, name, charstring_length);
+		       "/%.*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);
-    cairo_type1_font_subset_write_encrypted (font, "ND\n", 4);
+    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,
@@ -875,7 +886,19 @@ cairo_type1_font_subset_write (cairo_typ
 
     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;
diff-tree d09d95a3231d9137c00da72e5bf56fe246671e15 (from 5f55ae7d91174d29f83b2a15e4def0f6baea7344)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Thu May 18 15:10:05 2006 -0400

    Track glyph subset indices and use them in the output.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 3cff501..b167b40 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -65,7 +65,8 @@ typedef struct _cairo_type1_font_subset 
     } base;
 
     FT_Face face;
-    char *glyph_set;
+    int num_glyphs;
+    int *glyph_set;
     char **glyph_names;
 
     cairo_output_stream_t *output;
@@ -134,12 +135,13 @@ _cairo_type1_font_subset_create (cairo_u
     }
     font->base.base_font[i] = '\0';
 
-    font->glyph_set = calloc (face->num_glyphs, sizeof (char));
+    font->glyph_set = calloc (face->num_glyphs, sizeof font->glyph_set[0]);
     if (font->glyph_set == NULL)
 	goto fail2;
 
-    /* Add .notdef glyph */
-    font->glyph_set[0] = 1;
+    font->num_glyphs = 0;
+    for (i = 0; i < face->num_glyphs; i++)
+	font->glyph_set[i] = -1;
 
     _cairo_array_init (&font->contents, sizeof (char));
 
@@ -158,11 +160,10 @@ _cairo_type1_font_subset_create (cairo_u
 }
 
 static int
-cairo_type1_font_subset_use_glyph (void *abstract_font, int glyph)
+cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph)
 {
-    cairo_type1_font_subset_t *font = abstract_font;
-
-    font->glyph_set[glyph] = 1;
+    font->glyph_set[glyph] = font->num_glyphs;
+    font->num_glyphs++;
 
     return glyph;
 }
@@ -235,7 +236,7 @@ cairo_type1_font_subset_write_header (ca
 					 const char *name)
 {
     const char *start, *end, *segment_end;
-    int i, j;
+    int i;
 
     segment_end = font->header_segment + font->header_segment_size;
 
@@ -261,12 +262,13 @@ cairo_type1_font_subset_write_header (ca
     _cairo_output_stream_printf (font->output,
 				 "/Encoding 256 array\n"
 				 "0 1 255 {1 index exch /.notdef put} for\n");
-    for (i = 1, j = 0; i < font->base.num_glyphs; i++) {
-	if (!font->glyph_set[i])
+    for (i = 0; i < font->base.num_glyphs; i++) {
+	if (font->glyph_set[i] < 0)
 	    continue;
-	_cairo_output_stream_printf (font->output, "dup %d /%s put\n",
-				     j, font->glyph_names[i]);
-	j++;
+	_cairo_output_stream_printf (font->output,
+				     "dup %d /%s put\n",
+				     font->glyph_set[i],
+				     font->glyph_names[i]);
     }
     _cairo_output_stream_printf (font->output, "readonly def");
 
@@ -384,7 +386,7 @@ cairo_type1_font_subset_contains_glyph (
     int i;
 
     for (i = 0; i < font->base.num_glyphs; i++) {
-	if (!font->glyph_set[i])
+	if (font->glyph_set[i] < -1)
 	    continue;
 	if (font->glyph_names[i] &&
 	    strncmp (font->glyph_names[i], glyph_name, length) == 0)
@@ -413,7 +415,7 @@ cairo_type1_font_subset_get_glyph_names_
 
     /* Get glyph names and width using the freetype API */
     for (i = 0; i < font->base.num_glyphs; i++) {
-	if (!font->glyph_set[i])
+	if (font->glyph_set[i] < 0)
 	    continue;
 	if (font->glyph_names[i] != NULL)
 	    continue;
@@ -609,8 +611,8 @@ cairo_type1_font_subset_look_for_seac(ca
 		    break;
 		}
 
-		font->glyph_set[last_int] = 1;
-		font->glyph_set[current_int] = 1;
+		cairo_type1_font_subset_use_glyph (font, last_int);
+		cairo_type1_font_subset_use_glyph (font, current_int);
 		break;
 
 	    case TYPE1_CHARSTRING_COMMAND_CALLOTHERSUBR:
@@ -725,7 +727,7 @@ cairo_type1_font_subset_write_private_di
     const char *p, *charstrings, *dict_start;
     const char *closefile_token;
     char buffer[32], *glyph_count_end;
-    int num_charstrings, length, i;
+    int num_charstrings, length;
 
     /* The private dict holds hint information, common subroutines and
      * the actual glyph definitions (charstrings).  
@@ -749,6 +751,7 @@ cairo_type1_font_subset_write_private_di
 	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) {
@@ -801,13 +804,9 @@ cairo_type1_font_subset_write_private_di
     cairo_type1_font_subset_write_encrypted (font, font->cleartext,
 					     charstrings - font->cleartext);
 
-    num_charstrings = 0;
-    for (i = 0; i < font->base.num_glyphs; i++)
-	num_charstrings += font->glyph_set[i];
-
     /* Write out new charstring count */
     length = snprintf (buffer, sizeof buffer,
-		       "/CharStrings %d", num_charstrings + 50);
+		       "/CharStrings %d", font->num_glyphs);
     cairo_type1_font_subset_write_encrypted (font, buffer, length);
 
     /* Write out text between the charstring count and the first
@@ -997,6 +996,9 @@ _cairo_type1_subset_init (cairo_type1_su
 	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;
diff-tree 5f55ae7d91174d29f83b2a15e4def0f6baea7344 (from fe58e7a81fe9f787ef262615bc1802243770a432)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Thu May 18 13:57:03 2006 -0400

    Make ps surface use type1 subset code.
    
    - Add _cairo_ps_surface_emit_type1_font_subset() which just dumps the
      type1 subset into the ps document.
    - Add a 'name' parameter to _cairo_type1_subset_init() so it will be
      defined under the right name in the ps document.
    - Quiet down debug output from type1 subset code.
    - Reenable code to output custom /Encoding table.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 84f03ba..99eec3d 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1674,8 +1674,11 @@ _cairo_pdf_surface_emit_type1_font_subse
     unsigned long length, compressed_length;
     char *compressed;
     int i;
+    char name[64];
 
-    status = _cairo_type1_subset_init (&subset, font_subset);
+    snprintf (name, sizeof name, "CairoFont-%d-%d",
+	      font_subset->font_id, font_subset->subset_id);
+    status = _cairo_type1_subset_init (&subset, name, font_subset);
     if (status)
 	return status;
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index fc66048..1506909 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -345,6 +345,36 @@ _cairo_ps_surface_emit_header (cairo_ps_
 }
 
 static cairo_status_t
+_cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t		*surface,
+					  cairo_scaled_font_subset_t	*font_subset)
+
+
+{
+    cairo_type1_subset_t subset;
+    cairo_status_t status;
+    int length;
+    char name[64];
+
+    snprintf (name, sizeof name, "CairoFont-%d-%d",
+	      font_subset->font_id, font_subset->subset_id);
+    status = _cairo_type1_subset_init (&subset, name, font_subset);
+    if (status)
+	return status;
+
+    /* FIXME: Figure out document structure convention for fonts */
+
+    _cairo_output_stream_printf (surface->final_stream,
+				 "%% _cairo_ps_surface_emit_type1_font_subset\n");
+
+    length = subset.header_length + subset.data_length + subset.trailer_length;
+    _cairo_output_stream_write (surface->final_stream, subset.data, length);
+
+    _cairo_type1_subset_fini (&subset);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t		*surface,
 					     cairo_scaled_font_subset_t	*font_subset)
 
@@ -518,6 +548,10 @@ _cairo_ps_surface_emit_font_subset (cair
     cairo_ps_surface_t *surface = closure;
     cairo_status_t status;
 
+    status = _cairo_ps_surface_emit_type1_font_subset (surface, font_subset);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return;
+
     status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index cd1b086..6dcf273 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -250,6 +250,7 @@ typedef struct _cairo_type1_subset {
  **/
 cairo_private cairo_status_t
 _cairo_type1_subset_init (cairo_type1_subset_t		*type_subset,
+			  const char			*name,
 			  cairo_scaled_font_subset_t	*font_subset);
 
 /**
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 4421fba..3cff501 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -134,11 +134,11 @@ _cairo_type1_font_subset_create (cairo_u
     }
     font->base.base_font[i] = '\0';
 
-    printf ("allocating glyph_set of size %ld\n", face->num_glyphs);
     font->glyph_set = calloc (face->num_glyphs, sizeof (char));
     if (font->glyph_set == NULL)
 	goto fail2;
 
+    /* Add .notdef glyph */
     font->glyph_set[0] = 1;
 
     _cairo_array_init (&font->contents, sizeof (char));
@@ -235,6 +235,7 @@ cairo_type1_font_subset_write_header (ca
 					 const char *name)
 {
     const char *start, *end, *segment_end;
+    int i, j;
 
     segment_end = font->header_segment + font->header_segment_size;
 
@@ -252,7 +253,6 @@ cairo_type1_font_subset_write_header (ca
 	return font->status = CAIRO_INT_STATUS_UNSUPPORTED;
     end += 3;
 
-#if 0
     start = find_token (end, segment_end, "/Encoding");
     if (start == NULL)
 	return font->status = CAIRO_INT_STATUS_UNSUPPORTED;
@@ -261,11 +261,12 @@ cairo_type1_font_subset_write_header (ca
     _cairo_output_stream_printf (font->output,
 				 "/Encoding 256 array\n"
 				 "0 1 255 {1 index exch /.notdef put} for\n");
-    for (i = 1; i < font->base.num_glyphs; i++) {
+    for (i = 1, j = 0; i < font->base.num_glyphs; i++) {
 	if (!font->glyph_set[i])
 	    continue;
 	_cairo_output_stream_printf (font->output, "dup %d /%s put\n",
-				     i, font->glyph_names[i]);
+				     j, font->glyph_names[i]);
+	j++;
     }
     _cairo_output_stream_printf (font->output, "readonly def");
 
@@ -273,7 +274,6 @@ cairo_type1_font_subset_write_header (ca
     if (end == NULL)
 	return font->status = CAIRO_INT_STATUS_UNSUPPORTED;
     end += 3;
-#endif
 
     _cairo_output_stream_write (font->output, end, segment_end - end);
 
@@ -479,6 +479,7 @@ cairo_type1_font_subset_decode_integer (
     return p;
 }
 
+#ifdef DEBUG_GLYPH_COMMANDS
 typedef struct _charstring_command charstring_command_t;
 struct _charstring_command {
     const char *name;
@@ -546,6 +547,7 @@ get_command_name (int command)
     sprintf (buffer, "<invalid %d>", command);
     return buffer;
 }
+#endif
 
 #define TYPE1_CHARSTRING_COMMAND_RLINETO	(5)
 #define TYPE1_CHARSTRING_COMMAND_HLINETO	(6)
@@ -584,6 +586,8 @@ cairo_type1_font_subset_look_for_seac(ca
 						charstring);
     end = charstring + encrypted_charstring_length;
     p = charstring + 4;
+    current_int = -1;
+    last_int = -1;
     count = 0;
     while (p < end) {
         if (*p < 32) {
@@ -591,13 +595,17 @@ cairo_type1_font_subset_look_for_seac(ca
 	    if (command == 12)
 		command = 32 + *p++;
 
+#ifdef DEBUG_GLYPH_COMMANDS
 	    printf ("%s ", get_command_name(command));
+#endif
 
 	    switch (command) {
 	    case TYPE1_CHARSTRING_COMMAND_SEAC:
 		if (last_int >= font->base.num_glyphs ||
 		    current_int >= font->base.num_glyphs) {
+#ifdef DEBUG_GLYPH_COMMANDS
 		    printf ("*** composite glyph out of bounds\n");
+#endif
 		    break;
 		}
 
@@ -616,11 +624,15 @@ cairo_type1_font_subset_look_for_seac(ca
             last_int = current_int;
             p = cairo_type1_font_subset_decode_integer (p, &current_int);
 
+#ifdef DEBUG_GLYPH_COMMANDS
 	    printf ("%d ", current_int);
+#endif
         }
     }
 
+#ifdef DEBUG_GLYPH_COMMANDS
     printf ("\n");
+#endif
 
     free (charstring);
 }
@@ -814,6 +826,7 @@ cairo_type1_font_subset_write_private_di
      * 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;
 }
@@ -960,6 +973,7 @@ cairo_type1_font_subset_destroy (void *a
 
 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;
@@ -983,7 +997,7 @@ _cairo_type1_subset_init (cairo_type1_su
 	cairo_type1_font_subset_use_glyph (font, parent_glyph);
     }
 
-    status = cairo_type1_font_subset_generate (font, "Bobby");
+    status = cairo_type1_font_subset_generate (font, name);
     if (status)
 	goto fail1;
 
diff-tree fe58e7a81fe9f787ef262615bc1802243770a432 (from 2fafbac390f13c8c47464defc8c30e705be98bbb)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Thu May 18 13:35:57 2006 -0400

    Only use the word wrap stream when emitting paths.
    
    This patch also factors the word wrap stream setup and teardown
    and the call to _cairo_path_fixed_interpret() out into a new function,
    _cairo_ps_surface_emit_path().

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index eaf4924..fc66048 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -87,6 +87,117 @@ typedef struct cairo_ps_surface {
 #define PS_SURFACE_DPI_DEFAULT		300.0
 #define PS_SURFACE_MAX_GLYPHS_PER_FONT	256
 
+/* A word wrap stream can be used as a filter to do word wrapping on
+ * top of an existing output stream. The word wrapping is quite
+ * simple, using isspace to determine characters that separate
+ * words. Any word that will cause the column count exceeed the given
+ * max_column will have a '\n' character emitted before it.
+ *
+ * The stream is careful to maintain integrity for words that cross
+ * the boundary from one call to write to the next.
+ *
+ * Note: This stream does not guarantee that the output will never
+ * exceed max_column. In particular, if a single word is larger than
+ * max_column it will not be broken up.
+ */
+typedef struct _word_wrap_stream {
+    cairo_output_stream_t *output;
+    int max_column;
+    int column;
+    cairo_bool_t last_write_was_space;
+} word_wrap_stream_t;
+
+static int
+_count_word_up_to (const unsigned char *s, int length)
+{
+    int word = 0;
+
+    while (length--) {
+	if (! isspace (*s++))
+	    word++;
+	else
+	    return word;
+    }
+
+    return word;
+}
+
+static cairo_status_t
+_word_wrap_stream_write (void			*closure,
+			 const unsigned char	*data,
+			 unsigned int		 length)
+{
+    word_wrap_stream_t *stream = closure;
+    cairo_bool_t newline;
+    int word;
+
+    while (length) {
+	if (isspace (*data)) {
+	    newline =  (*data == '\n' || *data == '\r');
+	    if (! newline && stream->column >= stream->max_column) {
+		_cairo_output_stream_printf (stream->output, "\n");
+		stream->column = 0;
+	    }
+	    _cairo_output_stream_write (stream->output, data, 1);
+	    data++;
+	    length--;
+	    if (newline)
+		stream->column = 0;
+	    else
+		stream->column++;
+	    stream->last_write_was_space = TRUE;
+	} else {
+	    word = _count_word_up_to (data, length);
+	    /* Don't wrap if this word is a continuation of a word
+	     * from a previous call to write. */
+	    if (stream->column + word >= stream->max_column &&
+		stream->last_write_was_space)
+	    {
+		_cairo_output_stream_printf (stream->output, "\n");
+		stream->column = 0;
+	    }
+	    _cairo_output_stream_write (stream->output, data, word);
+	    data += word;
+	    length -= word;
+	    stream->column += word;
+	    stream->last_write_was_space = FALSE;
+	}
+    }
+
+    return _cairo_output_stream_get_status (stream->output);
+}
+
+static cairo_status_t
+_word_wrap_stream_close (void *closure)
+{
+    cairo_status_t status;
+    word_wrap_stream_t *stream = closure;
+
+    status = _cairo_output_stream_get_status (stream->output);
+
+    free (stream);
+
+    return status;
+}
+
+static cairo_output_stream_t *
+_word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
+{
+    word_wrap_stream_t *stream;
+
+    stream = malloc (sizeof (word_wrap_stream_t));
+    if (stream == NULL)
+	return (cairo_output_stream_t *) &cairo_output_stream_nil;
+
+    stream->output = output;
+    stream->max_column = max_column;
+    stream->column = 0;
+    stream->last_write_was_space = FALSE;
+
+    return _cairo_output_stream_create (_word_wrap_stream_write,
+					_word_wrap_stream_close, stream);
+}
+
 static cairo_status_t
 _cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
 {
@@ -144,6 +255,28 @@ _cairo_ps_surface_path_close_path (void 
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+_cairo_ps_surface_emit_path (cairo_output_stream_t *stream,
+			     cairo_path_fixed_t    *path)
+{
+    cairo_output_stream_t *word_wrap;
+    cairo_status_t status;
+
+    word_wrap = _word_wrap_stream_create (stream, 79);
+
+    status = _cairo_path_fixed_interpret (path,
+					  CAIRO_DIRECTION_FORWARD,
+					  _cairo_ps_surface_path_move_to,
+					  _cairo_ps_surface_path_line_to,
+					  _cairo_ps_surface_path_curve_to,
+					  _cairo_ps_surface_path_close_path,
+					  word_wrap);
+
+    _cairo_output_stream_destroy (word_wrap);
+
+    return status;
+}
+
 static void
 _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
 {
@@ -319,13 +452,9 @@ _cairo_ps_surface_emit_glyph (cairo_ps_s
 				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
 				 -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
     
-    status = _cairo_path_fixed_interpret (scaled_glyph->path,
-					  CAIRO_DIRECTION_FORWARD,
-					  _cairo_ps_surface_path_move_to,
-					  _cairo_ps_surface_path_line_to,
-					  _cairo_ps_surface_path_curve_to,
-					  _cairo_ps_surface_path_close_path,
-					  surface->final_stream);
+    status = _cairo_ps_surface_emit_path (surface->final_stream,
+					  scaled_glyph->path);
+					  
     
     _cairo_output_stream_printf (surface->final_stream,
 				 "F\n");
@@ -870,117 +999,6 @@ cairo_ps_surface_dsc_begin_page_setup (c
     }
 }
 
-/* A word wrap stream can be used as a filter to do word wrapping on
- * top of an existing output stream. The word wrapping is quite
- * simple, using isspace to determine characters that separate
- * words. Any word that will cause the column count exceeed the given
- * max_column will have a '\n' character emitted before it.
- *
- * The stream is careful to maintain integrity for words that cross
- * the boundary from one call to write to the next.
- *
- * Note: This stream does not guarantee that the output will never
- * exceed max_column. In particular, if a single word is larger than
- * max_column it will not be broken up.
- */
-typedef struct _word_wrap_stream {
-    cairo_output_stream_t *output;
-    int max_column;
-    int column;
-    cairo_bool_t last_write_was_space;
-} word_wrap_stream_t;
-
-static int
-_count_word_up_to (const unsigned char *s, int length)
-{
-    int word = 0;
-
-    while (length--) {
-	if (! isspace (*s++))
-	    word++;
-	else
-	    return word;
-    }
-
-    return word;
-}
-
-static cairo_status_t
-_word_wrap_stream_write (void			*closure,
-			 const unsigned char	*data,
-			 unsigned int		 length)
-{
-    word_wrap_stream_t *stream = closure;
-    cairo_bool_t newline;
-    int word;
-
-    while (length) {
-	if (isspace (*data)) {
-	    newline =  (*data == '\n' || *data == '\r');
-	    if (! newline && stream->column >= stream->max_column) {
-		_cairo_output_stream_printf (stream->output, "\n");
-		stream->column = 0;
-	    }
-	    _cairo_output_stream_write (stream->output, data, 1);
-	    data++;
-	    length--;
-	    if (newline)
-		stream->column = 0;
-	    else
-		stream->column++;
-	    stream->last_write_was_space = TRUE;
-	} else {
-	    word = _count_word_up_to (data, length);
-	    /* Don't wrap if this word is a continuation of a word
-	     * from a previous call to write. */
-	    if (stream->column + word >= stream->max_column &&
-		stream->last_write_was_space)
-	    {
-		_cairo_output_stream_printf (stream->output, "\n");
-		stream->column = 0;
-	    }
-	    _cairo_output_stream_write (stream->output, data, word);
-	    data += word;
-	    length -= word;
-	    stream->column += word;
-	    stream->last_write_was_space = FALSE;
-	}
-    }
-
-    return _cairo_output_stream_get_status (stream->output);
-}
-
-static cairo_status_t
-_word_wrap_stream_close (void *closure)
-{
-    cairo_status_t status;
-    word_wrap_stream_t *stream = closure;
-
-    status = _cairo_output_stream_get_status (stream->output);
-
-    free (stream);
-
-    return status;
-}
-
-static cairo_output_stream_t *
-_word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
-{
-    word_wrap_stream_t *stream;
-
-    stream = malloc (sizeof (word_wrap_stream_t));
-    if (stream == NULL)
-	return (cairo_output_stream_t *) &cairo_output_stream_nil;
-
-    stream->output = output;
-    stream->max_column = max_column;
-    stream->column = 0;
-    stream->last_write_was_space = FALSE;
-
-    return _cairo_output_stream_create (_word_wrap_stream_write,
-					_word_wrap_stream_close, stream);
-}
-
 static cairo_surface_t *
 _cairo_ps_surface_create_similar (void		       *abstract_src,
 				   cairo_content_t	content,
@@ -999,16 +1017,13 @@ _cairo_ps_surface_finish (void *abstract
 {
     cairo_status_t status;
     cairo_ps_surface_t *surface = abstract_surface;
-    cairo_output_stream_t *final_stream, *word_wrap;
+    cairo_output_stream_t *final_stream;
     int i, num_comments;
     char **comments;
 
     /* Save final_stream to be restored later. */
     final_stream = surface->final_stream;
 
-    word_wrap = _word_wrap_stream_create (final_stream, 79);
-    surface->final_stream = word_wrap;
-   
     _cairo_ps_surface_emit_header (surface);
     
     _cairo_ps_surface_emit_font_subsets (surface);
@@ -1023,10 +1038,6 @@ _cairo_ps_surface_finish (void *abstract
 
     fclose (surface->tmpfile);
 
-    /* Restore final stream before final cleanup. */
-    _cairo_output_stream_destroy (word_wrap);
-    surface->final_stream = final_stream;
-
     _cairo_output_stream_close (surface->final_stream);
     if (status == CAIRO_STATUS_SUCCESS)
 	status = _cairo_output_stream_get_status (surface->final_stream);
@@ -1568,13 +1579,7 @@ _cairo_ps_surface_intersect_clip_path (v
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    status = _cairo_path_fixed_interpret (path,
-					  CAIRO_DIRECTION_FORWARD,
-					  _cairo_ps_surface_path_move_to,
-					  _cairo_ps_surface_path_line_to,
-					  _cairo_ps_surface_path_curve_to,
-					  _cairo_ps_surface_path_close_path,
-					  stream);
+    status = _cairo_ps_surface_emit_path (stream, path);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
@@ -1717,13 +1722,7 @@ _cairo_ps_surface_stroke (void			*abstra
 
     _cairo_output_stream_printf (stream,
 				 "gsave\n");
-    status = _cairo_path_fixed_interpret (path,
-					  CAIRO_DIRECTION_FORWARD,
-					  _cairo_ps_surface_path_move_to,
-					  _cairo_ps_surface_path_line_to,
-					  _cairo_ps_surface_path_curve_to,
-					  _cairo_ps_surface_path_close_path,
-					  stream);
+    status = _cairo_ps_surface_emit_path (stream, path);
 
     /*
      * Switch to user space to set line parameters
@@ -1783,13 +1782,7 @@ _cairo_ps_surface_fill (void		*abstract_
 
     emit_pattern (surface, source);
 
-    status = _cairo_path_fixed_interpret (path,
-					  CAIRO_DIRECTION_FORWARD,
-					  _cairo_ps_surface_path_move_to,
-					  _cairo_ps_surface_path_line_to,
-					  _cairo_ps_surface_path_curve_to,
-					  _cairo_ps_surface_path_close_path,
-					  stream);
+    status = _cairo_ps_surface_emit_path (stream, path);
 
     switch (fill_rule) {
     case CAIRO_FILL_RULE_WINDING:
diff-tree 2fafbac390f13c8c47464defc8c30e705be98bbb (from 466d3da4ef2267287095e67342da8eb360198542)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Thu May 18 02:24:02 2006 -0400

    Use RD and ND for delimiting glyph data instead of -| and |-.
    
    We probably should figure out from the private dictionary which of the two
    pairs the font defines and uses, but I don't actually have fonts that
    use -| and |-, so for now for flip the default.

diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 709a8ff..4421fba 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -634,11 +634,11 @@ write_used_glyphs (cairo_type1_font_subs
     int length;
 
     length = snprintf (buffer, sizeof buffer,
-		       "/%.*s %d -| ", name_length, name, charstring_length);
+		       "/%.*s %d RD ", name_length, name, charstring_length);
     cairo_type1_font_subset_write_encrypted (font, buffer, length);
     cairo_type1_font_subset_write_encrypted (font,
 					     charstring, charstring_length);
-    cairo_type1_font_subset_write_encrypted (font, " |-\n", 4);
+    cairo_type1_font_subset_write_encrypted (font, "ND\n", 4);
 }
 
 typedef void (*glyph_func_t) (cairo_type1_font_subset_t *font,
diff-tree 466d3da4ef2267287095e67342da8eb360198542 (from c36de5b7c5173639712074d0f98365b107707ae7)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Wed May 17 17:17:02 2006 -0400

    Add code to emit type1 dicts to the pdf backend.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 3ab2d89..84f03ba 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1664,6 +1664,112 @@ _cairo_pdf_surface_write_pages (cairo_pd
 }
 
 static cairo_status_t
+_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t		*surface,
+					   cairo_scaled_font_subset_t	*font_subset)
+{
+    cairo_pdf_resource_t stream, descriptor, subset_resource;
+    cairo_status_t status;
+    cairo_pdf_font_t font;
+    cairo_type1_subset_t subset;
+    unsigned long length, compressed_length;
+    char *compressed;
+    int i;
+
+    status = _cairo_type1_subset_init (&subset, font_subset);
+    if (status)
+	return status;
+
+    /* We ignore the zero-trailer and set Length3 to 0. */
+    length = subset.header_length + subset.data_length;
+    compressed = compress_dup (subset.data, length, &compressed_length);
+    if (compressed == NULL) {
+	_cairo_type1_subset_fini (&subset);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
+    stream = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Filter /FlateDecode\r\n"
+				 "   /Length %lu\r\n"
+				 "   /Length1 %lu\r\n"
+				 "   /Length2 %lu\r\n"
+				 "   /Length3 0\r\n"
+				 ">>\r\n"
+				 "stream\r\n",
+				 stream.id,
+				 compressed_length,
+				 subset.header_length,
+				 subset.data_length);
+    _cairo_output_stream_write (surface->output, compressed, compressed_length);
+    _cairo_output_stream_printf (surface->output,
+				 "\r\n"
+				 "endstream\r\n"
+				 "endobj\r\n");
+    free (compressed);
+
+    descriptor = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /FontDescriptor\r\n"
+				 "   /FontName /%s\r\n"
+				 "   /Flags 4\r\n"
+				 "   /FontBBox [ %ld %ld %ld %ld ]\r\n"
+				 "   /ItalicAngle 0\r\n"
+				 "   /Ascent %ld\r\n"
+				 "   /Descent %ld\r\n"
+				 "   /CapHeight 500\r\n"
+				 "   /StemV 80\r\n"
+				 "   /StemH 80\r\n"
+				 "   /FontFile %u 0 R\r\n"
+				 ">>\r\n"
+				 "endobj\r\n",
+				 descriptor.id,
+				 subset.base_font,
+				 subset.x_min,
+				 subset.y_min,
+				 subset.x_max,
+				 subset.y_max,
+				 subset.ascent,
+				 subset.descent,
+				 stream.id);
+
+    subset_resource = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /Font\r\n"
+				 "   /Subtype /Type1\r\n"
+				 "   /BaseFont /%s\r\n"
+				 "   /FirstChar 0\r\n"
+				 "   /LastChar %d\r\n"
+				 "   /FontDescriptor %d 0 R\r\n"
+				 "   /Widths [",
+				 subset_resource.id,
+				 subset.base_font,
+				 font_subset->num_glyphs,
+				 descriptor.id);
+
+    for (i = 0; i < font_subset->num_glyphs; i++)
+	_cairo_output_stream_printf (surface->output,
+				     " %d",
+				     subset.widths[i]);
+
+    _cairo_output_stream_printf (surface->output,
+				 " ]\r\n"
+				 ">>\r\n"
+				 "endobj\r\n");
+
+    font.font_id = font_subset->font_id;
+    font.subset_id = font_subset->subset_id;
+    font.subset_resource = subset_resource;
+    _cairo_array_append (&surface->fonts, &font);
+
+    _cairo_type1_subset_fini (&subset);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
 					      cairo_scaled_font_subset_t	*font_subset)
 {
@@ -1919,6 +2025,10 @@ _cairo_pdf_surface_emit_font_subset (cai
     cairo_pdf_surface_t *surface = closure;
     cairo_status_t status;
 
+    status = _cairo_pdf_surface_emit_type1_font_subset (surface, font_subset);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return;
+
     status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	return;
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index 23e1531..cd1b086 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -228,7 +228,9 @@ typedef struct _cairo_type1_subset {
     long x_min, y_min, x_max, y_max;
     long ascent, descent;
     char *data;
+    unsigned long header_length;
     unsigned long data_length;
+    unsigned long trailer_length;
 } cairo_type1_subset_t;
 
 /**
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 47dbec9..709a8ff 100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -978,8 +978,8 @@ _cairo_type1_subset_init (cairo_type1_su
     if (status)
 	return status;
 
-    for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
-	parent_glyph = font->scaled_font_subset->glyphs[i];
+    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);
     }
 
@@ -1004,14 +1004,18 @@ _cairo_type1_subset_init (cairo_type1_su
     type1_subset->ascent = font->base.ascent;
     type1_subset->descent = font->base.descent;
 
-    length = font->contents.num_elements;
+    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->data_length = 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;
 
     return CAIRO_STATUS_SUCCESS;
 
diff-tree c36de5b7c5173639712074d0f98365b107707ae7 (from 127fab4695ef849364e755e10c2b960add78782b)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Wed May 17 12:05:16 2006 -0400

    Pull in type1 subset code from the cvs repo it was sitting in.

diff --git a/src/Makefile.am b/src/Makefile.am
index bf1068a..2ff83db 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,7 @@
 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
 
diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c
index ef0a225..f6169e2 100644
--- a/src/cairo-font-subset.c
+++ b/src/cairo-font-subset.c
@@ -34,7 +34,6 @@
  */
 
 #include "cairoint.h"
-#include "cairo-font-subset-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 
 /* XXX: Eventually, we need to handle other font backends */
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index a0b0dbc..23e1531 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -220,4 +220,45 @@ _cairo_truetype_subset_init (cairo_truet
 cairo_private void
 _cairo_truetype_subset_fini (cairo_truetype_subset_t *truetype_subset);
 
+
+
+typedef struct _cairo_type1_subset {
+    char *base_font;
+    int *widths;
+    long x_min, y_min, x_max, y_max;
+    long ascent, descent;
+    char *data;
+    unsigned long data_length;
+} cairo_type1_subset_t;
+
+/**
+ * _cairo_type1_subset_init:
+ * @type1_subset: a #cairo_type1_subset_t to initialize
+ * @font_subset: the #cairo_scaled_font_subset_t to initialize from
+ *
+ * If possible (depending on the format of the underlying
+ * cairo_scaled_font_t and the font backend in use) generate a type1
+ * file corresponding to @font_subset and initialize @type1_subset
+ * with information about the subset and the type1 data.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if successful,
+ * CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type1
+ * file, or an non-zero value indicating an error.  Possible errors
+ * include CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_status_t
+_cairo_type1_subset_init (cairo_type1_subset_t		*type_subset,
+			  cairo_scaled_font_subset_t	*font_subset);
+
+/**
+ * _cairo_type1_subset_fini:
+ * @type1_subset: a #cairo_type1_subset_t
+ *
+ * Free all resources associated with @type1_subset.  After this call,
+ * @type1_subset should not be used again without a subsequent call to
+ * _cairo_truetype_type1_init() again first.
+ **/
+cairo_private void
+_cairo_type1_subset_fini (cairo_type1_subset_t *subset);
+
 #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
new file mode 100644
index 0000000..47dbec9
--- /dev/null
+++ b/src/cairo-type1-subset.c
@@ -0,0 +1,1035 @@
+/* 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 at 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_TYPE1_TABLES_H
+
+typedef 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;
+	int *widths;
+	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;
+    char *glyph_set;
+    char **glyph_names;
+
+    cairo_output_stream_t *output;
+    cairo_array_t contents;
+
+    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';
+
+    printf ("allocating glyph_set of size %ld\n", face->num_glyphs);
+    font->glyph_set = calloc (face->num_glyphs, sizeof (char));
+    if (font->glyph_set == NULL)
+	goto fail2;
+
+    font->glyph_set[0] = 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 int
+cairo_type1_font_subset_use_glyph (void *abstract_font, int glyph)
+{
+    cairo_type1_font_subset_t *font = abstract_font;
+
+    font->glyph_set[glyph] = 1;
+
+    return glyph;
+}
+
+/* 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 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 || isspace(buffer[i - 1])) &&
+		(buffer + i == end - length || isspace(buffer[i + length])))
+		return buffer + i;
+
+    return NULL;
+}
+
+static cairo_status_t
+cairo_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_t
+cairo_type1_font_subset_write_header (cairo_type1_font_subset_t *font,
+					 const char *name)
+{
+    const char *start, *end, *segment_end;
+
+    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;
+
+#if 0
+    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 = 1; i < font->base.num_glyphs; i++) {
+	if (!font->glyph_set[i])
+	    continue;
+	_cairo_output_stream_printf (font->output, "dup %d /%s put\n",
+				     i, font->glyph_names[i]);
+    }
+    _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;
+#endif
+
+    _cairo_output_stream_write (font->output, end, segment_end - end);
+
+    return font->status;
+}
+
+static int
+hex_to_int (int ch)
+{
+    if (ch <= '9')
+	return ch - '0';
+    else if (ch <= 'F')
+	return ch - 'A' + 10;
+    else
+	return ch - 'a' + 10;
+}
+
+static void
+cairo_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_t
+cairo_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 cairo_bool_t
+cairo_type1_font_subset_contains_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->glyph_set[i])
+	    continue;
+	if (font->glyph_names[i] &&
+	    strncmp (font->glyph_names[i], glyph_name, length) == 0)
+	    return TRUE;
+    }
+
+    return FALSE;
+}
+
+static cairo_status_t
+cairo_type1_font_subset_get_glyph_names_and_widths (cairo_type1_font_subset_t *font)
+{
+    int i;
+    char buffer[256];
+    FT_Error error;
+
+    if (font->glyph_names == NULL) {
+	font->glyph_names = calloc (font->base.num_glyphs, sizeof (char *));
+	if (font->glyph_names == NULL)
+	    return font->status = CAIRO_STATUS_NO_MEMORY;
+	
+	font->base.widths = calloc (font->face->num_glyphs, sizeof (int));
+	if (font->base.widths == NULL)
+	    return font->status = CAIRO_STATUS_NO_MEMORY;
+    }
+
+    /* Get glyph names and width using the freetype API */
+    for (i = 0; i < font->base.num_glyphs; i++) {
+	if (!font->glyph_set[i])
+	    continue;
+	if (font->glyph_names[i] != 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->base.widths[i] = 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->glyph_names[i] = strdup (buffer);
+	if (font->glyph_names[i] == NULL)
+	    return font->status = CAIRO_STATUS_NO_MEMORY;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+cairo_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;
+}
+
+typedef struct _charstring_command charstring_command_t;
+struct _charstring_command {
+    const char *name;
+    int args;
+};
+
+charstring_command_t charstring_commands[] = {
+    {},				/* 0 */
+    { "hstem", 2 },
+    {},
+    { "vstem", 2 },
+    { "vmoveto", 1 },
+    { "rlineto", 2 },		/* 5 */
+    { "hlineto", 1 },
+    { "vlineto", 1 },
+    { "rcurveto", 6 },
+    { "closepath", 0 },
+    { "callsubr", 0 },		/* 10 */
+    { "return", 0 },
+    {},
+    { "hsbw", 2 },
+    { "endchar", 0 },
+    {}, {}, {}, {}, {},		/* 15 */
+    {},				/* 20 */
+    { "rmoveto", 2 },
+    { "hmoveto", 1 },
+    {}, {},
+    {}, {}, {}, {}, {},		/* 25 */
+    { "vhcurveto", 4 },		/* 30 */
+    { "hvcurveto", 4 },
+
+    /* two byte codes */
+    { "dotsection", 0 },	/* 0 */
+    { "vstem3", 6 },
+    { "hstem3", 6 },
+    {}, {},
+    {},				/* 5 */
+    { "seac", 5 },
+    { "sbw", 4 },
+    {}, {},
+    {}, {},			/* 10 */
+    { "div", 2 },
+    {}, {},
+    {},				/* 15 */
+    { "callothersubr", 0 },
+    { "pop", 0 },
+    {}, {},
+    {}, {}, {}, {}, {},		/* 20 */
+    {}, {}, {}, {}, {},		/* 25 */
+    {}, {}, {}, 		/* 30 */
+    { "setcurrentpoint", 2 }
+};
+
+static const char *
+get_command_name (int command)
+{
+    static char buffer[100];
+
+    int num_commands = sizeof (charstring_commands) / sizeof (charstring_commands[0]);
+
+    if (command >= 0 && command < num_commands &&
+	charstring_commands[command].name != NULL)
+	return charstring_commands[command].name;
+
+    sprintf (buffer, "<invalid %d>", command);
+    return buffer;
+}
+
+#define TYPE1_CHARSTRING_COMMAND_RLINETO	(5)
+#define TYPE1_CHARSTRING_COMMAND_HLINETO	(6)
+#define TYPE1_CHARSTRING_COMMAND_CLOSEPATH	(9)
+#define TYPE1_CHARSTRING_COMMAND_CALLSUBR	(10)
+#define TYPE1_CHARSTRING_COMMAND_HSBW		(13)
+#define TYPE1_CHARSTRING_COMMAND_ENDCHAR	(14)
+#define TYPE1_CHARSTRING_COMMAND_HMOVETO	(22)
+#define TYPE1_CHARSTRING_COMMAND_HVCURVETO	(31)
+
+#define TYPE1_CHARSTRING_COMMAND_SEAC		(32 + 6)
+#define TYPE1_CHARSTRING_COMMAND_SBW		(32 + 7)
+#define TYPE1_CHARSTRING_COMMAND_DIV		(32 + 12)
+#define TYPE1_CHARSTRING_COMMAND_CALLOTHERSUBR	(32 + 16)
+#define TYPE1_CHARSTRING_COMMAND_POP		(32 + 17)
+
+static void
+cairo_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 current_int;
+    int last_int;
+    int command;
+    int count;
+
+    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;
+    count = 0;
+    while (p < end) {
+        if (*p < 32) {
+	    command = *p++;
+	    if (command == 12)
+		command = 32 + *p++;
+
+	    printf ("%s ", get_command_name(command));
+
+	    switch (command) {
+	    case TYPE1_CHARSTRING_COMMAND_SEAC:
+		if (last_int >= font->base.num_glyphs ||
+		    current_int >= font->base.num_glyphs) {
+		    printf ("*** composite glyph out of bounds\n");
+		    break;
+		}
+
+		font->glyph_set[last_int] = 1;
+		font->glyph_set[current_int] = 1;
+		break;
+
+	    case TYPE1_CHARSTRING_COMMAND_CALLOTHERSUBR:
+		break;
+	    case TYPE1_CHARSTRING_COMMAND_CALLSUBR:
+		break;
+	    }
+        } else {
+            /* integer argument */
+	    count++;
+            last_int = current_int;
+            p = cairo_type1_font_subset_decode_integer (p, &current_int);
+
+	    printf ("%d ", current_int);
+        }
+    }
+
+    printf ("\n");
+
+    free (charstring);
+}
+
+static void
+write_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 -| ", name_length, name, charstring_length);
+    cairo_type1_font_subset_write_encrypted (font, buffer, length);
+    cairo_type1_font_subset_write_encrypted (font,
+					     charstring, charstring_length);
+    cairo_type1_font_subset_write_encrypted (font, " |-\n", 4);
+}
+
+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;
+    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;
+	}
+
+	if (cairo_type1_font_subset_contains_glyph (font, name, name_length))
+	    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, i;
+
+    /* 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;
+    }
+
+    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);
+
+    num_charstrings = 0;
+    for (i = 0; i < font->base.num_glyphs; i++)
+	num_charstrings += font->glyph_set[i];
+
+    /* Write out new charstring count */
+    length = snprintf (buffer, sizeof buffer,
+		       "/CharStrings %d", num_charstrings + 50);
+    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);
+
+    return p;
+}
+
+static cairo_status_t
+cairo_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_t
+type1_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_t
+cairo_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;
+    
+    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_t
+cairo_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 void
+cairo_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->glyph_names != NULL)
+	for (i = 0; i < font->base.num_glyphs; i++)
+	    free (font->glyph_names[i]);
+
+    free (font->base.widths);
+    free (font->glyph_names);
+
+    _cairo_unscaled_font_destroy (font->base.unscaled_font);
+
+    free (font->base.base_font);
+    free (font->glyph_set);
+    free (font);
+}
+
+
+cairo_status_t
+_cairo_type1_subset_init (cairo_type1_subset_t		*type1_subset,
+			  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 < font->scaled_font_subset->num_glyphs; i++) {
+	parent_glyph = font->scaled_font_subset->glyphs[i];
+	cairo_type1_font_subset_use_glyph (font, parent_glyph);
+    }
+
+    status = cairo_type1_font_subset_generate (font, "Bobby");
+    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->base.num_glyphs);
+    if (type1_subset->widths == NULL)
+	goto fail2;
+    for (i = 0; i < font->base.num_glyphs; i++)
+	type1_subset->widths[i] = font->base.widths[i];
+
+    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->contents.num_elements;
+    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->data_length = length;
+
+    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);
+}
+
diff-tree 127fab4695ef849364e755e10c2b960add78782b (from b16c29ff0c38b8fa8e5753770bb93ad9ff084579)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Thu May 18 02:12:06 2006 -0400

    Remember to call _cairo_truetype_subset_fini() after outputting subset.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index f92da83..eaf4924 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -249,7 +249,7 @@ _cairo_ps_surface_emit_truetype_font_sub
 				     "Encoding %d /g%d put\n", i, i);
 
     _cairo_output_stream_printf (surface->final_stream,
-				  "/CharStrings %d dict dup begin\n"
+				 "/CharStrings %d dict dup begin\n"
 				 "/.notdef 0 def\n",
 				 font_subset->num_glyphs);
 
@@ -270,9 +270,11 @@ _cairo_ps_surface_emit_truetype_font_sub
 					   subset.data, subset.data_length);
 
     _cairo_output_stream_printf (surface->final_stream,
-				  ">] def\n"
+				 ">] def\n"
 				 "FontName currentdict end definefont pop\n");
 
+    _cairo_truetype_subset_fini (&subset);
+
     return CAIRO_STATUS_SUCCESS;
 }
 
diff-tree b16c29ff0c38b8fa8e5753770bb93ad9ff084579 (from d42b2c7a89451e95e6e9ec6bc439f06855c66802)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Wed May 17 01:30:43 2006 -0400

    Set libcairo_font_subset_sources for ps, pdf, and svg backends.
    
    Backends that use the font subsetting code should add the font subsetting
    sources to the build.  This is dont by setting libcairo_font_subset_sources,
    in the conditional section for each backend.  If any one is enabled, the
    sources will be added to the build.

diff --git a/src/Makefile.am b/src/Makefile.am
index 6390d32..bf1068a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,14 +1,19 @@
+font_subset_sources =				\
+	cairo-font-subset.c			\
+	cairo-font-subset-private.h		\
+	cairo-scaled-font-subsets.c		\
+	cairo-scaled-font-subsets-private.h
 
 if CAIRO_HAS_PS_SURFACE
 libcairo_ps_headers = cairo-ps.h
-libcairo_ps_sources = cairo-ps-surface.c cairo-scaled-font-subsets.c cairo-scaled-font-subsets-private.h
-libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h
+libcairo_ps_sources = cairo-ps-surface.c
+libcairo_font_subset_sources =	$(font_subset_sources)
 endif
 
 if CAIRO_HAS_PDF_SURFACE
 libcairo_pdf_headers = cairo-pdf.h
 libcairo_pdf_sources = cairo-pdf-surface.c
-libcairo_font_subset_sources = cairo-font-subset.c cairo-font-subset-private.h
+libcairo_font_subset_sources =	$(font_subset_sources)
 endif
 
 if CAIRO_HAS_PNG_FUNCTIONS
@@ -18,6 +23,7 @@ endif
 if CAIRO_HAS_SVG_SURFACE
 libcairo_svg_headers = cairo-svg.h
 libcairo_svg_sources = cairo-svg-surface.c
+libcairo_font_subset_sources =	$(font_subset_sources)
 endif
 
 if CAIRO_HAS_TEST_SURFACES
diff-tree d42b2c7a89451e95e6e9ec6bc439f06855c66802 (from f3209660c33bc128c58ec487c51440271f30a923)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Tue May 16 23:56:38 2006 -0400

    Remember to destroy cairo_pdf_ft_font_t once we've generated the subset.
    
    Also, remove cairo_private from function definitions.

diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c
index 6ff93e5..ef0a225 100644
--- a/src/cairo-font-subset.c
+++ b/src/cairo-font-subset.c
@@ -740,7 +740,7 @@ cairo_pdf_ft_font_use_glyph (cairo_pdf_f
     return font->parent_to_subset[glyph];
 }
 
-cairo_private cairo_status_t
+cairo_status_t
 _cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
 			     cairo_scaled_font_subset_t	*font_subset)
 {
@@ -787,6 +787,8 @@ _cairo_truetype_subset_init (cairo_truet
     memcpy (truetype_subset->data, data, length);
     truetype_subset->data_length = length;
 
+    cairo_pdf_ft_font_destroy (font);
+
     return CAIRO_STATUS_SUCCESS;
 
  fail3:
@@ -799,7 +801,7 @@ _cairo_truetype_subset_init (cairo_truet
     return status;
 }
 
-cairo_private void
+void
 _cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
 {
     free (subset->base_font);
diff-tree f3209660c33bc128c58ec487c51440271f30a923 (from 3975d7f8a26b53d4d2c7d587fbcfe9ed6ddf78d8)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Tue May 16 23:24:09 2006 -0400

    Print out ps comment in the truetype emit code and update type3 ps comment.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 4e718ac..f92da83 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -228,6 +228,9 @@ _cairo_ps_surface_emit_truetype_font_sub
     /* FIXME: Figure out document structure convention for fonts */
 
     _cairo_output_stream_printf (surface->final_stream,
+				 "%% _cairo_ps_surface_emit_truetype_font_subset\n");
+
+    _cairo_output_stream_printf (surface->final_stream,
 				 "11 dict begin\n"
 				 "/FontType 42 def\n"
 				 "/FontName /CairoFont-%d-%d def\n"
@@ -339,7 +342,7 @@ _cairo_ps_surface_emit_type3_font_subset
     int i;
 
     _cairo_output_stream_printf (surface->final_stream,
-				 "%% _cairo_ps_surface_emit_font_subset\n");
+				 "%% _cairo_ps_surface_emit_type3_font_subset\n");
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "/CairoFont-%d-%d <<\n",
diff-tree 3975d7f8a26b53d4d2c7d587fbcfe9ed6ddf78d8 (from 2c6e799ee64cfc00145ecbe0d0b93256c237dcf4)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Tue May 16 23:20:08 2006 -0400

    Add support for truetype subset to ps backend.
    
    Same story as for the pdf backend: try to output a truetype subset if
    possible, otherwise fall back to a type3 font.  Ajdust text output code
    to scale font accordingly and scale type3 fonts to unity.

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index fb8935b..4e718ac 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -211,6 +211,68 @@ _cairo_ps_surface_emit_header (cairo_ps_
     }
 }
 
+static cairo_status_t
+_cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t		*surface,
+					     cairo_scaled_font_subset_t	*font_subset)
+
+
+{
+    cairo_truetype_subset_t subset;
+    cairo_status_t status;
+    int i;
+
+    status = _cairo_truetype_subset_init (&subset, font_subset);
+    if (status)
+	return status;
+
+    /* FIXME: Figure out document structure convention for fonts */
+
+    _cairo_output_stream_printf (surface->final_stream,
+				 "11 dict begin\n"
+				 "/FontType 42 def\n"
+				 "/FontName /CairoFont-%d-%d def\n"
+				 "/PaintType 0 def\n"
+				 "/FontMatrix [ 1 0 0 1 0 0 ] def\n"
+				 "/FontBBox [ 0 0 0 0 ] def\n"
+				 "/Encoding 256 array def\n"
+				 "0 1 255 { Encoding exch /.notdef put } for\n",
+				 font_subset->font_id,
+				 font_subset->subset_id);
+
+    /* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
+
+    for (i = 1; i < font_subset->num_glyphs; i++)
+	_cairo_output_stream_printf (surface->final_stream,
+				     "Encoding %d /g%d put\n", i, i);
+
+    _cairo_output_stream_printf (surface->final_stream,
+				  "/CharStrings %d dict dup begin\n"
+				 "/.notdef 0 def\n",
+				 font_subset->num_glyphs);
+
+    for (i = 1; i < font_subset->num_glyphs; i++)
+	_cairo_output_stream_printf (surface->final_stream,
+				     "/g%d %d def\n", i, i);
+
+    _cairo_output_stream_printf (surface->final_stream,
+				 "end readonly def\n");
+
+    /* FIXME: We need to break up fonts bigger than 64k so we don't
+     * exceed string size limitation.  At glyph boundaries.  Stupid
+     * postscript. */
+    _cairo_output_stream_printf (surface->final_stream,
+				 "/sfnts [<");
+
+    _cairo_output_stream_write_hex_string (surface->final_stream,
+					   subset.data, subset.data_length);
+
+    _cairo_output_stream_printf (surface->final_stream,
+				  ">] def\n"
+				 "FontName currentdict end definefont pop\n");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static void
 _cairo_ps_surface_emit_glyph (cairo_ps_surface_t	*surface,
 			      cairo_scaled_font_t	*scaled_font,
@@ -267,11 +329,13 @@ _cairo_ps_surface_emit_glyph (cairo_ps_s
 				 "\t\t}\n");
 }
 
-static void
-_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
-				    void			*closure)
+static cairo_status_t
+_cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
+					  cairo_scaled_font_subset_t	*font_subset)
+
+
 {
-    cairo_ps_surface_t *surface = closure;
+    cairo_matrix_t matrix;
     int i;
 
     _cairo_output_stream_printf (surface->final_stream,
@@ -282,12 +346,18 @@ _cairo_ps_surface_emit_font_subset (cair
 				 font_subset->font_id,
 				 font_subset->subset_id);
 
+    matrix = font_subset->scaled_font->scale;
+    cairo_matrix_invert (&matrix);
     _cairo_output_stream_printf (surface->final_stream,
 				 "\t/FontType\t3\n"
-				 "\t/FontMatrix\t[1 0 0 1 0 0]\n"
+				 "\t/FontMatrix\t[%f %f %f %f 0 0]\n"
 				 "\t/Encoding\t[0]\n"
 				 "\t/FontBBox\t[0 0 10 10]\n"
-				 "\t/Glyphs [\n");
+				 "\t/Glyphs [\n",
+				 matrix.xx,
+				 matrix.yx,
+				 -matrix.xy,
+				 -matrix.yy);
 
     for (i = 0; i < font_subset->num_glyphs; i++) {
 	_cairo_ps_surface_emit_glyph (surface, 
@@ -302,6 +372,25 @@ _cairo_ps_surface_emit_font_subset (cair
 				 "\t\texch get exec\n"
 				 "\t}\n"
 				 ">> definefont pop\n");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+
+static void
+_cairo_ps_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
+				    void			*closure)
+{
+    cairo_ps_surface_t *surface = closure;
+    cairo_status_t status;
+
+    status = _cairo_ps_surface_emit_truetype_font_subset (surface, font_subset);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return;
+
+    status = _cairo_ps_surface_emit_type3_font_subset (surface, font_subset);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return;
 }
 
 static cairo_status_t
@@ -1757,10 +1846,18 @@ _cairo_ps_surface_show_glyphs (void		   
 
 	if (subset_id != current_subset_id) {
 	    _cairo_output_stream_printf (surface->stream,
-					 "/CairoFont-%d-%d 1 selectfont\n",
-					 font_id, subset_id);
+					 "/CairoFont-%d-%d findfont\n"
+					 "[ %f %f %f %f 0 0 ] makefont\n"
+					 "setfont\n",
+					 font_id,
+					 subset_id,
+					 scaled_font->scale.xx,
+					 scaled_font->scale.yx,
+					 -scaled_font->scale.xy,
+					 -scaled_font->scale.yy);
 	    current_subset_id = subset_id;
 	}
+
 	_cairo_output_stream_printf (surface->stream,
 				     "%f %f M <%c%c> S\n",
 				     glyphs[i].x, glyphs[i].y,
diff-tree 2c6e799ee64cfc00145ecbe0d0b93256c237dcf4 (from e846dca44e8c60bf45ab84d7adaf7eefe3088f43)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Tue May 16 22:53:05 2006 -0400

    Switch to using Tm for text positioning and scale type3 fonts to unit size.
    
    This change changes the text output code to use the Tm operator for
    positioning the glyphs.  This allows us to set the scale matrix from
    the cairo_scaled_font_t so truetype glyphs get transformed correctly.
    However, we now need to scale type3 glyph to unity to compensate.
    Longer term we should just only output one unit sized type3 subset for
    a cairo_font_face_t and use that for all cairo_scaled_font_t's coming from
    that font face.
    
    Also, this fixes a num_glyphs initialization bug.

diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c
index 6841e98..6ff93e5 100644
--- a/src/cairo-font-subset.c
+++ b/src/cairo-font-subset.c
@@ -168,7 +168,7 @@ _cairo_pdf_ft_font_create (cairo_scaled_
     if (font->parent_to_subset == NULL)
 	goto fail3;
 
-    font->base.num_glyphs = 1;
+    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;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 30ae914..3ab2d89 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1830,6 +1830,7 @@ _cairo_pdf_surface_emit_type3_font_subse
 {
     cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource;
     cairo_pdf_font_t font;
+    cairo_matrix_t matrix;
     int i;
 
     glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t));
@@ -1871,17 +1872,23 @@ _cairo_pdf_surface_emit_type3_font_subse
 				 "endobj\r\n");
 
     subset_resource = _cairo_pdf_surface_new_object (surface);
+    matrix = font_subset->scaled_font->scale;
+    cairo_matrix_invert (&matrix);
     _cairo_output_stream_printf (surface->output,
 				 "%d 0 obj\r\n"
 				 "<< /Type /Font\r\n"
 				 "   /Subtype /Type3\r\n"
 				 "   /FontBBox [0 0 0 0]\r\n"
-				 "   /FontMatrix\t[1 0 0 1 0 0]\r\n"
+				 "   /FontMatrix [ %f %f %f %f 0 0 ]\r\n"
 				 "   /Encoding %d 0 R\r\n"
 				 "   /CharProcs %d 0 R\r\n"
 				 "   /FirstChar 0\r\n"
 				 "   /LastChar %d\r\n",
 				 subset_resource.id,
+				 matrix.xx,
+				 matrix.yx,
+				 -matrix.xy,
+				 -matrix.yy,
 				 encoding.id,
 				 char_procs.id,
 				 font_subset->num_glyphs - 1);
@@ -2465,6 +2472,9 @@ _cairo_pdf_surface_show_glyphs (void			*
     if (status)
 	return status;
 
+    _cairo_output_stream_printf (surface->output,
+				 "BT\r\n");
+
     for (i = 0; i < num_glyphs; i++) {
 	status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
 						       scaled_font, glyphs[i].index,
@@ -2478,13 +2488,22 @@ _cairo_pdf_surface_show_glyphs (void			*
 					 font_id, subset_id);
 	    current_subset_id = subset_id;
 	}
+
 	_cairo_output_stream_printf (surface->output,
-				     "BT %f %f Td <%c%c> Tj ET\r\n",
-				     glyphs[i].x, glyphs[i].y,
+				     "%f %f %f %f %f %f Tm <%c%c> Tj\r\n",
+				     scaled_font->scale.xx,
+				     scaled_font->scale.yx,
+				     -scaled_font->scale.xy,
+				     -scaled_font->scale.yy,
+				     glyphs[i].x,
+				     glyphs[i].y,
 				     hex_digit (subset_glyph_index >> 4),
 				     hex_digit (subset_glyph_index));
     }
 
+    _cairo_output_stream_printf (surface->output,
+				 "ET\r\n");
+
     return _cairo_output_stream_get_status (surface->output);
 }
 
diff-tree e846dca44e8c60bf45ab84d7adaf7eefe3088f43 (from f4f11eba5b6daa6f82b967dcb21715b7f16d9719)
Author: Kristian Høgsberg <krh at redhat.com>
Date:   Tue May 16 21:41:07 2006 -0400

    Hook _cairo_truetype_subset_init() up to existing truetype subset code.
    
    This is a minimal first change to get things working.  The truetype
    subset code still needs to be renamed and moved around a bit.

diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c
index 5a1fcd1..6841e98 100644
--- a/src/cairo-font-subset.c
+++ b/src/cairo-font-subset.c
@@ -52,29 +52,31 @@ struct ft_subset_glyph {
     unsigned long location;
 };
 
-struct cairo_font_subset_backend {
-    int			(*use_glyph)	(void *abstract_font,
-					 int glyph);
-    cairo_status_t	(*generate)	(void *abstract_font,
-					 const char **data,
-					 unsigned long *length);
-    void		(*destroy)	(void *abstract_font);
-};
+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;
 
-typedef struct cairo_pdf_ft_font cairo_pdf_ft_font_t;
-struct cairo_pdf_ft_font {
-    cairo_font_subset_t base;
     ft_subset_glyph_t *glyphs;
     FT_Face face;
     int checksum_index;
     cairo_array_t output;
     int *parent_to_subset;
     cairo_status_t status;
-};
 
-static int
-cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph);
+} cairo_pdf_ft_font_t;
 
+static int
+cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph);
 
 #define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
 
@@ -115,56 +117,44 @@ be32_to_cpu(unsigned long v)
 
 #endif
 
-static cairo_font_subset_backend_t cairo_pdf_ft_font_backend;
-
-int
-_cairo_font_subset_use_glyph (cairo_font_subset_t *font, int glyph)
-{
-    return font->backend->use_glyph (font, glyph);
-}
-
-cairo_status_t
-_cairo_font_subset_generate (cairo_font_subset_t *font,
-			 const char **data, unsigned long *length)
-{
-    return font->backend->generate (font, data, length);
-}
-
-void
-_cairo_font_subset_destroy (cairo_font_subset_t *font)
-{
-    font->backend->destroy (font);
-}
-
-cairo_font_subset_t *
-_cairo_font_subset_create (cairo_unscaled_font_t *unscaled_font)
+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;
-    FT_Face face;
+    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_unscaled_font_is_ft (unscaled_font))
-	return NULL;
+    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);
 
     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 NULL;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     font = malloc (sizeof (cairo_pdf_ft_font_t));
     if (font == NULL)
-	return NULL;
+	return CAIRO_STATUS_NO_MEMORY;
+
+    font->scaled_font_subset = scaled_font_subset;
 
     font->base.unscaled_font = _cairo_unscaled_font_reference (unscaled_font);
-    font->base.backend = &cairo_pdf_ft_font_backend;
 
     _cairo_array_init (&font->output, sizeof (char));
     if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
@@ -204,7 +194,9 @@ _cairo_font_subset_create (cairo_unscale
 
     font->status = CAIRO_STATUS_SUCCESS;
 
-    return &font->base;
+    *font_return = font;
+
+    return CAIRO_STATUS_SUCCESS;
 
  fail5:
     free (font->base.base_font);
@@ -216,14 +208,13 @@ _cairo_font_subset_create (cairo_unscale
     _cairo_array_fini (&font->output);
  fail1:
     free (font);
-    return NULL;
+
+    return status;
 }
 
 static void
-cairo_pdf_ft_font_destroy (void *abstract_font)
+cairo_pdf_ft_font_destroy (cairo_pdf_ft_font_t *font)
 {
-    cairo_pdf_ft_font_t *font = abstract_font;
-
     _cairo_unscaled_font_destroy (font->base.unscaled_font);
     free (font->base.base_font);
     free (font->parent_to_subset);
@@ -738,10 +729,8 @@ cairo_pdf_ft_font_generate (void *abstra
 }
 
 static int
-cairo_pdf_ft_font_use_glyph (void *abstract_font, int glyph)
+cairo_pdf_ft_font_use_glyph (cairo_pdf_ft_font_t *font, int glyph)
 {
-    cairo_pdf_ft_font_t *font = abstract_font;
-
     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;
@@ -751,21 +740,63 @@ cairo_pdf_ft_font_use_glyph (void *abstr
     return font->parent_to_subset[glyph];
 }
 
-static cairo_font_subset_backend_t cairo_pdf_ft_font_backend = {
-    cairo_pdf_ft_font_use_glyph,
-    cairo_pdf_ft_font_generate,
-    cairo_pdf_ft_font_destroy
-};
-
 cairo_private cairo_status_t
 _cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
 			     cairo_scaled_font_subset_t	*font_subset)
 {
-    cairo_unscaled_font_t *unscaled;
+    cairo_pdf_ft_font_t *font;
+    cairo_status_t status;
+    const char *data;
+    unsigned long length, parent_glyph;
+    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;
 
-    unscaled = _cairo_ft_scaled_font_get_unscaled_font (font_subset->scaled_font);
+    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;
+
+    return CAIRO_STATUS_SUCCESS;
+
+ fail3:
+    free (truetype_subset->widths);
+ fail2:
+    free (truetype_subset->base_font);
+ fail1:
+    cairo_pdf_ft_font_destroy (font);
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    return status;
 }
 
 cairo_private void
diff-tree f4f11eba5b6daa6f82b967dcb21715b7f16d9719 (from 13a05830f5e524cd69b75796888c7a99ba9ce106)
Author: Kristian Høgsberg <krh at dinky.bitplanet.net>
Date:   Tue May 16 19:01:15 2006 -0400

    Output pdf dicts for truetype subset fonts.

diff --git a/src/cairo-font-subset.c b/src/cairo-font-subset.c
index c504f2e..5a1fcd1 100644
--- a/src/cairo-font-subset.c
+++ b/src/cairo-font-subset.c
@@ -35,6 +35,7 @@
 
 #include "cairoint.h"
 #include "cairo-font-subset-private.h"
+#include "cairo-scaled-font-subsets-private.h"
 
 /* XXX: Eventually, we need to handle other font backends */
 #include "cairo-ft-private.h"
@@ -755,3 +756,23 @@ static cairo_font_subset_backend_t cairo
     cairo_pdf_ft_font_generate,
     cairo_pdf_ft_font_destroy
 };
+
+cairo_private cairo_status_t
+_cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
+			     cairo_scaled_font_subset_t	*font_subset)
+{
+    cairo_unscaled_font_t *unscaled;
+
+    unscaled = _cairo_ft_scaled_font_get_unscaled_font (font_subset->scaled_font);
+
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+cairo_private void
+_cairo_truetype_subset_fini (cairo_truetype_subset_t *subset)
+{
+    free (subset->base_font);
+    free (subset->widths);
+    free (subset->data);
+}
+
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 8cde5e4..30ae914 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1667,7 +1667,102 @@ static cairo_status_t
 _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
 					      cairo_scaled_font_subset_t	*font_subset)
 {
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    cairo_pdf_resource_t stream, descriptor, subset_resource;
+    cairo_status_t status;
+    cairo_pdf_font_t font;
+    cairo_truetype_subset_t subset;
+    unsigned long compressed_length;
+    char *compressed;
+    int i;
+
+    status = _cairo_truetype_subset_init (&subset, font_subset);
+    if (status)
+	return status;
+
+    compressed = compress_dup (subset.data, subset.data_length,
+			       &compressed_length);
+    if (compressed == NULL) {
+	_cairo_truetype_subset_fini (&subset);
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
+    stream = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Filter /FlateDecode\r\n"
+				 "   /Length %lu\r\n"
+				 "   /Length1 %lu\r\n"
+				 ">>\r\n"
+				 "stream\r\n",
+				 stream.id,
+				 compressed_length,
+				 subset.data_length);
+    _cairo_output_stream_write (surface->output, compressed, compressed_length);
+    _cairo_output_stream_printf (surface->output,
+				 "\r\n"
+				 "endstream\r\n"
+				 "endobj\r\n");
+    free (compressed);
+
+    descriptor = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /FontDescriptor\r\n"
+				 "   /FontName /7%s\r\n"
+				 "   /Flags 4\r\n"
+				 "   /FontBBox [ %ld %ld %ld %ld ]\r\n"
+				 "   /ItalicAngle 0\r\n"
+				 "   /Ascent %ld\r\n"
+				 "   /Descent %ld\r\n"
+				 "   /CapHeight 500\r\n"
+				 "   /StemV 80\r\n"
+				 "   /StemH 80\r\n"
+				 "   /FontFile2 %u 0 R\r\n"
+				 ">>\r\n"
+				 "endobj\r\n",
+				 descriptor.id,
+				 subset.base_font,
+				 subset.x_min,
+				 subset.y_min,
+				 subset.x_max,
+				 subset.y_max,
+				 subset.ascent,
+				 subset.descent,
+				 stream.id);
+
+    subset_resource = _cairo_pdf_surface_new_object (surface);
+    _cairo_output_stream_printf (surface->output,
+				 "%d 0 obj\r\n"
+				 "<< /Type /Font\r\n"
+				 "   /Subtype /TrueType\r\n"
+				 "   /BaseFont /%s\r\n"
+				 "   /FirstChar 0\r\n"
+				 "   /LastChar %d\r\n"
+				 "   /FontDescriptor %d 0 R\r\n"
+				 "   /Widths [",
+				 subset_resource.id,
+				 subset.base_font,
+				 font_subset->num_glyphs,
+				 descriptor.id);
+
+    for (i = 0; i < font_subset->num_glyphs; i++)
+	_cairo_output_stream_printf (surface->output,
+				     " %d",
+				     subset.widths[i]);
+
+    _cairo_output_stream_printf (surface->output,
+				 " ]\r\n"
+				 ">>\r\n"
+				 "endobj\r\n");
+
+    font.font_id = font_subset->font_id;
+    font.subset_id = font_subset->subset_id;
+    font.subset_resource = subset_resource;
+    _cairo_array_append (&surface->fonts, &font);
+
+    _cairo_truetype_subset_fini (&subset);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index aed01a3..a0b0dbc 100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -179,4 +179,45 @@ _cairo_scaled_font_subsets_foreach (cair
 				    cairo_scaled_font_subset_callback_func_t	 font_subset_callback,
 				    void					*closure);
 
+
+typedef struct _cairo_truetype_subset {
+    char *base_font;
+    int *widths;
+    long x_min, y_min, x_max, y_max;
+    long ascent, descent;
+    char *data;
+    unsigned long data_length;
+} cairo_truetype_subset_t;
+
+/**
+ * _cairo_truetype_subset_init:
+ * @truetype_subset: a #cairo_truetype_subset_t to initialize
+ * @font_subset: the #cairo_scaled_font_subset_t to initialize from
+ *
+ * If possible (depending on the format of the underlying
+ * cairo_scaled_font_t and the font backend in use) generate a
+ * truetype file corresponding to @font_subset and initialize
+ * @truetype_subset with information about the subset and the truetype
+ * data.
+ *
+ * Return value: CAIRO_STATUS_SUCCESS if successful,
+ * CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
+ * truetype file, or an non-zero value indicating an error.  Possible
+ * errors include CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_status_t
+_cairo_truetype_subset_init (cairo_truetype_subset_t    *truetype_subset,
+			     cairo_scaled_font_subset_t	*font_subset);
+			     
+/**
+ * _cairo_truetype_subset_fini:
+ * @truetype_subset: a #cairo_truetype_subset_t
+ *
+ * Free all resources associated with @truetype_subset.  After this
+ * call, @truetype_subset should not be used again without a
+ * subsequent call to _cairo_truetype_subset_init() again first.
+ **/
+cairo_private void
+_cairo_truetype_subset_fini (cairo_truetype_subset_t *truetype_subset);
+
 #endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
diff-tree 13a05830f5e524cd69b75796888c7a99ba9ce106 (from 05b1d2f9c5b827d52f3eb837c6c591c877dde419)
Author: Kristian Høgsberg <krh at dinky.bitplanet.net>
Date:   Tue May 16 16:42:44 2006 -0400

    Update pdf font emit code to try to emit a truetype subset before type3.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index a37a540..8cde5e4 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1663,6 +1663,13 @@ _cairo_pdf_surface_write_pages (cairo_pd
 				 "endobj\r\n");
 }
 
+static cairo_status_t
+_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
+					      cairo_scaled_font_subset_t	*font_subset)
+{
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
 static void
 _cairo_pdf_surface_emit_glyph (cairo_pdf_surface_t	*surface,
 			       cairo_scaled_font_t	*scaled_font,
@@ -1722,11 +1729,10 @@ _cairo_pdf_surface_emit_glyph (cairo_pdf
 	_cairo_surface_set_error (&surface->base, status);
 }
 
-static void
-_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
-				     void			*closure)
+static cairo_status_t
+_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
+					   cairo_scaled_font_subset_t	*font_subset)
 {
-    cairo_pdf_surface_t *surface = closure;
     cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource;
     cairo_pdf_font_t font;
     int i;
@@ -1734,7 +1740,7 @@ _cairo_pdf_surface_emit_font_subset (cai
     glyphs = malloc (font_subset->num_glyphs * sizeof (cairo_pdf_resource_t));
     if (glyphs == NULL) {
 	_cairo_surface_set_error (&surface->base, CAIRO_STATUS_NO_MEMORY);
-	return;
+	return CAIRO_STATUS_NO_MEMORY;
     }
 
     for (i = 0; i < font_subset->num_glyphs; i++) {
@@ -1800,6 +1806,24 @@ _cairo_pdf_surface_emit_font_subset (cai
     font.subset_id = font_subset->subset_id;
     font.subset_resource = subset_resource;
     _cairo_array_append (&surface->fonts, &font);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_pdf_surface_emit_font_subset (cairo_scaled_font_subset_t	*font_subset,
+				     void			*closure)
+{
+    cairo_pdf_surface_t *surface = closure;
+    cairo_status_t status;
+
+    status = _cairo_pdf_surface_emit_truetype_font_subset (surface, font_subset);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return;
+
+    status = _cairo_pdf_surface_emit_type3_font_subset (surface, font_subset);
+    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return;
 }
 
 static cairo_status_t


More information about the cairo-commit mailing list