mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 14:38:13 +02:00
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. reviewed by: cworth
This commit is contained in:
parent
5198e71eaf
commit
235838d49f
2 changed files with 121 additions and 53 deletions
28
ChangeLog
28
ChangeLog
|
|
@ -1,3 +1,31 @@
|
|||
2005-08-24 Keith Packard <keithp@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.
|
||||
|
||||
2005-08-24 Keith Packard <keithp@keithp.com>
|
||||
|
||||
reviewed by: cworth
|
||||
|
|
|
|||
|
|
@ -102,6 +102,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
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 @@ cairo_ps_surface_set_dpi (cairo_surface_t *surface,
|
|||
|
||||
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
|
||||
|
|
@ -631,6 +635,12 @@ color_is_gray (cairo_color_t *color)
|
|||
fabs (color->red - color->blue) < epsilon);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -639,7 +649,7 @@ pattern_is_translucent (cairo_pattern_t *abstract_pattern)
|
|||
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 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
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 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
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 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
}
|
||||
|
||||
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 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
/* 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 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
" /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 @@ emit_image (cairo_ps_surface_t *surface,
|
|||
bail2:
|
||||
free (rgb);
|
||||
bail1:
|
||||
cairo_surface_destroy (opaque);
|
||||
if (opaque_image != image)
|
||||
cairo_surface_destroy (opaque);
|
||||
bail0:
|
||||
return status;
|
||||
}
|
||||
|
|
@ -863,7 +879,7 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
* 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 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
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 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
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 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
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 @@ _ps_output_composite (cairo_operator_t operator,
|
|||
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 @@ _ps_output_fill_rectangles (void *abstract_surface,
|
|||
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 @@ _ps_output_fill_rectangles (void *abstract_surface,
|
|||
_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 @@ _ps_output_composite_trapezoids (cairo_operator_t operator,
|
|||
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 @@ _ps_output_composite_trapezoids (cairo_operator_t operator,
|
|||
|
||||
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 @@ _ps_output_path_move_to (void *closure, cairo_point_t *point)
|
|||
_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 @@ _ps_output_path_line_to (void *closure, cairo_point_t *point)
|
|||
_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 @@ _ps_output_path_curve_to (void *closure,
|
|||
_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 @@ _ps_output_intersect_clip_path (void *abstract_surface,
|
|||
|
||||
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 @@ _ps_output_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
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 @@ _ps_output_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
_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_fill_path (cairo_operator_t operator,
|
|||
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 @@ _ps_output_fill_path (cairo_operator_t operator,
|
|||
|
||||
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_ps_surface_render_page (cairo_ps_surface_t *surface,
|
|||
|
||||
_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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue