[cairo-commit] 2 commits - src/cairo-atsui-font.c src/cairo-ft-font.c src/cairoint.h src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-scaled-font.c

Carl Worth cworth at kemper.freedesktop.org
Tue Jun 13 14:06:14 PDT 2006


 src/cairo-atsui-font.c  |    2 -
 src/cairo-ft-font.c     |    4 +-
 src/cairo-pdf-surface.c |   92 +++++++++++++++++++++++++++++++++---------------
 src/cairo-ps-surface.c  |   91 +++++++++++++++++++++++++++++++++--------------
 src/cairo-scaled-font.c |   10 ++++-
 src/cairoint.h          |    4 +-
 6 files changed, 142 insertions(+), 61 deletions(-)

New commits:
diff-tree 4b063c607208935fad040d481d42085c4ed6e64d (from d2045c1f7465f7f3625ce14a7b0e395b35ba8dc0)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Jun 13 12:48:00 2006 -0700

    PS, PDF: Re-organize handling of bitmapped fonts to avoid invalid output.
    
    Previously, using the ps or pdf backend with a bitmapped font would
    result in a coorupt output file, filled with uninitialized values and
    missing procedures for drawing the glyphs.
    
    Now, the file should actually be valid, but it's simply drawing black
    boxes instead of the correct glyphs.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index c0586b9..e365b77 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1579,44 +1579,25 @@ _cairo_pdf_surface_write_pages (cairo_pd
 				 "endobj\r\n");
 }
 
-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;
-    cairo_status_t status;
     pdf_path_info_t info;
+    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);
-    /*
-     * If that fails, try again but ask for an image instead
-     */
     if (status)
-	status = _cairo_scaled_glyph_lookup (scaled_font,
-					     scaled_font_glyph_index,
-					     CAIRO_SCALED_GLYPH_INFO_METRICS|
-					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
-					     &scaled_glyph);
-    if (status) {
-	_cairo_surface_set_error (&surface->base, status);
-	return;
-    }
-
-    /* XXX: Need to actually use the image not the path if that's all
-     * we could get... */
-
-    *glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL);
+	return status;
 
     _cairo_output_stream_printf (surface->output,
-				 "0 0 %f %f %f %f d1\r\n"
-				 "                                                                                                             \r\n",
+				 "0 0 %f %f %f %f d1\r\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),
@@ -1636,6 +1617,61 @@ _cairo_pdf_surface_emit_glyph (cairo_pdf
     _cairo_output_stream_printf (surface->output,
 				 " f");
 
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_pdf_surface_emit_bitmap_glyph_data (cairo_pdf_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);
+    if (status)
+	return status;
+
+    _cairo_output_stream_printf (surface->output,
+				 "0 0 %f %f %f %f d1\r\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->output,
+				 "%f %f %f %f re f\r\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_pdf_surface_emit_glyph (cairo_pdf_surface_t	*surface,
+			       cairo_scaled_font_t	*scaled_font,
+			       unsigned long		 glyph_index,
+			       cairo_pdf_resource_t	*glyph_ret)
+{
+    cairo_status_t status;
+
+    *glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL);
+
+    status = _cairo_pdf_surface_emit_outline_glyph_data (surface,
+							 scaled_font,
+							 glyph_index);
+    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+	status = _cairo_pdf_surface_emit_bitmap_glyph_data (surface,
+							    scaled_font,
+							    glyph_index);
+
     _cairo_pdf_surface_close_stream (surface);
 
     if (status)
@@ -1660,7 +1696,7 @@ _cairo_pdf_surface_emit_font_subset (cai
     for (i = 0; i < font_subset->num_glyphs; i++) {
 	_cairo_pdf_surface_emit_glyph (surface,
 				       font_subset->scaled_font,
-				       font_subset->glyphs[i], i,
+				       font_subset->glyphs[i],
 				       &glyphs[i]);
     }
 
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index a621670..6553bce 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -209,39 +209,21 @@ _cairo_ps_surface_emit_header (cairo_ps_
     }
 }
 
-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);
-    /*
-     * If that fails, try again but ask for an image instead
-     */
     if (status)
-	status = _cairo_scaled_glyph_lookup (scaled_font,
-					     scaled_font_glyph_index,
-					     CAIRO_SCALED_GLYPH_INFO_METRICS|
-					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
-					     &scaled_glyph);
-    if (status) {
-	_cairo_surface_set_error (&surface->base, status);
-	return;
-    }
-
-    /* XXX: Need to actually use the image not the path if that's all
-     * we could get... */
-
-    _cairo_output_stream_printf (surface->final_stream,
-				 "\t\t{ %% %d\n", subset_glyph_index);
+	return status;
 
     _cairo_output_stream_printf (surface->final_stream,
 				 "0 0 %f %f %f %f setcachedevice\n",
@@ -261,8 +243,65 @@ _cairo_ps_surface_emit_glyph (cairo_ps_s
     _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
diff-tree d2045c1f7465f7f3625ce14a7b0e395b35ba8dc0 (from 0e30fc44363435c52c762fa8a353de43fe087822)
Author: Carl Worth <cworth at cworth.org>
Date:   Tue Jun 13 12:45:16 2006 -0700

    Change return type of _cairo_scaled_glyph_lookup to allow UNSUPPORTED.
    
    This allows graceful recovery when first requesting a path from a font
    that only supports bitmapped glyph. The changed return type is also
    pushed down into the scaled_glyph_init function of the
    cairo_scaled_font backend.

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index e444cff..7f8d1e4 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -471,7 +471,7 @@ _cairo_atsui_scaled_font_init_glyph_path
     return CAIRO_STATUS_SUCCESS;
 }
 
-static cairo_status_t
+static cairo_int_status_t
 _cairo_atsui_font_scaled_glyph_init (void			*abstract_font,
 				     cairo_scaled_glyph_t	*scaled_glyph,
 				     cairo_scaled_glyph_info_t	 info)
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 3eac243..fd2c899 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1734,7 +1734,7 @@ _cairo_ft_scaled_glyph_vertical_layout_b
     }
 }
 
-static cairo_status_t
+static cairo_int_status_t
 _cairo_ft_scaled_glyph_init (void			*abstract_font,
 			     cairo_scaled_glyph_t	*scaled_glyph,
 			     cairo_scaled_glyph_info_t	 info)
@@ -1932,7 +1932,7 @@ _cairo_ft_scaled_glyph_init (void			*abs
 	    status = _decompose_glyph_outline (face, &scaled_font->base.options,
 					       &path);
 	else
-	    status = CAIRO_STATUS_NO_MEMORY;
+	    status = CAIRO_INT_STATUS_UNSUPPORTED;
 
 	if (status) {
 	    cairo_ft_scaled_font_unlock_face (abstract_font);
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index c46e336..c614d81 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1167,8 +1167,12 @@ _cairo_scaled_glyph_set_path (cairo_scal
  *  %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box
  *  %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image
  *  %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space
+ *
+ * If the desired info is not available, (for example, when trying to
+ * get INFO_PATH with a bitmapped font), this function will return
+ * CAIRO_INT_STATUS_UNSUPPORTED.
  **/
-cairo_status_t
+cairo_int_status_t
 _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
 			    unsigned long index,
 			    cairo_scaled_glyph_info_t info,
@@ -1246,7 +1250,9 @@ _cairo_scaled_glyph_lookup (cairo_scaled
 
   CLEANUP:
     if (status) {
-	_cairo_scaled_font_set_error (scaled_font, status);
+	/* It's not an error for the backend to not support the info we want. */
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    _cairo_scaled_font_set_error (scaled_font, status);
 	*scaled_glyph_ret = NULL;
     } else {
 	*scaled_glyph_ret = scaled_glyph;
diff --git a/src/cairoint.h b/src/cairoint.h
index 78062a7..8f65015 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -528,7 +528,7 @@ struct _cairo_scaled_font_backend {
     void
     (*fini)		(void			*scaled_font);
 
-    cairo_status_t
+    cairo_int_status_t
     (*scaled_glyph_init)	(void			     *scaled_font,
 				 cairo_scaled_glyph_t	     *scaled_glyph,
 				 cairo_scaled_glyph_info_t    info);
@@ -1598,7 +1598,7 @@ _cairo_scaled_glyph_set_path (cairo_scal
 			      cairo_scaled_font_t *scaled_font,
 			      cairo_path_fixed_t *path);
 
-cairo_private cairo_status_t
+cairo_private cairo_int_status_t
 _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
 			    unsigned long index,
 			    cairo_scaled_glyph_info_t info,


More information about the cairo-commit mailing list