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

📄 cairo-pdf-surface.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 5 页
字号:
	_cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_TYPE_MISMATCH);	return;    }    pdf_surface->width = width_in_points;    pdf_surface->height = height_in_points;}static void_cairo_pdf_surface_clear (cairo_pdf_surface_t *surface){    _cairo_array_truncate (&surface->streams, 0);}static cairo_surface_t *_cairo_pdf_surface_create_similar (void		       *abstract_src,				   cairo_content_t	content,				   int			width,				   int			height){    cairo_format_t format = _cairo_format_from_content (content);    /* Just return an image for now, until PDF surface can be used     * as source. */    return cairo_image_surface_create (format, width, height);}static cairo_pdf_resource_t_cairo_pdf_surface_open_stream (cairo_pdf_surface_t	*surface,				const char		*fmt,				...){    va_list ap;    surface->current_stream.active = TRUE;    surface->current_stream.self = _cairo_pdf_surface_new_object (surface);    surface->current_stream.length = _cairo_pdf_surface_new_object (surface);    _cairo_output_stream_printf (surface->output,				 "%d 0 obj\r\n"				 "<< /Length %d 0 R\r\n",				 surface->current_stream.self.id,				 surface->current_stream.length.id);    if (fmt != NULL) {	va_start (ap, fmt);	_cairo_output_stream_vprintf (surface->output, fmt, ap);	va_end (ap);    }    _cairo_output_stream_printf (surface->output,				 ">>\r\n"				 "stream\r\n");    surface->current_stream.start_offset = _cairo_output_stream_get_position (surface->output);    return surface->current_stream.self;}static void_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface){    long length;    if (! surface->current_stream.active)	return;    length = _cairo_output_stream_get_position (surface->output) -	surface->current_stream.start_offset;    _cairo_output_stream_printf (surface->output,				 "endstream\r\n"				 "endobj\r\n");    _cairo_pdf_surface_update_object (surface,				      surface->current_stream.length);    _cairo_output_stream_printf (surface->output,				 "%d 0 obj\r\n"				 "   %ld\r\n"				 "endobj\r\n",				 surface->current_stream.length.id,				 length);    surface->current_stream.active = FALSE;}static cairo_status_t_cairo_pdf_surface_finish (void *abstract_surface){    cairo_status_t status;    cairo_pdf_surface_t *surface = abstract_surface;    long offset;    cairo_pdf_resource_t info, catalog;    _cairo_pdf_surface_close_stream (surface);    _cairo_pdf_surface_emit_font_subsets (surface);    _cairo_pdf_surface_write_pages (surface);    info = _cairo_pdf_surface_write_info (surface);    catalog = _cairo_pdf_surface_write_catalog (surface);    offset = _cairo_pdf_surface_write_xref (surface);    _cairo_output_stream_printf (surface->output,				 "trailer\r\n"				 "<< /Size %d\r\n"				 "   /Root %d 0 R\r\n"				 "   /Info %d 0 R\r\n"				 ">>\r\n",				 surface->next_available_resource.id,				 catalog.id,				 info.id);    _cairo_output_stream_printf (surface->output,				 "startxref\r\n"				 "%ld\r\n"				 "%%%%EOF\r\n",				 offset);    status = _cairo_output_stream_get_status (surface->output);    _cairo_output_stream_destroy (surface->output);    _cairo_array_fini (&surface->objects);    _cairo_array_fini (&surface->pages);    _cairo_array_fini (&surface->patterns);    _cairo_array_fini (&surface->xobjects);    _cairo_array_fini (&surface->streams);    _cairo_array_fini (&surface->alphas);    if (surface->font_subsets) {	_cairo_scaled_font_subsets_destroy (surface->font_subsets);	surface->font_subsets = NULL;    }    _cairo_array_fini (&surface->fonts);    return status;}static void_cairo_pdf_surface_pause_content_stream (cairo_pdf_surface_t *surface){    _cairo_pdf_surface_close_stream (surface);}static void_cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface){    cairo_pdf_resource_t stream;    stream = _cairo_pdf_surface_open_stream (surface,					     "   /Type /XObject\r\n"					     "   /Subtype /Form\r\n"					     "   /BBox [ 0 0 %f %f ]\r\n",					     surface->width,					     surface->height);    _cairo_pdf_surface_add_stream (surface, stream);}static cairo_int_status_t_cairo_pdf_surface_start_page (void *abstract_surface){    cairo_pdf_surface_t *surface = abstract_surface;    cairo_pdf_resource_t stream;    stream = _cairo_pdf_surface_open_stream (surface,					     "   /Type /XObject\r\n"					     "   /Subtype /Form\r\n"					     "   /BBox [ 0 0 %f %f ]\r\n",					     surface->width,					     surface->height);    _cairo_pdf_surface_add_stream (surface, stream);    _cairo_output_stream_printf (surface->output,				 "1 0 0 -1 0 %f cm\r\n",				 surface->height);    return CAIRO_STATUS_SUCCESS;}static void *compress_dup (const void *data, unsigned long data_size,	      unsigned long *compressed_size){    void *compressed;    /* Bound calculation taken from zlib. */    *compressed_size = data_size + (data_size >> 12) + (data_size >> 14) + 11;    compressed = malloc (*compressed_size);    if (compressed == NULL)	return NULL;    compress (compressed, compressed_size, data, data_size);    return compressed;}/* Emit alpha channel from the image into the given data, providing * and id that can be used to reference the resulting SMask object. * * In the case that the alpha channel happens to be all opaque, then * no SMask object will be emitted and *id_ret will be set to 0. */static cairo_status_temit_smask (cairo_pdf_surface_t		*surface,	    cairo_image_surface_t	*image,	    cairo_pdf_resource_t	*stream_ret){    cairo_status_t status = CAIRO_STATUS_SUCCESS;    char *alpha, *alpha_compressed;    unsigned long alpha_size, alpha_compressed_size;    pixman_bits_t *pixel;    int i, x, y;    cairo_bool_t opaque;    uint8_t a;    /* This is the only image format we support, which simplfies things. */    assert (image->format == CAIRO_FORMAT_ARGB32);    alpha_size = image->height * image->width;    alpha = malloc (alpha_size);    if (alpha == NULL) {	status = CAIRO_STATUS_NO_MEMORY;	goto CLEANUP;    }    opaque = TRUE;    i = 0;    for (y = 0; y < image->height; y++) {	pixel = (pixman_bits_t *) (image->data + y * image->stride);	for (x = 0; x < image->width; x++, pixel++) {	    a = (*pixel & 0xff000000) >> 24;	    alpha[i++] = a;	    if (a != 0xff)		opaque = FALSE;	}    }    /* Bail out without emitting smask if it's all opaque. */    if (opaque) {	stream_ret->id = 0;	goto CLEANUP_ALPHA;    }    alpha_compressed = compress_dup (alpha, alpha_size, &alpha_compressed_size);    if (alpha_compressed == NULL) {	status = CAIRO_STATUS_NO_MEMORY;	goto CLEANUP_ALPHA;    }    *stream_ret = _cairo_pdf_surface_open_stream (surface,						  "   /Type /XObject\r\n"						  "   /Subtype /Image\r\n"						  "   /Width %d\r\n"						  "   /Height %d\r\n"						  "   /ColorSpace /DeviceGray\r\n"						  "   /BitsPerComponent 8\r\n"						  "   /Filter /FlateDecode\r\n",						  image->width, image->height);    _cairo_output_stream_write (surface->output, alpha_compressed, alpha_compressed_size);    _cairo_output_stream_printf (surface->output, "\r\n");    _cairo_pdf_surface_close_stream (surface);    free (alpha_compressed); CLEANUP_ALPHA:    free (alpha); CLEANUP:    return status;}/* Emit image data into the given surface, providing a resource that * can be used to reference the data in image_ret. */static cairo_status_temit_image (cairo_pdf_surface_t		*surface,	    cairo_image_surface_t	*image,	    cairo_pdf_resource_t	*image_ret){    cairo_status_t status = CAIRO_STATUS_SUCCESS;    char *rgb, *compressed;    unsigned long rgb_size, compressed_size;    pixman_bits_t *pixel;    int i, x, y;    cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */    cairo_bool_t need_smask;    /* XXX: Need to rewrite this as a pdf_surface function with     * pause/resume of content_stream, (currently the only caller does     * the pause/resume already, but that is expected to change in the     * future). */    /* These are the only image formats we currently support, (which     * makes things a lot simpler here). This is enforced through     * _analyze_operation which only accept source surfaces of     * CONTENT_COLOR or CONTENT_COLOR_ALPHA.     */    assert (image->format == CAIRO_FORMAT_RGB24 || image->format == CAIRO_FORMAT_ARGB32);    rgb_size = image->height * image->width * 3;    rgb = malloc (rgb_size);    if (rgb == NULL) {	status = CAIRO_STATUS_NO_MEMORY;	goto CLEANUP;    }    i = 0;    for (y = 0; y < image->height; y++) {	pixel = (pixman_bits_t *) (image->data + y * image->stride);	for (x = 0; x < image->width; x++, pixel++) {	    /* XXX: We're un-premultiplying alpha here. My reading of the PDF	     * specification suggests that we should be able to avoid having	     * to do this by filling in the SMask's Matte dictionary	     * appropriately, but my attempts to do that so far have	     * failed. */	    if (image->format == CAIRO_FORMAT_ARGB32) {		uint8_t a;		a = (*pixel & 0xff000000) >> 24;		if (a == 0) {		    rgb[i++] = 0;		    rgb[i++] = 0;		    rgb[i++] = 0;		} else {		    rgb[i++] = (((*pixel & 0xff0000) >> 16) * 255 + a / 2) / a;		    rgb[i++] = (((*pixel & 0x00ff00) >>  8) * 255 + a / 2) / a;		    rgb[i++] = (((*pixel & 0x0000ff) >>  0) * 255 + a / 2) / a;		}	    } else {		rgb[i++] = (*pixel & 0x00ff0000) >> 16;		rgb[i++] = (*pixel & 0x0000ff00) >>  8;		rgb[i++] = (*pixel & 0x000000ff) >>  0;	    }	}    }    compressed = compress_dup (rgb, rgb_size, &compressed_size);    if (compressed == NULL) {	status = CAIRO_STATUS_NO_MEMORY;	goto CLEANUP_RGB;    }    need_smask = FALSE;    if (image->format == CAIRO_FORMAT_ARGB32) {	status = emit_smask (surface, image, &smask);	if (status)	    goto CLEANUP_COMPRESSED;	if (smask.id)	    need_smask = TRUE;    }#define IMAGE_DICTIONARY	"   /Type /XObject\r\n"		\				"   /Subtype /Image\r\n"	\				"   /Width %d\r\n"		\				"   /Height %d\r\n"		\				"   /ColorSpace /DeviceRGB\r\n"	\				"   /BitsPerComponent 8\r\n"	\				"   /Filter /FlateDecode\r\n"    if (need_smask)	*image_ret = _cairo_pdf_surface_open_stream (surface,						     IMAGE_DICTIONARY						     "   /SMask %d 0 R\r\n",						     image->width, image->height,						     smask.id);    else	*image_ret = _cairo_pdf_surface_open_stream (surface,						     IMAGE_DICTIONARY,						     image->width, image->height);#undef IMAGE_DICTIONARY    _cairo_output_stream_write (surface->output, compressed, compressed_size);    _cairo_output_stream_printf (surface->output, "\r\n");    _cairo_pdf_surface_close_stream (surface); CLEANUP_COMPRESSED:    free (compressed); CLEANUP_RGB:    free (rgb); CLEANUP:    return status;}static cairo_status_temit_solid_pattern (cairo_pdf_surface_t *surface,		    cairo_solid_pattern_t *pattern){    cairo_pdf_resource_t alpha;    alpha = _cairo_pdf_surface_add_alpha (surface, pattern->color.alpha);    /* With some work, we could separate the stroking     * or non-stroking color here as actually needed. */    _cairo_output_stream_printf (surface->output,				 "%f %f %f RG "				 "%f %f %f rg "				 "/a%d gs\r\n",				 pattern->color.red,				 pattern->color.green,				 pattern->color.blue,				 pattern->color.red,				 pattern->color.green,				 pattern->color.blue,				 alpha.id);    return CAIRO_STATUS_SUCCESS;}static cairo_status_temit_surface_pattern (cairo_pdf_surface_t	*surface,		      cairo_surface_pattern_t	*pattern){    cairo_pdf_resource_t stream;    cairo_image_surface_t *image;    void *image_extra;    cairo_status_t status = CAIRO_STATUS_SUCCESS;    cairo_pdf_resource_t alpha, image_resource = {0}; /* squelch bogus compiler warning */    cairo_matrix_t cairo_p2d, pdf_p2d;    cairo_extend_t extend = cairo_pattern_get_extend (&pattern->base);    int xstep, ystep;    cairo_rectangle_int16_t surface_extents;    /* XXX: Should do something clever here for PDF source surfaces ? */    _cairo_pdf_surface_pause_content_stream (surface);    status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);    if (status)	return status;    status = emit_image (surface, image, &image_resource);    if (status)	goto BAIL;    _cairo_surface_get_extents (&surface->base, &surface_extents);    /* In PDF, (as far as I can tell), all patterns are repeating. So     * we support cairo's EXTEND_NONE semantics by setting the repeat

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -