📄 cairo-ps-surface.c
字号:
return surface_pattern_supported ((const cairo_surface_pattern_t *) pattern); return FALSE;}static cairo_bool_t cairo_ps_force_fallbacks = FALSE;/** * _cairo_ps_test_force_fallbacks * * Force the PS surface backend to use image fallbacks for every * operation. * * <note> * This function is <emphasis>only</emphasis> intended for internal * testing use within the cairo distribution. It is not installed in * any public header file. * </note> **/void_cairo_ps_test_force_fallbacks (void){ cairo_ps_force_fallbacks = TRUE;}static cairo_int_status_toperation_supported (cairo_ps_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *pattern){ if (cairo_ps_force_fallbacks) return FALSE; if (! pattern_supported (pattern)) return FALSE; if (_cairo_operator_always_opaque (op)) return TRUE; if (_cairo_operator_always_translucent (op)) return FALSE; return _cairo_pattern_is_opaque (pattern);}static cairo_int_status_t_analyze_operation (cairo_ps_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *pattern){ if (operation_supported (surface, op, pattern)) return CAIRO_STATUS_SUCCESS; else return CAIRO_INT_STATUS_UNSUPPORTED;}/* The "standard" implementation limit for PostScript string sizes is * 65535 characters (see PostScript Language Reference, Appendix * B). We go one short of that because we sometimes need two * characters in a string to represent a single ASCII85 byte, (for the * escape sequences "\\", "\(", and "\)") and we must not split these * across two strings. So we'd be in trouble if we went right to the * limit and one of these escape sequences just happened to land at * the end. */#define STRING_ARRAY_MAX_STRING_SIZE (65535-1)#define STRING_ARRAY_MAX_COLUMN 72typedef struct _string_array_stream { cairo_output_stream_t base; cairo_output_stream_t *output; int column; int string_size;} string_array_stream_t;static cairo_status_t_string_array_stream_write (cairo_output_stream_t *base, const unsigned char *data, unsigned int length){ string_array_stream_t *stream = (string_array_stream_t *) base; unsigned char c; const unsigned char backslash = '\\'; if (length == 0) return CAIRO_STATUS_SUCCESS; while (length--) { if (stream->string_size == 0) { _cairo_output_stream_printf (stream->output, "("); stream->column++; } c = *data++; switch (c) { case '\\': case '(': case ')': _cairo_output_stream_write (stream->output, &backslash, 1); stream->column++; stream->string_size++; break; /* Have to also be careful to never split the final ~> sequence. */ case '~': _cairo_output_stream_write (stream->output, &c, 1); stream->column++; stream->string_size++; length--; c = *data++; break; } _cairo_output_stream_write (stream->output, &c, 1); stream->column++; stream->string_size++; if (stream->string_size >= STRING_ARRAY_MAX_STRING_SIZE) { _cairo_output_stream_printf (stream->output, ")\n"); stream->string_size = 0; stream->column = 0; } if (stream->column >= STRING_ARRAY_MAX_COLUMN) { _cairo_output_stream_printf (stream->output, "\n "); stream->string_size += 2; stream->column = 1; } } return _cairo_output_stream_get_status (stream->output);}static cairo_status_t_string_array_stream_close (cairo_output_stream_t *base){ cairo_status_t status; string_array_stream_t *stream = (string_array_stream_t *) base; _cairo_output_stream_printf (stream->output, ")\n"); status = _cairo_output_stream_get_status (stream->output); return status;}/* A string_array_stream wraps an existing output stream. It takes the * data provided to it and output one or more consecutive string * objects, each within the standard PostScript implementation limit * of 65k characters. * * The strings are each separated by a space character for easy * inclusion within an array object, (but the array delimiters are not * added by the string_array_stream). * * The string array stream is also careful to wrap the output within * STRING_ARRAY_MAX_COLUMN columns (+/- 1). The stream also adds * necessary escaping for special characters within a string, * (specifically '\', '(', and ')'). */static cairo_output_stream_t *_string_array_stream_create (cairo_output_stream_t *output){ string_array_stream_t *stream; stream = malloc (sizeof (string_array_stream_t)); if (stream == NULL) return (cairo_output_stream_t *) &cairo_output_stream_nil; _cairo_output_stream_init (&stream->base, _string_array_stream_write, _string_array_stream_close); stream->output = output; stream->column = 0; stream->string_size = 0; return &stream->base;}/* PS Output - this section handles output of the parts of the meta * surface we can render natively in PS. */static cairo_status_temit_image (cairo_ps_surface_t *surface, cairo_image_surface_t *image, cairo_matrix_t *matrix, char *name){ cairo_status_t status; 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; int x, y, i; cairo_output_stream_t *base85_stream, *string_array_stream; /* PostScript can not represent the alpha channel, so we blend the current image over a white RGB surface to eliminate it. */ if (image->base.status) return image->base.status; 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_fill_rectangle (opaque, CAIRO_OPERATOR_SOURCE, CAIRO_COLOR_WHITE, 0, 0, image->width, image->height); _cairo_surface_composite (CAIRO_OPERATOR_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; } rgb_size = 3 * opaque_image->width * opaque_image->height; rgb = malloc (rgb_size); if (rgb == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto bail1; } i = 0; 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; } } /* XXX: Should fix cairo-lzw to provide a stream-based interface * instead. */ compressed_size = rgb_size; compressed = _cairo_lzw_compress (rgb, &compressed_size); if (compressed == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto bail2; } /* First emit the image data as a base85-encoded string which will * be used as the data source for the image operator later. */ _cairo_output_stream_printf (surface->stream, "/%sData [\n", name); string_array_stream = _string_array_stream_create (surface->stream); base85_stream = _cairo_base85_stream_create (string_array_stream); _cairo_output_stream_write (base85_stream, compressed, compressed_size); _cairo_output_stream_destroy (base85_stream); _cairo_output_stream_destroy (string_array_stream); _cairo_output_stream_printf (surface->stream, "] def\n"); _cairo_output_stream_printf (surface->stream, "/%sDataIndex 0 def\n", name); _cairo_output_stream_printf (surface->stream, "/%s {\n" " /DeviceRGB setcolorspace\n" " <<\n" " /ImageType 1\n" " /Width %d\n" " /Height %d\n" " /BitsPerComponent 8\n" " /Decode [ 0 1 0 1 0 1 ]\n" " /DataSource {\n" " %sData %sDataIndex get\n" " /%sDataIndex %sDataIndex 1 add def\n" " %sDataIndex %sData length 1 sub gt { /%sDataIndex 0 def } if\n" " } /ASCII85Decode filter /LZWDecode filter\n" " /ImageMatrix [ %f %f %f %f %f %f ]\n" " >>\n" " image\n" "} def\n", name, opaque_image->width, opaque_image->height, name, name, name, name, name, name, name, matrix->xx, matrix->yx, matrix->xy, matrix->yy, 0.0, 0.0); status = CAIRO_STATUS_SUCCESS; free (compressed); bail2: free (rgb); bail1: if (opaque_image != image) cairo_surface_destroy (opaque); bail0: return status;}static voidemit_solid_pattern (cairo_ps_surface_t *surface, cairo_solid_pattern_t *pattern){ if (color_is_gray (&pattern->color)) _cairo_output_stream_printf (surface->stream, "%f G\n", pattern->color.red); else _cairo_output_stream_printf (surface->stream, "%f %f %f R\n", pattern->color.red, pattern->color.green, pattern->color.blue);}static voidemit_surface_pattern (cairo_ps_surface_t *surface, cairo_surface_pattern_t *pattern, double x, double y){ cairo_rectangle_int16_t extents; if (_cairo_surface_is_meta (pattern->surface)) { _cairo_output_stream_printf (surface->stream, "/MyPattern {\n"); _cairo_meta_surface_replay (pattern->surface, &surface->base); extents.width = surface->width; extents.height = surface->height; _cairo_output_stream_printf (surface->stream, "} bind def\n"); } else { cairo_image_surface_t *image; void *image_extra; cairo_status_t status; cairo_matrix_t inverse = pattern->base.matrix; cairo_matrix_invert (&inverse); status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra); assert (status == CAIRO_STATUS_SUCCESS); _cairo_pattern_get_extents (&pattern->base, &extents); emit_image (surface, image, &pattern->base.matrix, "MyPattern"); _cairo_surface_release_source_image (pattern->surface, image, image_extra); } _cairo_output_stream_printf (surface->stream, "%f %f translate\n", x, y); _cairo_output_stream_printf (surface->stream, "<< /PatternType 1\n" " /PaintType 1\n" " /TilingType 1\n"); _cairo_output_stream_printf (surface->stream, " /BBox [0 0 %d %d]\n", extents.width, extents.height); _cairo_output_stream_printf (surface->stream, " /XStep %d /YStep %d\n", extents.width, extents.height); _cairo_output_stream_printf (surface->stream, " /PaintProc { MyPattern } bind\n" ">> matrix makepattern setpattern\n"); _cairo_output_stream_printf (surface->stream, "-%f -%f translate\n", x, y);}static voidemit_linear_pattern (cairo_ps_surface_t *surface, cairo_linear_pattern_t *pattern){ /* XXX: NYI */}static voidemit_radial_pattern (cairo_ps_surface_t *surface, cairo_radial_pattern_t *pattern){ /* XXX: NYI */}static voidemit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern, double x, double y){ /* FIXME: We should keep track of what pattern is currently set in * the postscript file and only emit code if we're setting a * different pattern. */ switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern); break; case CAIRO_PATTERN_TYPE_SURFACE: emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, x, y); break; case CAIRO_PATTERN_TYPE_LINEAR: emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); break; case CAIRO_PATTERN_TYPE_RADIAL: emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern); break; }}static cairo_int_status_t_cairo_ps_surface_intersect_clip_path (void *abstract_surface, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -