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

📄 cairo-pdf-surface.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 5 页
字号:
     * step size to the larger of the image size and the extents of     * the destination surface. That way we guarantee the pattern will     * not repeat.     */    switch (extend) {    case CAIRO_EXTEND_NONE:	xstep = MAX(image->width, surface_extents.width);	ystep = MAX(image->height, surface_extents.height);	break;    case CAIRO_EXTEND_REPEAT:	xstep = image->width;	ystep = image->height;	break;    default:	ASSERT_NOT_REACHED; /* all others should be analyzed away */	xstep = 0;	ystep = 0;    }    /* At this point, (that is, within the surface backend interface),     * the pattern's matrix maps from cairo's device space to cairo's     * pattern space, (both with their origin at the upper-left, and     * cairo's pattern space of size width,height).     *     * Then, we must emit a PDF pattern object that maps from its own     * pattern space, (which has a size that we establish in the BBox     * dictionary entry), to the PDF page's *initial* space, (which     * does not benefit from the Y-axis flipping matrix that we emit     * on each page). So the PDF patterns patrix maps from a     * (width,height) pattern space to a device space with the origin     * in the lower-left corner.     *     * So to handle all of that, we start with an identity matrix for     * the PDF pattern to device matrix. We translate it up by the     * image height then flip it in the Y direction, (moving us from     * the PDF origin to cairo's origin). We then multiply in the     * inverse of the cairo pattern matrix, (since it maps from device     * to pattern, while we're setting up pattern to device). Finally,     * we translate back down by the image height and flip again to     * end up at the lower-left origin that PDF expects.     *     * Additionally, within the stream that paints the pattern itself,     * we are using a PDF image object that has a size of (1,1) so we     * have to scale it up by the image width and height to fill our     * pattern cell.     */    cairo_p2d = pattern->base.matrix;    cairo_matrix_invert (&cairo_p2d);    cairo_matrix_init_identity (&pdf_p2d);    cairo_matrix_translate (&pdf_p2d, 0.0, surface_extents.height);    cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);    cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);    cairo_matrix_translate (&pdf_p2d, 0.0, image->height);    cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);    stream = _cairo_pdf_surface_open_stream (surface,					     "   /BBox [0 0 %d %d]\r\n"					     "   /XStep %d\r\n"					     "   /YStep %d\r\n"					     "   /PatternType 1\r\n"					     "   /TilingType 1\r\n"					     "   /PaintType 1\r\n"					     "   /Matrix [ %f %f %f %f %f %f ]\r\n"					     "   /Resources << /XObject << /res%d %d 0 R >> >>\r\n",					     image->width, image->height,					     xstep, ystep,					     pdf_p2d.xx, pdf_p2d.yx,					     pdf_p2d.xy, pdf_p2d.yy,					     pdf_p2d.x0, pdf_p2d.y0,					     image_resource.id,					     image_resource.id);    _cairo_output_stream_printf (surface->output,				 "q %d 0 0 %d 0 0 cm /res%d Do Q\r\n",				 image->width, image->height,				 image_resource.id);    _cairo_pdf_surface_close_stream (surface);    _cairo_pdf_surface_resume_content_stream (surface);    _cairo_pdf_surface_add_pattern (surface, stream);    alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);    /* With some work, we could separate the stroking     * or non-stroking pattern here as actually needed. */    _cairo_output_stream_printf (surface->output,				 "/Pattern CS /res%d SCN "				 "/Pattern cs /res%d scn "				 "/a%d gs\r\n",				 stream.id, stream.id, alpha.id); BAIL:    _cairo_surface_release_source_image (pattern->surface, image, image_extra);    return status;}typedef struct _cairo_pdf_color_stop {    double	  		offset;    cairo_pdf_resource_t	gradient;    unsigned char		color_char[4];} cairo_pdf_color_stop_t;static cairo_pdf_resource_temit_linear_colorgradient (cairo_pdf_surface_t		*surface,			   cairo_pdf_color_stop_t	*stop1,			   cairo_pdf_color_stop_t	*stop2){    cairo_pdf_resource_t function = _cairo_pdf_surface_new_object (surface);    _cairo_output_stream_printf (surface->output,				 "%d 0 obj\r\n"				 "<< /FunctionType 0\r\n"				 "   /Domain [ 0 1 ]\r\n"				 "   /Size [ 2 ]\r\n"				 "   /BitsPerSample 8\r\n"				 "   /Range [ 0 1 0 1 0 1 ]\r\n"				 "   /Length 6\r\n"				 ">>\r\n"				 "stream\r\n",				 function.id);    _cairo_output_stream_write (surface->output, stop1->color_char, 3);    _cairo_output_stream_write (surface->output, stop2->color_char, 3);    _cairo_output_stream_printf (surface->output,				 "\r\n"				 "endstream\r\n"				 "endobj\r\n");    return function;}static cairo_pdf_resource_temit_stiched_colorgradient (cairo_pdf_surface_t   *surface,			    unsigned int 	   n_stops,			    cairo_pdf_color_stop_t stops[]){    cairo_pdf_resource_t function;    unsigned int i;    /* emit linear gradients between pairs of subsequent stops... */    for (i = 0; i < n_stops-1; i++) {	stops[i].gradient = emit_linear_colorgradient (surface,						       &stops[i],						       &stops[i+1]);    }    /* ... and stich them together */    function = _cairo_pdf_surface_new_object (surface);    _cairo_output_stream_printf (surface->output,				 "%d 0 obj\r\n"				 "<< /FunctionType 3\r\n"				 "   /Domain [ 0 1 ]\r\n",				 function.id);    _cairo_output_stream_printf (surface->output,				 "   /Functions [ ");    for (i = 0; i < n_stops-1; i++)    {        _cairo_output_stream_printf (surface->output,				     "%d 0 R ", stops[i].gradient.id);    }    _cairo_output_stream_printf (surface->output,		    		 "]\r\n");    _cairo_output_stream_printf (surface->output,				 "   /Bounds [ ");    for (i = 1; i < n_stops-1; i++)    {        _cairo_output_stream_printf (surface->output,				     "%f ", stops[i].offset);    }    _cairo_output_stream_printf (surface->output,		    		 "]\r\n");    _cairo_output_stream_printf (surface->output,				 "   /Encode [ ");    for (i = 1; i < n_stops; i++)    {        _cairo_output_stream_printf (surface->output,				     "0 1 ");    }    _cairo_output_stream_printf (surface->output,	    			 "]\r\n");    _cairo_output_stream_printf (surface->output,	    			 ">>\r\n"				 "endobj\r\n");    return function;}#define COLOR_STOP_EPSILLON 1e-6static cairo_pdf_resource_temit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern){    cairo_pdf_resource_t    function;    cairo_pdf_color_stop_t *allstops, *stops;    unsigned int 	   n_stops;    unsigned int 	   i;    function = _cairo_pdf_surface_new_object (surface);    allstops = malloc ((pattern->n_stops + 2) * sizeof (cairo_pdf_color_stop_t));    if (allstops == NULL) {	_cairo_error (CAIRO_STATUS_NO_MEMORY);	function.id = 0;	return function;    }    stops = &allstops[1];    n_stops = pattern->n_stops;    for (i = 0; i < pattern->n_stops; i++) {	stops[i].color_char[0] = pattern->stops[i].color.red   >> 8;	stops[i].color_char[1] = pattern->stops[i].color.green >> 8;	stops[i].color_char[2] = pattern->stops[i].color.blue  >> 8;	stops[i].color_char[3] = pattern->stops[i].color.alpha >> 8;	stops[i].offset = _cairo_fixed_to_double (pattern->stops[i].x);    }    /* make sure first offset is 0.0 and last offset is 1.0. (Otherwise Acrobat     * Reader chokes.) */    if (stops[0].offset > COLOR_STOP_EPSILLON) {	    memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));	    stops = allstops;	    stops[0].offset = 0.0;	    n_stops++;    }    if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILLON) {	    memcpy (&stops[n_stops],		    &stops[n_stops - 1],		    sizeof (cairo_pdf_color_stop_t));	    stops[n_stops].offset = 1.0;	    n_stops++;    }    if (n_stops == 2) {	/* no need for stiched function */	function = emit_linear_colorgradient (surface, &stops[0], &stops[1]);    } else {	/* multiple stops: stich. XXX possible optimization: regulary spaced	 * stops do not require stiching. XXX */	function = emit_stiched_colorgradient (surface,					       n_stops,					       stops);    }    free (allstops);    return function;}static cairo_status_temit_linear_pattern (cairo_pdf_surface_t *surface, cairo_linear_pattern_t *pattern){    cairo_pdf_resource_t function, pattern_resource, alpha;    double x0, y0, x1, y1;    cairo_matrix_t p2u;    _cairo_pdf_surface_pause_content_stream (surface);    function = emit_pattern_stops (surface, &pattern->base);    if (function.id == 0)	return CAIRO_STATUS_NO_MEMORY;    p2u = pattern->base.base.matrix;    cairo_matrix_invert (&p2u);    x0 = _cairo_fixed_to_double (pattern->gradient.p1.x);    y0 = _cairo_fixed_to_double (pattern->gradient.p1.y);    cairo_matrix_transform_point (&p2u, &x0, &y0);    x1 = _cairo_fixed_to_double (pattern->gradient.p2.x);    y1 = _cairo_fixed_to_double (pattern->gradient.p2.y);    cairo_matrix_transform_point (&p2u, &x1, &y1);    pattern_resource = _cairo_pdf_surface_new_object (surface);    _cairo_output_stream_printf (surface->output,				 "%d 0 obj\r\n"				 "<< /Type /Pattern\r\n"				 "   /PatternType 2\r\n"				 "   /Matrix [ 1 0 0 -1 0 %f ]\r\n"				 "   /Shading\r\n"				 "      << /ShadingType 2\r\n"				 "         /ColorSpace /DeviceRGB\r\n"				 "         /Coords [ %f %f %f %f ]\r\n"				 "         /Function %d 0 R\r\n"				 "         /Extend [ true true ]\r\n"				 "      >>\r\n"				 ">>\r\n"				 "endobj\r\n",				 pattern_resource.id,				 surface->height,				 x0, y0, x1, y1,				 function.id);    _cairo_pdf_surface_add_pattern (surface, pattern_resource);    alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);    /* Use pattern */    /* With some work, we could separate the stroking     * or non-stroking pattern here as actually needed. */    _cairo_output_stream_printf (surface->output,				 "/Pattern CS /res%d SCN "				 "/Pattern cs /res%d scn "				 "/a%d gs\r\n",				 pattern_resource.id,				 pattern_resource.id,				 alpha.id);    _cairo_pdf_surface_resume_content_stream (surface);    return CAIRO_STATUS_SUCCESS;}static cairo_status_temit_radial_pattern (cairo_pdf_surface_t *surface, cairo_radial_pattern_t *pattern){    cairo_pdf_resource_t function, pattern_resource, alpha;    double x0, y0, x1, y1, r0, r1;    cairo_matrix_t p2u;    _cairo_pdf_surface_pause_content_stream (surface);    function = emit_pattern_stops (surface, &pattern->base);    if (function.id == 0)	return CAIRO_STATUS_NO_MEMORY;    p2u = pattern->base.base.matrix;    cairo_matrix_invert (&p2u);    x0 = _cairo_fixed_to_double (pattern->gradient.inner.x);    y0 = _cairo_fixed_to_double (pattern->gradient.inner.y);    r0 = _cairo_fixed_to_double (pattern->gradient.inner.radius);    cairo_matrix_transform_point (&p2u, &x0, &y0);    x1 = _cairo_fixed_to_double (pattern->gradient.outer.x);    y1 = _cairo_fixed_to_double (pattern->gradient.outer.y);    r1 = _cairo_fixed_to_double (pattern->gradient.outer.radius);    cairo_matrix_transform_point (&p2u, &x1, &y1);    /* FIXME: This is surely crack, but how should you scale a radius     * in a non-orthogonal coordinate system? */    cairo_matrix_transform_distance (&p2u, &r0, &r1);    /* FIXME: There is a difference between the cairo gradient extend     * semantics and PDF extend semantics. PDFs extend=false means     * that nothing is painted outside the gradient boundaries,     * whereas cairo takes this to mean that the end color is padded     * to infinity. Setting extend=true in PDF gives the cairo default     * behavoir, not yet sure how to implement the cairo mirror and     * repeat behaviour. */    pattern_resource = _cairo_pdf_surface_new_object (surface);    _cairo_output_stream_printf (surface->output,				 "%d 0 obj\r\n"				 "<< /Type /Pattern\r\n"				 "   /PatternType 2\r\n"				 "   /Matrix [ 1 0 0 -1 0 %f ]\r\n"				 "   /Shading\r\n"				 "      << /ShadingType 3\r\n"				 "         /ColorSpace /DeviceRGB\r\n"				 "         /Coords [ %f %f %f %f %f %f ]\r\n"				 "         /Function %d 0 R\r\n"				 "         /Extend [ true true ]\r\n"				 "      >>\r\n"				 ">>\r\n"				 "endobj\r\n",				 pattern_resource.id,				 surface->height,				 x0, y0, r0, x1, y1, r1,				 function.id);    _cairo_pdf_surface_add_pattern (surface, pattern_resource);    alpha = _cairo_pdf_surface_add_alpha (surface, 1.0);    /* Use pattern */    /* With some work, we could separate the stroking     * or non-stroking pattern here as actually needed. */    _cairo_output_stream_printf (surface->output,				 "/Pattern CS /res%d SCN "				 "/Pattern cs /res%d scn "				 "/a%d gs\r\n",				 pattern_resource.id,				 pattern_resource.id,				 alpha.id);    _cairo_pdf_surface_resume_content_stream (surface);    return CAIRO_STATUS_SUCCESS;}static cairo_status_temit_pattern (cairo_pdf_surface_t *surface, cairo_pattern_t *pattern){    switch (pattern->type) {    case CAIRO_PATTERN_TYPE_SOLID:	return emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern);    case CAIRO_PATTERN_TYPE_SURFACE:	return emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);    case CAIRO_PATTERN_TYPE_LINEAR:	return emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);    case CAIRO_PATTERN_TYPE_RADIAL:	return emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);    }    ASSERT_NOT_REACHED;    return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;}static cairo_int_status_t_cairo_pdf_surface_copy_page (void *abstract_surface){    cairo_pdf_surface_t *surface = abstract_surface;    return _cairo_pdf_surface_write_page (surface);}static cairo_int_status_t_cairo_pdf_surface_show_page (void *abstract_surface){    cairo_pdf_surface_t *surface = abstract_surface;    cairo_int_status_t status;    status = _cairo_pdf_surface_write_page (surface);    if (status)	return status;    _cairo_pdf_surface_clear (surface);    return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_pdf_surface_get_extents (void		        *abstract_surface,

⌨️ 快捷键说明

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