[cairo-commit] 4 commits - src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-scaled-font-subsets.c src/cairo-type3-glyph-surface.c src/cairo-type3-glyph-surface-private.h src/cairo-types-private.h src/cairo-user-font.c src/cairo-user-font-private.h src/Makefile.am

Adrian Johnson ajohnson at kemper.freedesktop.org
Sun Jun 8 00:58:11 PDT 2008


 src/Makefile.am                         |    2 
 src/cairo-pdf-surface.c                 |  137 +++------
 src/cairo-ps-surface.c                  |  143 +++-------
 src/cairo-scaled-font-subsets.c         |    4 
 src/cairo-type3-glyph-surface-private.h |   74 +++++
 src/cairo-type3-glyph-surface.c         |  445 ++++++++++++++++++++++++++++++++
 src/cairo-types-private.h               |    3 
 src/cairo-user-font-private.h           |   45 +++
 src/cairo-user-font.c                   |    3 
 9 files changed, 671 insertions(+), 185 deletions(-)

New commits:
commit 42c212135d22654f9220a06779c7611fe6f0a714
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 8 17:03:05 2008 +0930

    Implement PS Type 3 font image support
    
    There does not appear to be any way of emulating PDF inline images in
    PostScript so we call back to the PS or PDF surface to emit the image.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ef9a90a..1c74376 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -3398,6 +3398,46 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
 }
 
 static cairo_status_t
+_cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
+			     cairo_output_stream_t *stream)
+{
+    unsigned char *byte, output_byte;
+    int row, col, num_cols;
+
+    /* The only image type supported by Type 3 fonts are 1-bit image
+     * masks */
+    assert (image->format == CAIRO_FORMAT_A1);
+
+    _cairo_output_stream_printf (stream,
+				 "BI\n"
+				 "/IM true\n"
+				 "/W %d\n"
+				 "/H %d\n"
+				 "/BPC 1\n"
+				 "/D [1 0]\n",
+				 image->width,
+				 image->height);
+
+    _cairo_output_stream_printf (stream,
+				 "ID ");
+
+    num_cols = (image->width + 7) / 8;
+    for (row = 0; row < image->height; row++) {
+	byte = image->data + row * image->stride;
+	for (col = 0; col < num_cols; col++) {
+	    output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
+	    _cairo_output_stream_write (stream, &output_byte, 1);
+	    byte++;
+	}
+    }
+
+    _cairo_output_stream_printf (stream,
+				 "\nEI\n");
+
+    return _cairo_output_stream_get_status (stream);
+}
+
+static cairo_status_t
 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset)
 {
@@ -3430,7 +3470,9 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
-    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, NULL);
+    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
+						       NULL,
+						       _cairo_pdf_emit_imagemask);
 
     for (i = 0; i < font_subset->num_glyphs; i++) {
 	status = _cairo_pdf_surface_open_stream (surface,
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 2ab6b2c..3f4b3bf 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -375,6 +375,51 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t		*surface,
 }
 
 static cairo_status_t
+_cairo_ps_emit_imagemask (cairo_image_surface_t *image,
+			  cairo_output_stream_t *stream)
+{
+    unsigned char *row, *byte;
+    int rows, cols;
+
+    /* The only image type supported by Type 3 fonts are 1-bit image
+     * masks */
+    assert (image->format == CAIRO_FORMAT_A1);
+
+    _cairo_output_stream_printf (stream,
+				 "<<\n"
+				 "   /ImageType 1\n"
+				 "   /Width %d\n"
+				 "   /Height %d\n"
+				 "   /ImageMatrix [%d 0 0 %d 0 %d]\n"
+				 "   /Decode [1 0]\n"
+				 "   /BitsPerComponent 1\n",
+				 image->width,
+				 image->height,
+				 image->width,
+				 -image->height,
+				 image->height);
+
+    _cairo_output_stream_printf (stream,
+				 "   /DataSource   {<");
+    for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
+	for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
+	    unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
+	    _cairo_output_stream_printf (stream, "%02x ", output_byte);
+	}
+	_cairo_output_stream_printf (stream, "\n   ");
+    }
+    _cairo_output_stream_printf (stream,
+				 "   >}\n");
+    _cairo_output_stream_printf (stream,
+				 ">>\n");
+
+    _cairo_output_stream_printf (stream,
+				 "imagemask\n");
+
+    return _cairo_output_stream_get_status (stream);
+}
+
+static cairo_status_t
 _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
 					  cairo_scaled_font_subset_t	*font_subset)
 
@@ -401,7 +446,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
 				 "/Encoding 256 array def\n"
 				 "0 1 255 { Encoding exch /.notdef put } for\n");
 
-    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, NULL);
+    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
+						       NULL,
+						       _cairo_ps_emit_imagemask);
 
     for (i = 1; i < font_subset->num_glyphs; i++) {
 	if (font_subset->glyph_names != NULL) {
diff --git a/src/cairo-type3-glyph-surface-private.h b/src/cairo-type3-glyph-surface-private.h
index 894efbb..6981988 100644
--- a/src/cairo-type3-glyph-surface-private.h
+++ b/src/cairo-type3-glyph-surface-private.h
@@ -40,6 +40,9 @@
 #include "cairo-surface-private.h"
 #include "cairo-pdf-operators-private.h"
 
+typedef cairo_status_t (*cairo_type3_glyph_surface_emit_image_t) (cairo_image_surface_t *image,
+								  cairo_output_stream_t	*stream);
+
 typedef struct cairo_type3_glyph_surface {
     cairo_surface_t base;
 
@@ -47,11 +50,13 @@ typedef struct cairo_type3_glyph_surface {
     cairo_output_stream_t *stream;
     cairo_pdf_operators_t pdf_operators;
     cairo_matrix_t cairo_to_pdf;
+    cairo_type3_glyph_surface_emit_image_t emit_image;
 } cairo_type3_glyph_surface_t;
 
 cairo_private cairo_surface_t *
-_cairo_type3_glyph_surface_create (cairo_scaled_font_t	 *scaled_font,
-				   cairo_output_stream_t *stream);
+_cairo_type3_glyph_surface_create (cairo_scaled_font_t	 		 *scaled_font,
+				   cairo_output_stream_t		 *stream,
+				   cairo_type3_glyph_surface_emit_image_t emit_image);
 
 cairo_private cairo_status_t
 _cairo_type3_glyph_surface_emit_notdef_glyph (void		    *abstract_surface,
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index ded725c..0398c3a 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -42,8 +42,9 @@
 static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
 
 cairo_surface_t *
-_cairo_type3_glyph_surface_create (cairo_scaled_font_t	 *scaled_font,
-				   cairo_output_stream_t *stream)
+_cairo_type3_glyph_surface_create (cairo_scaled_font_t	 		 *scaled_font,
+				   cairo_output_stream_t 		 *stream,
+				   cairo_type3_glyph_surface_emit_image_t emit_image)
 {
     cairo_type3_glyph_surface_t *surface;
     cairo_matrix_t invert_y_axis;
@@ -57,6 +58,7 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t	 *scaled_font,
 
     surface->scaled_font = scaled_font;
     surface->stream = stream;
+    surface->emit_image = emit_image;
 
     /* Setup the transform from the user-font device space to Type 3
      * font space. The Type 3 font space is defined by the FontMatrix
@@ -81,8 +83,6 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
 {
     cairo_status_t status;
     cairo_image_surface_t *image_mask;
-    unsigned char *byte, output_byte;
-    int row, col, num_cols;
 
     /* The only image type supported by Type 3 fonts are 1-bit image
      * masks */
@@ -104,30 +104,10 @@ _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
 				 image_matrix->x0,
 				 image_matrix->y0);
 
-    _cairo_output_stream_printf (surface->stream,
-				 "BI\n"
-				 "/IM true\n"
-				 "/W %d\n"
-				 "/H %d\n"
-				 "/BPC 1\n"
-				 "/D [1 0]\n",
-				 image_mask->width,
-				 image_mask->height);
+    status = surface->emit_image (image_mask, surface->stream);
 
     _cairo_output_stream_printf (surface->stream,
-				 "ID ");
-
-    num_cols = (image_mask->width + 7) / 8;
-    for (row = 0; row < image_mask->height; row++) {
-	byte = image_mask->data + row * image_mask->stride;
-	for (col = 0; col < num_cols; col++) {
-	    output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
-	    _cairo_output_stream_write (surface->stream, &output_byte, 1);
-	    byte++;
-	}
-    }
-    _cairo_output_stream_printf (surface->stream,
-				 "\nEI Q\n");
+				 "Q\n");
 
     if (image_mask != image)
 	cairo_surface_destroy (&image_mask->base);
commit 5b05034cc9d943a5acb052763c1a595ac0e347fb
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 8 16:57:58 2008 +0930

    Implement PS Type 3 font subsetting of user fonts

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 0a08667..2ab6b2c 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -49,6 +49,7 @@
 #include "cairo-paginated-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-output-stream-private.h"
+#include "cairo-type3-glyph-surface-private.h"
 
 #include <stdio.h>
 #include <ctype.h>
@@ -192,7 +193,8 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
 				 "/Tm { 6 array astore /cairo_font_matrix exch def /cairo_font where\n"
 				 "      { cairo_selectfont } if } bind def\n"
 				 "/g { setgray } bind def\n"
-				 "/rg { setrgbcolor } bind def\n");
+				 "/rg { setrgbcolor } bind def\n"
+				 "/d1 { setcachedevice } bind def\n");
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "%%%%EndProlog\n");
@@ -372,115 +374,6 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t		*surface,
     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_box_t           *bbox)
-{
-    cairo_scaled_glyph_t *scaled_glyph;
-    cairo_status_t status;
-    cairo_image_surface_t *image;
-    unsigned char *row, *byte;
-    int rows, cols;
-    double x_advance, y_advance;
-
-    status = _cairo_scaled_glyph_lookup (scaled_font,
-					 glyph_index,
-					 CAIRO_SCALED_GLYPH_INFO_METRICS|
-					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
-					 &scaled_glyph);
-    if (status)
-	return status;
-
-    *bbox = scaled_glyph->bbox;
-    x_advance = scaled_glyph->metrics.x_advance;
-    y_advance = scaled_glyph->metrics.y_advance;
-    cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
-
-    image = scaled_glyph->surface;
-    if (image->format != CAIRO_FORMAT_A1) {
-	image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
-	if (cairo_surface_status (&image->base))
-	    return cairo_surface_status (&image->base);
-    }
-
-    _cairo_output_stream_printf (surface->final_stream,
-				 "%f 0 %f %f %f %f setcachedevice\n",
-				 x_advance,
-				 _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));
-
-    _cairo_output_stream_printf (surface->final_stream,
-				 "<<\n"
-				 "   /ImageType 1\n"
-				 "   /Width %d\n"
-				 "   /Height %d\n"
-				 "   /ImageMatrix [%f %f %f %f %f %f]\n"
-				 "   /Decode [1 0]\n"
-				 "   /BitsPerComponent 1\n",
-				 image->width,
-				 image->height,
-				 image->base.device_transform.xx,
-				 image->base.device_transform.yx,
-				 image->base.device_transform.xy,
-				 image->base.device_transform.yy,
-				 image->base.device_transform.x0,
-				 image->base.device_transform.y0);
-
-    _cairo_output_stream_printf (surface->final_stream,
-				 "   /DataSource   {<");
-    for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
-	for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
-	    unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
-	    _cairo_output_stream_printf (surface->final_stream, "%02x ", output_byte);
-	}
-	_cairo_output_stream_printf (surface->final_stream, "\n   ");
-    }
-    _cairo_output_stream_printf (surface->final_stream,
-				 "   >}\n");
-    _cairo_output_stream_printf (surface->final_stream,
-				 ">>\n");
-
-    _cairo_output_stream_printf (surface->final_stream,
-				 "imagemask\n");
-
-    if (image != scaled_glyph->surface)
-	cairo_surface_destroy (&image->base);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_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_box_t               *bbox)
-{
-    cairo_status_t	    status = CAIRO_STATUS_SUCCESS;
-
-    _cairo_output_stream_printf (surface->final_stream,
-				 "\t\t{ %% %d\n", subset_glyph_index);
-
-    if (subset_glyph_index != 0) {
-	status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
-							   scaled_font,
-							   scaled_font_glyph_index,
-							   bbox);
-    }
-
-    _cairo_output_stream_printf (surface->final_stream,
-				 "\t\t}\n");
-
-    if (status)
-	status = _cairo_surface_set_error (&surface->base, status);
-
-    return status;
-}
-
 static cairo_status_t
 _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
 					  cairo_scaled_font_subset_t	*font_subset)
@@ -492,6 +385,8 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
     unsigned int i;
     cairo_box_t font_bbox = {{0,0},{0,0}};
     cairo_box_t bbox = {{0,0},{0,0}};
+    cairo_surface_t *type3_surface;
+    double width;
 
 #if DEBUG_PS
     _cairo_output_stream_printf (surface->final_stream,
@@ -502,13 +397,11 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
     _cairo_output_stream_printf (surface->final_stream,
 				 "8 dict begin\n"
 				 "/FontType 3 def\n"
-				 "/FontMatrix [%f %f %f %f 0 0] def\n"
+				 "/FontMatrix [1 0 0 1 0 0] def\n"
 				 "/Encoding 256 array def\n"
-				 "0 1 255 { Encoding exch /.notdef put } for\n",
-				 matrix.xx,
-				 matrix.yx,
-				 -matrix.xy,
-				 -matrix.yy);
+				 "0 1 255 { Encoding exch /.notdef put } for\n");
+
+    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, NULL);
 
     for (i = 1; i < font_subset->num_glyphs; i++) {
 	if (font_subset->glyph_names != NULL) {
@@ -525,13 +418,25 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
 				 "/Glyphs [\n");
 
     for (i = 0; i < font_subset->num_glyphs; i++) {
-	status = _cairo_ps_surface_emit_glyph (surface,
-				               font_subset->scaled_font,
-					       font_subset->glyphs[i], i,
-					       &bbox);
+	_cairo_output_stream_printf (surface->final_stream,
+				     "    { %% %d\n", i);
+	if (i == 0) {
+	    status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
+								   surface->final_stream,
+								   &bbox,
+								   &width);
+	} else {
+	    status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
+							    surface->final_stream,
+							    font_subset->glyphs[i],
+							    &bbox,
+							    &width);
+	}
 	if (status)
 	    return status;
 
+	_cairo_output_stream_printf (surface->final_stream,
+				     "    }\n");
         if (i == 0) {
             font_bbox.p1.x = bbox.p1.x;
             font_bbox.p1.y = bbox.p1.y;
@@ -548,6 +453,7 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
                 font_bbox.p2.y = bbox.p2.y;
         }
     }
+    cairo_surface_destroy (type3_surface);
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "] def\n"
@@ -560,9 +466,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
 				 "end\n"
 				 "/f-%d-%d exch definefont pop\n",
 				 _cairo_fixed_to_double (font_bbox.p1.x),
-				 _cairo_fixed_to_double (font_bbox.p1.y),
+				 - _cairo_fixed_to_double (font_bbox.p2.y),
 				 _cairo_fixed_to_double (font_bbox.p2.x),
-				 _cairo_fixed_to_double (font_bbox.p2.y),
+				 - _cairo_fixed_to_double (font_bbox.p1.y),
 				 font_subset->font_id,
 				 font_subset->subset_id);
 
commit 100a34bea66545c4d962604ed9beefd3180e53fc
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 8 17:11:39 2008 +0930

    Implement PDF Type 3 font subsetting of user fonts
    
    show_glyphs inside a Type 3 font currently results in a fallback
    image. Some refactoring is required before font subsets can be created
    while emitting all the font subsets.

