[cairo-commit] cairo/src cairo-ps-surface.c,1.49,1.50

Keith Packard commit at pdx.freedesktop.org
Wed Aug 24 01:47:15 PDT 2005


Committed by: keithp

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

Modified Files:
	cairo-ps-surface.c 
Log Message:
2005-08-24  Keith Packard  <keithp at keithp.com>

	reviewed by: cworth

	* src/cairo-ps-surface.c:
	(_cairo_ps_surface_create_for_stream_internal),
	(cairo_ps_surface_set_dpi), (color_is_translucent),
	(pattern_is_translucent), (emit_image), (_ps_output_composite),
	(_ps_output_fill_rectangles), (_ps_output_composite_trapezoids),
	(_ps_output_path_move_to), (_ps_output_path_line_to),
	(_ps_output_path_curve_to), (_ps_output_intersect_clip_path),
	(_ps_output_show_glyphs), (_ps_output_fill_path),
	(_cairo_ps_surface_render_page):
	
	Use new device_x_scale/device_y_scale surface fields
	to set the device coordinate space to the nominal pixels.

	Treat more alpha values as translucent (up to 0.999)

	Fix emit_image to actually use a temporary image
	when necessary.

	Change PS coordinate space to match cairo (top-down),
	adjust PS output to use new space.

	Find more cases where PS output was not supported and
	fall back to image surface.


Index: cairo-ps-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ps-surface.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- cairo-ps-surface.c	23 Aug 2005 03:43:23 -0000	1.49
+++ cairo-ps-surface.c	24 Aug 2005 08:47:13 -0000	1.50
@@ -102,6 +102,8 @@
     surface->height = height;
     surface->x_dpi = PS_SURFACE_DPI_DEFAULT;
     surface->y_dpi = PS_SURFACE_DPI_DEFAULT;
+    surface->base.device_x_scale = surface->x_dpi / 72.0;
+    surface->base.device_y_scale = surface->y_dpi / 72.0;
 
     surface->current_page = _cairo_meta_surface_create (width,
 							height);
@@ -173,6 +175,8 @@
 
     ps_surface->x_dpi = x_dpi;    
     ps_surface->y_dpi = y_dpi;    
+    ps_surface->base.device_x_scale = ps_surface->x_dpi / 72.0;
+    ps_surface->base.device_y_scale = ps_surface->y_dpi / 72.0;
 }
 
 static cairo_status_t
@@ -632,6 +636,12 @@
 }
 
 static cairo_bool_t
+color_is_translucent (const cairo_color_t *color)
+{
+    return color->alpha < 0.999;
+}
+
+static cairo_bool_t
 pattern_is_translucent (cairo_pattern_t *abstract_pattern)
 {
     cairo_pattern_union_t *pattern;
@@ -639,7 +649,7 @@
     pattern = (cairo_pattern_union_t *) abstract_pattern;
     switch (pattern->base.type) {
     case CAIRO_PATTERN_SOLID:
-	return pattern->solid.color.alpha < 0.9;
+	return color_is_translucent (&pattern->solid.color);
     case CAIRO_PATTERN_SURFACE:
     case CAIRO_PATTERN_LINEAR:
     case CAIRO_PATTERN_RADIAL:
@@ -679,6 +689,7 @@
     unsigned char *rgb, *compressed;
     unsigned long rgb_size, compressed_size;
     cairo_surface_t *opaque;
+    cairo_image_surface_t *opaque_image;
     cairo_pattern_union_t pattern;
     cairo_matrix_t d2i;
     int x, y, i;
@@ -689,31 +700,35 @@
     if (image->base.status)
 	return image->base.status;
 
-    opaque = _cairo_surface_create_similar_solid (&image->base,
-						  CAIRO_CONTENT_COLOR,
-						  image->width,
-						  image->height, 
-						  CAIRO_COLOR_WHITE);
-    if (opaque->status) {
-	status = CAIRO_STATUS_NO_MEMORY;
-	goto bail0;
+    if (image->format != CAIRO_FORMAT_RGB24) {
+	opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+					     image->width,
+					     image->height);
+	if (opaque->status) {
+	    status = CAIRO_STATUS_NO_MEMORY;
+	    goto bail0;
+	}
+    
+	_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
+    
+	_cairo_surface_composite (CAIRO_OPERATOR_DEST_OVER,
+				  &pattern.base,
+				  NULL,
+				  opaque,
+				  0, 0,
+				  0, 0,
+				  0, 0,
+				  image->width,
+				  image->height);
+    
+	_cairo_pattern_fini (&pattern.base);
+	opaque_image = (cairo_image_surface_t *) opaque;
+    } else {
+	opaque = &image->base;
+	opaque_image = image;
     }
 
-    _cairo_pattern_init_for_surface (&pattern.surface, &image->base);
-
-    _cairo_surface_composite (CAIRO_OPERATOR_DEST_OVER,
-			      &pattern.base,
-			      NULL,
-			      opaque,
-			      0, 0,
-			      0, 0,
-			      0, 0,
-			      image->width,
-			      image->height);
-
-    _cairo_pattern_fini (&pattern.base);
-
-    rgb_size = 3 * image->width * image->height;
+    rgb_size = 3 * opaque_image->width * opaque_image->height;
     rgb = malloc (rgb_size);
     if (rgb == NULL) {
 	status = CAIRO_STATUS_NO_MEMORY;
@@ -721,9 +736,9 @@
     }
 
     i = 0;
-    for (y = 0; y < image->height; y++) {
-	pixman_bits_t *pixel = (pixman_bits_t *) (image->data + y * image->stride);
-	for (x = 0; x < image->width; x++, pixel++) {
+    for (y = 0; y < opaque_image->height; y++) {
+	pixman_bits_t *pixel = (pixman_bits_t *) (opaque_image->data + y * opaque_image->stride);
+	for (x = 0; x < opaque_image->width; x++, pixel++) {
 	    rgb[i++] = (*pixel & 0x00ff0000) >> 16;
 	    rgb[i++] = (*pixel & 0x0000ff00) >>  8;
 	    rgb[i++] = (*pixel & 0x000000ff) >>  0;
@@ -739,7 +754,7 @@
     /* matrix transforms from user space to image space.  We need to
      * transform from device space to image space to compensate for
      * postscripts coordinate system. */
-    cairo_matrix_init (&d2i, 1, 0, 0, -1, 0, surface->height);
+    cairo_matrix_init (&d2i, 1, 0, 0, 1, 0, 0);
     cairo_matrix_multiply (&d2i, &d2i, matrix);
 
     _cairo_output_stream_printf (surface->stream,
@@ -754,8 +769,8 @@
 				 "	/ImageMatrix [ %f %f %f %f %f %f ]\n"
 				 ">>\n"
 				 "image\n",
-				 image->width,
-				 image->height,
+				 opaque_image->width,
+				 opaque_image->height,
 				 d2i.xx, d2i.yx,
 				 d2i.xy, d2i.yy,
 				 d2i.x0, d2i.y0);
@@ -771,7 +786,8 @@
  bail2:
     free (rgb);
  bail1:
-    cairo_surface_destroy (opaque);
+    if (opaque_image != image)
+	cairo_surface_destroy (opaque);
  bail0:
     return status;
 }
@@ -863,7 +879,7 @@
 	 * need pixmap fallbacks for this, though. */
 	_cairo_output_stream_printf (stream,
 				     "%% _ps_output_composite: with mask\n");
-	return CAIRO_STATUS_SUCCESS;
+	goto bail;
     }
 
     status = CAIRO_STATUS_SUCCESS;
@@ -871,7 +887,7 @@
     case CAIRO_PATTERN_SOLID:
 	_cairo_output_stream_printf (stream,
 				     "%% _ps_output_composite: solid\n");
-	break;
+	goto bail;
 
     case CAIRO_PATTERN_SURFACE:
 	surface_pattern = (cairo_surface_pattern_t *) src_pattern;
@@ -879,7 +895,7 @@
 	if (src_pattern->extend != CAIRO_EXTEND_NONE) {
 	    _cairo_output_stream_printf (stream,
 					 "%% _ps_output_composite: repeating image\n");
-	    break;
+	    goto bail;
 	}
 	    
 
@@ -889,7 +905,7 @@
 	if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
 	    _cairo_output_stream_printf (stream,
 					 "%% _ps_output_composite: src_pattern not available as image\n");
-	    break;
+	    goto bail;
 	} else if (status) {
 	    break;
 	}
@@ -902,10 +918,12 @@
     case CAIRO_PATTERN_RADIAL:
 	_cairo_output_stream_printf (stream,
 				     "%% _ps_output_composite: gradient\n");
-	break;
+	goto bail;
     }
 
     return status;
+bail:
+    return _ps_output_add_fallback_area (surface, dst_x, dst_y, width, height);
 }
 
 static cairo_int_status_t
@@ -920,6 +938,24 @@
     cairo_solid_pattern_t solid;
     int i;
 
+    if (!num_rects)
+	return CAIRO_STATUS_SUCCESS;
+    
+    if (color_is_translucent (color)) {
+	int min_x = rects[0].x;
+	int min_y = rects[0].y;
+	int max_x = rects[0].x + rects[0].width;
+	int max_y = rects[0].y + rects[0].height;
+
+	for (i = 1; i < num_rects; i++) {
+	    if (rects[i].x < min_x) min_x = rects[i].x;
+	    if (rects[i].y < min_y) min_y = rects[i].y;
+	    if (rects[i].x + rects[i].width > max_x) max_x = rects[i].x + rects[i].width;
+	    if (rects[i].y + rects[i].height > max_y) max_y = rects[i].y + rects[i].height;
+	}
+	return _ps_output_add_fallback_area (surface, min_x, min_y, max_x - min_x, max_y - min_y);
+    }
+	
     _cairo_output_stream_printf (stream,
 				 "%% _ps_output_fill_rectangles\n");
 
@@ -930,9 +966,8 @@
     _cairo_output_stream_printf (stream, "[");
     for (i = 0; i < num_rects; i++) {
       _cairo_output_stream_printf (stream,
-				   " %d %f %d %d",
-				   rects[i].x,
-				   (double)(surface->parent->height - rects[i].y - rects[i].height),
+				   " %d %d %d %d",
+				   rects[i].x, rects[i].y,
 				   rects[i].width, rects[i].height);
     }
 
@@ -983,8 +1018,8 @@
 	left_x2  = intersect (&traps[i].left, traps[i].bottom);
 	right_x1 = intersect (&traps[i].right, traps[i].top);
 	right_x2 = intersect (&traps[i].right, traps[i].bottom);
-	top      = surface->parent->height - _cairo_fixed_to_double (traps[i].top);
-	bottom   = surface->parent->height - _cairo_fixed_to_double (traps[i].bottom);
+	top      = _cairo_fixed_to_double (traps[i].top);
+	bottom   = _cairo_fixed_to_double (traps[i].bottom);
 
 	_cairo_output_stream_printf
 	    (stream,
@@ -1004,7 +1039,6 @@
 
 typedef struct
 {
-    double height;
     cairo_output_stream_t *output_stream;
     cairo_bool_t has_current_point;
 } ps_output_path_info_t;
@@ -1017,7 +1051,7 @@
     _cairo_output_stream_printf (info->output_stream,
 				 "%f %f moveto ",
 				 _cairo_fixed_to_double (point->x),
-				 info->height - _cairo_fixed_to_double (point->y));
+				 _cairo_fixed_to_double (point->y));
     info->has_current_point = TRUE;
     
     return CAIRO_STATUS_SUCCESS;
@@ -1037,7 +1071,7 @@
     _cairo_output_stream_printf (info->output_stream,
 				 "%f %f %s ",
 				 _cairo_fixed_to_double (point->x),
-				 info->height - _cairo_fixed_to_double (point->y),
+				 _cairo_fixed_to_double (point->y),
 				 ps_operator);
     info->has_current_point = TRUE;
 
@@ -1055,11 +1089,11 @@
     _cairo_output_stream_printf (info->output_stream,
 				 "%f %f %f %f %f %f curveto ",
 				 _cairo_fixed_to_double (b->x),
-				 info->height - _cairo_fixed_to_double (b->y),
+				 _cairo_fixed_to_double (b->y),
 				 _cairo_fixed_to_double (c->x),
-				 info->height - _cairo_fixed_to_double (c->y),
+				 _cairo_fixed_to_double (c->y),
 				 _cairo_fixed_to_double (d->x),
-				 info->height - _cairo_fixed_to_double (d->y));
+				 _cairo_fixed_to_double (d->y));
     
     return CAIRO_STATUS_SUCCESS;
 }
@@ -1099,7 +1133,6 @@
 
     info.output_stream = stream;
     info.has_current_point = FALSE;
-    info.height = surface->parent->height;
 
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
@@ -1171,7 +1204,7 @@
 				 scaled_font->scale.xx,
 				 scaled_font->scale.yx,
 				 scaled_font->scale.xy,
-				 scaled_font->scale.yy);
+				 -scaled_font->scale.yy);
 
     /* FIXME: Need to optimize per glyph code.  Should detect when
      * glyphs share the same baseline and when the spacing corresponds
@@ -1182,7 +1215,7 @@
 	_cairo_output_stream_printf (stream,
 				     "%f %f moveto (\\%o) show\n",
 				     glyphs[i].x,
-				     surface->parent->height - glyphs[i].y,
+				     glyphs[i].y,
 				     subset_index);
 	
     }
@@ -1204,6 +1237,11 @@
     ps_output_path_info_t info;
     const char *ps_operator;
 
+    if (pattern_is_translucent (pattern))
+	return _ps_output_add_fallback_area (surface,
+					     0, 0,
+					     surface->parent->width,
+					     surface->parent->height);
     _cairo_output_stream_printf (stream,
 				 "%% _ps_output_fill_path\n");
 
@@ -1211,7 +1249,6 @@
 
     info.output_stream = stream;
     info.has_current_point = FALSE;
-    info.height = surface->parent->height;
 
     status = _cairo_path_fixed_interpret (path,
 					  CAIRO_DIRECTION_FORWARD,
@@ -1333,8 +1370,11 @@
 
     _cairo_output_stream_printf (surface->stream,
 				 "%%%%Page: %d\n"
-				 "gsave\n",
-				 page_number);
+				 "gsave %f %f translate %f %f scale \n",
+				 page_number,
+				 0.0, surface->height,
+				 1.0/surface->base.device_x_scale,
+				 -1.0/surface->base.device_y_scale);
 
     ps_output = _ps_output_surface_create (surface);
     if (ps_output->status)



More information about the cairo-commit mailing list