[cairo-commit] cairo/src cairo-pdf-surface.c,1.58,1.59

Kristian Høgsberg commit at pdx.freedesktop.org
Fri Oct 7 13:21:03 PDT 2005


Committed by: krh

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv17883/src

Modified Files:
	cairo-pdf-surface.c 
Log Message:
2005-10-07  Kristian Høgsberg  <krh at redhat.com>

        * src/cairo-pdf-surface.c: (emit_solid_pattern),
        (emit_surface_pattern), (_cairo_pdf_color_stop_compare),
        (emit_pattern_stops), (emit_linear_pattern), (emit_radial_pattern),
        (emit_pattern), (_cairo_pdf_surface_fill_path),
        (_cairo_pdf_surface_composite_trapezoids),
        (_cairo_pdf_surface_show_glyphs):
        Apply patch from #4672 by Jens Taprogge to implement color stop
        sorting and multiple color stops for gradients.



Index: cairo-pdf-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-pdf-surface.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -u -d -r1.58 -r1.59
--- cairo-pdf-surface.c	19 Aug 2005 21:05:14 -0000	1.58
+++ cairo-pdf-surface.c	7 Oct 2005 20:21:01 -0000	1.59
@@ -51,8 +51,8 @@
  *   could add generation counters to surfaces and remember the stream
  *   ID for a particular generation for a particular surface.
  *
- * - Multi stop gradients.  What are the exponential interpolation
- *   functions, could they be used for gradients?
+ * - Multi stop gradients.  Need to fix support for non-regular spacing
+ *   using Type 3 (Stiching) Functions.
  *
  * - Clipping: must be able to reset clipping
  *
@@ -766,7 +766,7 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
 emit_solid_pattern (cairo_pdf_surface_t *surface,
 		    cairo_solid_pattern_t *pattern)
 {
@@ -782,9 +782,11 @@
 				 pattern->color.green,
 				 pattern->color.blue,
 				 alpha);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
 emit_surface_pattern (cairo_pdf_surface_t	*dst,
 		      cairo_surface_pattern_t		*pattern)
 {
@@ -841,15 +843,38 @@
 				 stream->id, alpha);
 
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static unsigned int
+typedef struct _cairo_pdf_color_stop {
+    cairo_fixed_t	offset;
+    int			id;
+    unsigned char	color_char[4];
+} cairo_pdf_color_stop_t;
+
+static int
+_cairo_pdf_color_stop_compare (const void *elem1, const void *elem2)
+{
+    cairo_pdf_color_stop_t *s1 = (cairo_pdf_color_stop_t *) elem1;
+    cairo_pdf_color_stop_t *s2 = (cairo_pdf_color_stop_t *) elem2;
+	
+    if (s1->offset == s2->offset)
+        /* equal offsets, sort on id */
+	return (s1->id < s2->id) ? -1 : 1;
+    else
+        /* sort on offset */
+        return (s1->offset < s2->offset) ? -1 : 1;
+}
+
+static int
 emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
 {
     cairo_pdf_document_t *document = surface->document;
     cairo_output_stream_t *output = document->output_stream;
     unsigned int function_id;
-    char stops[2][3];
+    cairo_pdf_color_stop_t *stops;
+    int i;
 
     function_id = _cairo_pdf_document_new_object (document);
 
@@ -857,22 +882,40 @@
 				 "%d 0 obj\r\n"
 				 "<< /FunctionType 0\r\n"
 				 "   /Domain [ 0.0 1.0 ]\r\n"
-				 "   /Size [ 2 ]\r\n"
+				 "   /Size [ %d ]\r\n"
 				 "   /BitsPerSample 8\r\n"
 				 "   /Range [ 0.0 1.0 0.0 1.0 0.0 1.0 ]\r\n"
-				 "   /Length 6\r\n"
+				 "   /Length %d\r\n"
 				 ">>\r\n"
 				 "stream\r\n",
-				 function_id);
+				 function_id,
+				 pattern->n_stops,
+				 pattern->n_stops * 3);
 
