⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-ps-surface.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -