[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