-    stops[0][0] = pattern->stops[0].color.red   * 0xff + 0.5;
-    stops[0][1] = pattern->stops[0].color.green * 0xff + 0.5;
-    stops[0][2] = pattern->stops[0].color.blue  * 0xff + 0.5;
-    stops[1][0] = pattern->stops[1].color.red   * 0xff + 0.5;
-    stops[1][1] = pattern->stops[1].color.green * 0xff + 0.5;
-    stops[1][2] = pattern->stops[1].color.blue  * 0xff + 0.5;
+    stops = malloc (pattern->n_stops * sizeof(cairo_pdf_color_stop_t));
+    if (!stops) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return 0;
+    }
+    
+    for (i = 0; i < pattern->n_stops; i++) {
+	stops[i].color_char[0] = pattern->stops[i].color.red   * 0xff + 0.5;
+	stops[i].color_char[1] = pattern->stops[i].color.green * 0xff + 0.5;
+	stops[i].color_char[2] = pattern->stops[i].color.blue  * 0xff + 0.5;
+	stops[i].color_char[3] = pattern->stops[i].color.alpha * 0xff + 0.5;
+	stops[i].offset = pattern->stops[i].offset;
+	stops[i].id = i;
+    }
+    
+    /* sort stops in ascending order */
+    qsort (stops, pattern->n_stops, sizeof (cairo_pdf_color_stop_t),
+	   _cairo_pdf_color_stop_compare);
 
-    _cairo_output_stream_write (output, stops, sizeof (stops));
+    for (i = 0; i < pattern->n_stops; i++) {
+	_cairo_output_stream_write (output, stops[i].color_char, 3);
+    }
+
+    free (stops);
 
     _cairo_output_stream_printf (output,
 				 "\r\n"
@@ -882,7 +925,7 @@
     return function_id;
 }
 
-static void
+static cairo_status_t
 emit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern)
 {
     cairo_pdf_document_t *document = surface->document;
@@ -894,6 +937,8 @@
     _cairo_pdf_document_close_stream (document);
 
     function_id = emit_pattern_stops (surface, &pattern->base);
+    if (function_id == 0)
+	return CAIRO_STATUS_NO_MEMORY;
 
     p2u = pattern->base.base.matrix;
     cairo_matrix_invert (&p2u);
@@ -934,9 +979,11 @@
     _cairo_output_stream_printf (output,
 				 "/Pattern cs /res%d scn /a%d gs\r\n",
 				 pattern_id, alpha);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 	
-static void
+static cairo_status_t
 emit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern)
 {
     cairo_pdf_document_t *document = surface->document;
@@ -948,6 +995,8 @@
     _cairo_pdf_document_close_stream (document);
 
     function_id = emit_pattern_stops (surface, &pattern->base);
+    if (function_id == 0)
+	return CAIRO_STATUS_NO_MEMORY;
 
     p2u = pattern->base.base.matrix;
     cairo_matrix_invert (&p2u);
@@ -1001,28 +1050,28 @@
     _cairo_output_stream_printf (output,
 				 "/Pattern cs /res%d scn /a%d gs\r\n",
 				 pattern_id, alpha);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 	
-static void
+static cairo_status_t
 emit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern)
 {
     switch (pattern->type) {
     case CAIRO_PATTERN_SOLID:	
-	emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
-	break;
+	return emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);
 
     case CAIRO_PATTERN_SURFACE:
-	emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
-	break;
+	return emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
 
     case CAIRO_PATTERN_LINEAR:
-	emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
-	break;
+	return emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
 
     case CAIRO_PATTERN_RADIAL:
-	emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
-	break;	    
+	return emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
     }
+
+    ASSERT_NOT_REACHED;
 }
 
 static double
@@ -1121,7 +1170,9 @@
     cairo_status_t status;
     pdf_path_info_t info;
 
-    emit_pattern (surface, pattern);
+    status = emit_pattern (surface, pattern);
+    if (status)
+	return status;
 
     /* After the above switch the current stream should belong to this
      * surface, so no need to _cairo_pdf_surface_ensure_stream() */
@@ -1174,9 +1225,12 @@
     cairo_pdf_surface_t *surface = abstract_dst;
     cairo_pdf_document_t *document = surface->document;
     cairo_output_stream_t *output = document->output_stream;
+    cairo_int_status_t status;
     int i;
 
-    emit_pattern (surface, pattern);
+    status = emit_pattern (surface, pattern);
+    if (status)
+	return status;
 
     /* After the above switch the current stream should belong to this
      * surface, so no need to _cairo_pdf_surface_ensure_stream() */
@@ -1305,6 +1359,7 @@
     cairo_pdf_document_t *document = surface->document;
     cairo_output_stream_t *output = document->output_stream;
     cairo_font_subset_t *pdf_font;
+    cairo_int_status_t status;
     int i, index;
     double det;
 
@@ -1323,7 +1378,9 @@
     if (fabs (det) < 0.000001)
 	return CAIRO_STATUS_SUCCESS;
     
-    emit_pattern (surface, pattern);
+    status = emit_pattern (surface, pattern);
+    if (status)
+	return status;
 
     _cairo_output_stream_printf (output,
 				 "BT /res%u 1 Tf", pdf_font->font_id);



More information about the cairo-commit mailing list