diff --git a/src/Makefile.am b/src/Makefile.am
index de080e7..6c467bb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -89,6 +89,8 @@ font_subset_sources_base =			\
 	cairo-type1-fallback.c			\
 	cairo-type1-private.h			\
 	cairo-truetype-subset-private.h		\
+        cairo-type3-glyph-surface.c             \
+        cairo-type3-glyph-surface-private.h     \
 	cairo-scaled-font-subsets.c		\
 	cairo-scaled-font-subsets-private.h
 cairo_all_sources += $(font_subset_sources_base)
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ddabc03..ef9a90a 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -48,6 +48,7 @@
 #include "cairo-paginated-private.h"
 #include "cairo-output-stream-private.h"
 #include "cairo-meta-surface-private.h"
+#include "cairo-type3-glyph-surface-private.h"
 
 #include <time.h>
 #include <zlib.h>
@@ -3396,99 +3397,6 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t		*surface,
     return status;
 }
 
-static cairo_int_status_t
-_cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t	*surface,
-				      cairo_scaled_font_t	*scaled_font,
-				      unsigned long		 glyph_index,
-				      cairo_pdf_resource_t	*glyph_ret,
-                                      cairo_box_t               *bbox,
-                                      double                    *width)
-{
-    cairo_scaled_glyph_t *scaled_glyph;
-    cairo_status_t status;
-    cairo_image_surface_t *image;
-    unsigned char *row, *byte;
-    int rows, cols;
-    double x_advance, y_advance;
-
-    status = _cairo_scaled_glyph_lookup (scaled_font,
-					 glyph_index,
-					 CAIRO_SCALED_GLYPH_INFO_METRICS|
-					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
-					 &scaled_glyph);
-    if (status)
-	return status;
-
-    x_advance = scaled_glyph->metrics.x_advance;
-    y_advance = scaled_glyph->metrics.y_advance;
-    cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
-    *bbox = scaled_glyph->bbox;
-    *width = x_advance;
-
-    image = scaled_glyph->surface;
-    if (image->format != CAIRO_FORMAT_A1) {
-	image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
-	status = cairo_surface_status (&image->base);
-	if (status)
-	    return status;
-    }
-
-    status = _cairo_pdf_surface_open_stream (surface,
-				             NULL,
-					     surface->compress_content,
-					     NULL);
-    if (status) {
-	if (image != scaled_glyph->surface)
-	    cairo_surface_destroy (&image->base);
-	return status;
-    }
-
-    *glyph_ret = surface->pdf_stream.self;
-
-    _cairo_output_stream_printf (surface->output,
-				 "%f 0 %f %f %f %f d1\n",
-                                 x_advance,
-				 _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));
-
-    _cairo_output_stream_printf (surface->output,
-				 "%f 0 0 %f %f %f cm\n",
-				 _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),
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
-				 _cairo_fixed_to_double (scaled_glyph->bbox.p2.y));
-
-    _cairo_output_stream_printf (surface->output,
-				 "BI\n"
-				 "/IM true\n"
-				 "/W %d\n"
-				 "/H %d\n"
-				 "/BPC 1\n"
-				 "/D [1 0]\n",
-				 image->width,
-				 image->height);
-
-    _cairo_output_stream_printf (surface->output,
-				 "ID ");
-    for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
-	for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
-	    unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
-	    _cairo_output_stream_write (surface->output, &output_byte, 1);
-	}
-    }
-    _cairo_output_stream_printf (surface->output,
-				 "\nEI\n");
-
-    status = _cairo_pdf_surface_close_stream (surface);
-
-    if (image != scaled_glyph->surface)
-	cairo_surface_destroy (&image->base);
-
-    return status;
-}
-
 static cairo_status_t
 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset)
@@ -3501,6 +3409,7 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
     unsigned int i;
     cairo_box_t font_bbox = {{0,0},{0,0}};
     cairo_box_t bbox = {{0,0},{0,0}};
+    cairo_surface_t *type3_surface;
 
     if (font_subset->num_glyphs == 0)
 	return CAIRO_STATUS_SUCCESS;
@@ -3521,13 +3430,27 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     }
 
+    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font, NULL);
+
     for (i = 0; i < font_subset->num_glyphs; i++) {
-        status = _cairo_pdf_surface_emit_bitmap_glyph (surface,
-                                                       font_subset->scaled_font,
-                                                       font_subset->glyphs[i],
-                                                       &glyphs[i],
-                                                       &bbox,
-                                                       &widths[i]);
+	status = _cairo_pdf_surface_open_stream (surface,
+						 NULL,
+						 surface->compress_content,
+						 NULL);
+	glyphs[i] = surface->pdf_stream.self;
+	if (i == 0) {
+	    status = _cairo_type3_glyph_surface_emit_notdef_glyph (type3_surface,
+								   surface->output,
+								   &bbox,
+								   &widths[i]);
+	} else {
+	    status = _cairo_type3_glyph_surface_emit_glyph (type3_surface,
+							    surface->output,
+							    font_subset->glyphs[i],
+							    &bbox,
+							    &widths[i]);
+	}
+	status = _cairo_pdf_surface_close_stream (surface);
 	if (status)
 	    break;
 
@@ -3547,6 +3470,7 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
                 font_bbox.p2.y = bbox.p2.y;
         }
     }
+    cairo_surface_destroy (type3_surface);
     if (status) {
 	free (glyphs);
 	free (widths);
@@ -3607,20 +3531,16 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 				 "<< /Type /Font\n"
 				 "   /Subtype /Type3\n"
 				 "   /FontBBox [%f %f %f %f]\n"
-				 "   /FontMatrix [ %f %f %f %f 0 0 ]\n"
+				 "   /FontMatrix [ 1 0 0 1 0 0 ]\n"
 				 "   /Encoding %d 0 R\n"
 				 "   /CharProcs %d 0 R\n"
 				 "   /FirstChar 0\n"
 				 "   /LastChar %d\n",
 				 subset_resource.id,
 				 _cairo_fixed_to_double (font_bbox.p1.x),
-				 _cairo_fixed_to_double (font_bbox.p1.y),
+				 - _cairo_fixed_to_double (font_bbox.p2.y),
 				 _cairo_fixed_to_double (font_bbox.p2.x),
-				 _cairo_fixed_to_double (font_bbox.p2.y),
-				 matrix.xx,
-				 matrix.yx,
-				 -matrix.xy,
-				 -matrix.yy,
+				 - _cairo_fixed_to_double (font_bbox.p1.y),
 				 encoding.id,
 				 char_procs.id,
 				 font_subset->num_glyphs - 1);
@@ -3677,6 +3597,7 @@ _cairo_pdf_surface_emit_unscaled_font_subset (cairo_scaled_font_subset_t *font_s
         status = _cairo_pdf_surface_emit_type1_fallback_font (surface, font_subset);
         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
             return status;
+
     }
 
     ASSERT_NOT_REACHED;
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 133f6b5..f70d978 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -43,6 +43,7 @@
 #define _BSD_SOURCE /* for snprintf(), strdup() */
 #include "cairoint.h"
 #include "cairo-scaled-font-subsets-private.h"
+#include "cairo-user-font-private.h"
 
 #define MAX_GLYPHS_PER_SIMPLE_FONT 256
 #define MAX_GLYPHS_PER_COMPOSITE_FONT 65536
@@ -580,7 +581,8 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t	*subsets,
         return status;
 
     if (status == CAIRO_STATUS_SUCCESS &&
-	subsets->type != CAIRO_SUBSETS_SCALED)
+	subsets->type != CAIRO_SUBSETS_SCALED &&
+	! _cairo_font_face_is_user (scaled_font->font_face))
     {
         /* Path available. Add to unscaled subset. */
         key.is_scaled = FALSE;
diff --git a/src/cairo-type3-glyph-surface-private.h b/src/cairo-type3-glyph-surface-private.h
new file mode 100644
index 0000000..894efbb
--- /dev/null
+++ b/src/cairo-type3-glyph-surface-private.h
@@ -0,0 +1,69 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 Adrian Johnson
+ *
+ * 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 Adrian Johnson.
+ *
+ * Contributor(s):
+ *	Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#ifndef CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H
+#define CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H
+
+#include "cairo-surface-private.h"
+#include "cairo-pdf-operators-private.h"
+
+typedef struct cairo_type3_glyph_surface {
+    cairo_surface_t base;
+
+    cairo_scaled_font_t *scaled_font;
+    cairo_output_stream_t *stream;
+    cairo_pdf_operators_t pdf_operators;
+    cairo_matrix_t cairo_to_pdf;
+} cairo_type3_glyph_surface_t;
+
+cairo_private cairo_surface_t *
+_cairo_type3_glyph_surface_create (cairo_scaled_font_t	 *scaled_font,
+				   cairo_output_stream_t *stream);
+
+cairo_private cairo_status_t
+_cairo_type3_glyph_surface_emit_notdef_glyph (void		    *abstract_surface,
+					      cairo_output_stream_t *stream,
+					      cairo_box_t           *bbox,
+					      double                *width);
+
+cairo_private cairo_status_t
+_cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
+				       cairo_output_stream_t *stream,
+				       unsigned long	      glyph_index,
+				       cairo_box_t           *bbox,
+				       double                *width);
+
+#endif /* CAIRO_TYPE3_GLYPH_SURFACE_PRIVATE_H */
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
new file mode 100644
index 0000000..ded725c
--- /dev/null
+++ b/src/cairo-type3-glyph-surface.c
@@ -0,0 +1,465 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2008 Adrian Johnson
+ *
+ * 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 Adrian Johnson.
+ *
+ * Contributor(s):
+ *	Adrian Johnson <ajohnson at redneon.com>
+ */
+
+#include "cairoint.h"
+#include "cairo-type3-glyph-surface-private.h"
+#include "cairo-output-stream-private.h"
+#include "cairo-meta-surface-private.h"
+
+static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
+
+cairo_surface_t *
+_cairo_type3_glyph_surface_create (cairo_scaled_font_t	 *scaled_font,
+				   cairo_output_stream_t *stream)
+{
+    cairo_type3_glyph_surface_t *surface;
+    cairo_matrix_t invert_y_axis;
+
+    surface = malloc (sizeof (cairo_type3_glyph_surface_t));
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    _cairo_surface_init (&surface->base, &cairo_type3_glyph_surface_backend,
+			 CAIRO_CONTENT_COLOR_ALPHA);
+
+    surface->scaled_font = scaled_font;
+    surface->stream = stream;
+
+    /* Setup the transform from the user-font device space to Type 3
+     * font space. The Type 3 font space is defined by the FontMatrix
+     * entry in the Type 3 dictionary. In the PDF backend this is an
+     * identity matrix. */
+    surface->cairo_to_pdf = scaled_font->scale_inverse;
+    cairo_matrix_init_scale (&invert_y_axis, 1, -1);
+    cairo_matrix_multiply (&surface->cairo_to_pdf, &surface->cairo_to_pdf, &invert_y_axis);
+
+    _cairo_pdf_operators_init (&surface->pdf_operators,
+			       surface->stream,
+			       &surface->cairo_to_pdf,
+			       NULL);
+
+    return &surface->base;
+}
+
+static cairo_status_t
+_cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
+				       cairo_image_surface_t       *image,
+				       cairo_matrix_t              *image_matrix)
+{
+    cairo_status_t status;
+    cairo_image_surface_t *image_mask;
+    unsigned char *byte, output_byte;
+    int row, col, num_cols;
+
+    /* The only image type supported by Type 3 fonts are 1-bit image
+     * masks */
+    if (image->format == CAIRO_FORMAT_A1) {
+	image_mask = image;
+    } else {
+	image_mask = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
+	status = cairo_surface_status (&image->base);
+	if (status)
+	    return status;
+    }
+
+    _cairo_output_stream_printf (surface->stream,
+				 "q %f %f %f %f %f %f cm\n",
+				 image_matrix->xx,
+				 image_matrix->xy,
+				 image_matrix->yx,
+				 image_matrix->yy,
+				 image_matrix->x0,
+				 image_matrix->y0);
+
+    _cairo_output_stream_printf (surface->stream,
+				 "BI\n"
+				 "/IM true\n"
+				 "/W %d\n"
+				 "/H %d\n"
+				 "/BPC 1\n"
+				 "/D [1 0]\n",
+				 image_mask->width,
+				 image_mask->height);
+
+    _cairo_output_stream_printf (surface->stream,
+				 "ID ");
+
+    num_cols = (image_mask->width + 7) / 8;
+    for (row = 0; row < image_mask->height; row++) {
+	byte = image_mask->data + row * image_mask->stride;
+	for (col = 0; col < num_cols; col++) {
+	    output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
+	    _cairo_output_stream_write (surface->stream, &output_byte, 1);
+	    byte++;
+	}
+    }
+    _cairo_output_stream_printf (surface->stream,
+				 "\nEI Q\n");
+
+    if (image_mask != image)
+	cairo_surface_destroy (&image_mask->base);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_type3_glyph_surface_emit_image_pattern (cairo_type3_glyph_surface_t *surface,
+					       cairo_image_surface_t       *image,
+					       cairo_matrix_t              *pattern_matrix)
+{
+    cairo_matrix_t mat, upside_down;
+    cairo_status_t status;
+
+    if (image->width == 0 || image->height == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    mat = *pattern_matrix;
+
+    /* Get the pattern space to user space matrix  */
+    status = cairo_matrix_invert (&mat);
+
+    /* cairo_pattern_set_matrix ensures the matrix is invertible */
+    assert (status == CAIRO_STATUS_SUCCESS);
+
+    /* Make this a pattern space to Type 3 font space matrix */
+    cairo_matrix_multiply (&mat, &mat, &surface->cairo_to_pdf);
+
+    /* PDF images are in a 1 unit by 1 unit image space. Turn the 1 by
+     * 1 image upside down to convert to flip the Y-axis going from
+     * cairo to PDF. Then scale the image up to the required size. */
+    cairo_matrix_scale (&mat, image->width, image->height);
+    cairo_matrix_init (&upside_down, 1, 0, 0, -1, 0, 1);
+    cairo_matrix_multiply (&mat, &upside_down, &mat);
+
+    return _cairo_type3_glyph_surface_emit_image (surface, image, &mat);
+}
+
+static cairo_status_t
+_cairo_type3_glyph_surface_finish (void *abstract_surface)
+{
+    cairo_type3_glyph_surface_t *surface = abstract_surface;
+
+    return _cairo_pdf_operators_fini (&surface->pdf_operators);
+}
+
+static cairo_int_status_t
+_cairo_type3_glyph_surface_intersect_clip_path (void		   *abstract_surface,
+						cairo_path_fixed_t *path,
+						cairo_fill_rule_t   fill_rule,
+						double		    tolerance,
+						cairo_antialias_t   antialias)
+{
+    cairo_type3_glyph_surface_t *surface = abstract_surface;
+
+    if (path == NULL) {
+	_cairo_output_stream_printf (surface->stream, "Q q\n");
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    return _cairo_pdf_operators_clip (&surface->pdf_operators,
+				      path,
+				      fill_rule);
+}
+
+static cairo_int_status_t
+_cairo_type3_glyph_surface_paint (void			*abstract_surface,
+				  cairo_operator_t	 op,
+				  cairo_pattern_t	*source)
+{
+    cairo_type3_glyph_surface_t *surface = abstract_surface;
+    cairo_surface_pattern_t *pattern;
+    cairo_image_surface_t *image;
+    void *image_extra;
+    cairo_status_t status;
+
+    if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
+	return CAIRO_INT_STATUS_IMAGE_FALLBACK;
+
+    pattern = (cairo_surface_pattern_t *) source;
+    status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
+    if (status)
+	goto fail;
+
+    status = _cairo_type3_glyph_surface_emit_image_pattern (surface,
+							    image,
+							    &pattern->base.matrix);
+
+fail:
+    _cairo_surface_release_source_image (pattern->surface, image, image_extra);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_type3_glyph_surface_mask (void			*abstract_surface,
+				 cairo_operator_t	 op,
+				 cairo_pattern_t	*source,
+				 cairo_pattern_t	*mask)
+{
+    return _cairo_type3_glyph_surface_paint (abstract_surface, op, mask);
+}
+
+static cairo_int_status_t
+_cairo_type3_glyph_surface_stroke (void			*abstract_surface,
+				   cairo_operator_t	 op,
+				   cairo_pattern_t	*source,
+				   cairo_path_fixed_t	*path,
+				   cairo_stroke_style_t	*style,
+				   cairo_matrix_t	*ctm,
+				   cairo_matrix_t	*ctm_inverse,
+				   double		 tolerance,
+				   cairo_antialias_t	 antialias)
+{
+    cairo_type3_glyph_surface_t *surface = abstract_surface;
+
+    return _cairo_pdf_operators_stroke (&surface->pdf_operators,
+					path,
+					style,
+					ctm,
+					ctm_inverse);
+}
+
+static cairo_int_status_t
+_cairo_type3_glyph_surface_fill (void			*abstract_surface,
+				 cairo_operator_t	 op,
+				 cairo_pattern_t	*source,
+				 cairo_path_fixed_t	*path,
+				 cairo_fill_rule_t	 fill_rule,
+				 double			 tolerance,
+				 cairo_antialias_t	 antialias)
+{
+    cairo_type3_glyph_surface_t *surface = abstract_surface;
+    cairo_int_status_t status;
+
+    status = _cairo_pdf_operators_fill (&surface->pdf_operators,
+					path,
+					fill_rule);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_type3_glyph_surface_show_glyphs (void		     *abstract_surface,
+					cairo_operator_t      op,
+					cairo_pattern_t	     *source,
+					cairo_glyph_t        *glyphs,
+					int		      num_glyphs,
+					cairo_scaled_font_t  *scaled_font,
+					int		     *remaining_glyphs)
+{
+    /* XXX: Some refactoring is required before we can add font
+     * subsets in the middle of emitting all the subsets. */
+
+    return CAIRO_INT_STATUS_IMAGE_FALLBACK;
+}
+
+static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
+    CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH,
+    NULL, /* _cairo_type3_glyph_surface_create_similar */
+    _cairo_type3_glyph_surface_finish,
+    NULL, /* acquire_source_image */
+    NULL, /* release_source_image */
+    NULL, /* acquire_dest_image */
+    NULL, /* release_dest_image */
+    NULL, /* clone_similar */
+    NULL, /* composite */
+    NULL, /* fill_rectangles */
+    NULL, /* composite_trapezoids */
+    NULL, /* cairo_type3_glyph_surface_copy_page */
+    NULL, /* _cairo_type3_glyph_surface_show_page */
+    NULL, /* set_clip_region */
+    _cairo_type3_glyph_surface_intersect_clip_path,
+    NULL, /* _cairo_type3_glyph_surface_get_extents */
+    NULL, /* old_show_glyphs */
+    NULL, /* _cairo_type3_glyph_surface_get_font_options */
+    NULL, /* flush */
+    NULL, /* mark_dirty_rectangle */
+    NULL, /* scaled_font_fini */
+    NULL, /* scaled_glyph_fini */
+    _cairo_type3_glyph_surface_paint,
+    _cairo_type3_glyph_surface_mask,
+    _cairo_type3_glyph_surface_stroke,
+    _cairo_type3_glyph_surface_fill,
+    _cairo_type3_glyph_surface_show_glyphs,
+    NULL, /* snapshot */
+};
+
+static void
+_cairo_type3_glyph_surface_set_stream (cairo_type3_glyph_surface_t *surface,
+				       cairo_output_stream_t       *stream)
+{
+    surface->stream = stream;
+    _cairo_pdf_operators_set_stream (&surface->pdf_operators, stream);
+}
+
+static cairo_status_t
+_cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *surface,
+						unsigned long		     glyph_index)
+{
+    cairo_scaled_glyph_t *scaled_glyph;
+    cairo_status_t status;
+    cairo_image_surface_t *image;
+    cairo_matrix_t mat;
+    double width, height, x, y;
+
+    status = _cairo_scaled_glyph_lookup (surface->scaled_font,
+					 glyph_index,
+					 CAIRO_SCALED_GLYPH_INFO_METRICS |
+					 CAIRO_SCALED_GLYPH_INFO_SURFACE,
+					 &scaled_glyph);
+    if (status)
+	return status;
+
+    image = scaled_glyph->surface;
+    if (image->width == 0 || image->height == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
+    y = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y);
+    width = _cairo_fixed_to_double (scaled_glyph->bbox.p2.x) -
+	_cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
+    height = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y) -
+	_cairo_fixed_to_double (scaled_glyph->bbox.p1.y);
+    mat.xx = width;
+    mat.xy = 0;
+    mat.yx = 0;
+    mat.yy = height;
+    mat.x0 = x;
+    mat.y0 = y;
+    cairo_matrix_multiply (&mat, &mat, &surface->scaled_font->scale_inverse);
+    mat.y0 *= -1;
+
+    return _cairo_type3_glyph_surface_emit_image (surface, image, &mat);
+}
+
+cairo_status_t
+_cairo_type3_glyph_surface_emit_notdef_glyph (void		    *abstract_surface,
+					      cairo_output_stream_t *stream,
+					      cairo_box_t           *bbox,
+					      double                *width)
+{
+    bbox->p1.x = 0;
+    bbox->p1.y = 0;
+    bbox->p2.x = 0;
+    bbox->p2.y = 0;
+    *width = 0.0;
+    _cairo_output_stream_printf (stream, "0 0 0 0 0 0 d1\n");
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
+				       cairo_output_stream_t *stream,
+				       unsigned long	      glyph_index,
+				       cairo_box_t           *bbox,
+				       double                *width)
+{
+    cairo_type3_glyph_surface_t *surface = abstract_surface;
+    cairo_scaled_glyph_t *scaled_glyph;
+    cairo_status_t status, status2;
+    double x_advance, y_advance;
+    cairo_output_stream_t *mem_stream;
+    cairo_matrix_t font_matrix_inverse;
+
+    _cairo_type3_glyph_surface_set_stream (surface, stream);
+    status = _cairo_scaled_glyph_lookup (surface->scaled_font,
+					 glyph_index,
+					 CAIRO_SCALED_GLYPH_INFO_METRICS |
+					 CAIRO_SCALED_GLYPH_INFO_META_SURFACE,
+					 &scaled_glyph);
+    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+	return status;
+
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+	status = _cairo_scaled_glyph_lookup (surface->scaled_font,
+					     glyph_index,
+					     CAIRO_SCALED_GLYPH_INFO_METRICS,
+					     &scaled_glyph);
+	if (status)
+	    return status;
+
+	status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
+    }
+
+    x_advance = scaled_glyph->metrics.x_advance;
+    y_advance = scaled_glyph->metrics.y_advance;
+    font_matrix_inverse = surface->scaled_font->font_matrix;
+    status2 = cairo_matrix_invert (&font_matrix_inverse);
+
+    /* The invertability of font_matrix is tested in
+     * pdf_operators_show_glyphs before any glyphs are mappped to the
+     * subset. */
+    assert (status2 == CAIRO_STATUS_SUCCESS);
+
+    cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance);
+    *width = x_advance;
+
+    *bbox = scaled_glyph->bbox;
+    _cairo_matrix_transform_bounding_box_fixed (&surface->scaled_font->scale_inverse,
+						bbox, NULL);
+
+    _cairo_output_stream_printf (surface->stream,
+				 "%f 0 %f %f %f %f d1\n",
+                                 x_advance,
+				 _cairo_fixed_to_double (bbox->p1.x),
+				 - _cairo_fixed_to_double (bbox->p2.y),
+				 _cairo_fixed_to_double (bbox->p2.x),
+				 - _cairo_fixed_to_double (bbox->p1.y));
+
+    if (status == CAIRO_STATUS_SUCCESS) {
+	mem_stream = _cairo_memory_stream_create ();
+	_cairo_type3_glyph_surface_set_stream (surface, mem_stream);
+
+	_cairo_output_stream_printf (surface->stream, "q\n");
+	status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
+					 &surface->base);
+	_cairo_output_stream_printf (surface->stream, "Q\n");
+
+	_cairo_type3_glyph_surface_set_stream (surface, stream);
+	if (status == CAIRO_STATUS_SUCCESS)
+	    _cairo_memory_stream_copy (mem_stream, stream);
+
+	status2 = _cairo_output_stream_destroy (mem_stream);
+	if (status2)
+	    return status2;
+    }
+
+    if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
+	status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
+
+    return status;
+}
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index f7de874..6869c9f 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -149,7 +149,8 @@ typedef enum _cairo_internal_surface_type {
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
     CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
-    CAIRO_INTERNAL_SURFACE_TYPE_NULL
+    CAIRO_INTERNAL_SURFACE_TYPE_NULL,
+    CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH
 } cairo_internal_surface_type_t;
 
 typedef struct _cairo_region cairo_region_t;
commit 1e1c05e58f808c07ac0e7c0a4ba2c6f8ccb18792
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Jun 8 16:50:34 2008 +0930

    Change _cairo_font_face_is_user() from static to cairo_private

diff --git a/src/cairo-user-font-private.h b/src/cairo-user-font-private.h
new file mode 100644
index 0000000..d75c24b
--- /dev/null
+++ b/src/cairo-user-font-private.h
@@ -0,0 +1,45 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2006, 2008 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>
+ *      Behdad Esfahbod <behdad at behdad.org>
+ */
+
+#ifndef CAIRO_USER_FONT_PRIVATE_H
+#define CAIRO_USER_FONT_PRIVATE_H
+
+#include "cairo.h"
+
+cairo_private cairo_bool_t
+_cairo_font_face_is_user (cairo_font_face_t *font_face);
+
+#endif /* CAIRO_USER_FONT_PRIVATE_H */
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index e4a72c6..cb15ca4 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -35,6 +35,7 @@
  */
 
 #include "cairoint.h"
+#include "cairo-user-font-private.h"
 #include "cairo-meta-surface-private.h"
 #include "cairo-analysis-surface-private.h"
 
@@ -419,7 +420,7 @@ static const cairo_font_face_backend_t _cairo_user_font_face_backend = {
 };
 
 
-static cairo_bool_t
+cairo_bool_t
 _cairo_font_face_is_user (cairo_font_face_t *font_face)
 {
     return font_face->backend == &_cairo_user_font_face_backend;


More information about the cairo-commit mailing list