mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-17 11:18:06 +02:00
pdf,ps: Add native mesh pattern support
PS and PDF have native support for mesh patterns, but they have encode mesh points and colors in an appropriate binary stream. cairo_pdf_shading_* functions implement the encoding, which is the same for PDF and PS.
This commit is contained in:
parent
8df122cb4b
commit
30636206b0
5 changed files with 614 additions and 3 deletions
|
|
@ -200,8 +200,8 @@ cairo_egl_sources =
|
|||
cairo_glx_sources =
|
||||
cairo_wgl_sources =
|
||||
|
||||
_cairo_pdf_operators_private = cairo-pdf-operators-private.h
|
||||
_cairo_pdf_operators_sources = cairo-pdf-operators.c
|
||||
_cairo_pdf_operators_private = cairo-pdf-operators-private.h cairo-pdf-shading-private.h
|
||||
_cairo_pdf_operators_sources = cairo-pdf-operators.c cairo-pdf-shading.c
|
||||
cairo_private += $(_cairo_pdf_operators_private)
|
||||
cairo_sources += $(_cairo_pdf_operators_sources)
|
||||
|
||||
|
|
|
|||
99
src/cairo-pdf-shading-private.h
Normal file
99
src/cairo-pdf-shading-private.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Adrian Johnson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Adrian Johnson.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Adrian Johnson <ajohnson@redneon.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_PDF_SHADING_H
|
||||
#define CAIRO_PDF_SHADING_H
|
||||
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
|
||||
typedef struct _cairo_pdf_shading {
|
||||
int shading_type;
|
||||
int bits_per_coordinate;
|
||||
int bits_per_component;
|
||||
int bits_per_flag;
|
||||
double *decode_array;
|
||||
int decode_array_length;
|
||||
unsigned char *data;
|
||||
unsigned long data_length;
|
||||
} cairo_pdf_shading_t;
|
||||
|
||||
|
||||
/**
|
||||
* _cairo_pdf_shading_init_color:
|
||||
* @shading: a #cairo_pdf_shading_t to initialize
|
||||
* @pattern: the #cairo_mesh_pattern_t to initialize from
|
||||
*
|
||||
* Generate the PDF shading dictionary data for the a PDF type 7
|
||||
* shading from RGB part of the specified mesh pattern.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS if successful, possible errors
|
||||
* include %CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_pdf_shading_init_color (cairo_pdf_shading_t *shading,
|
||||
const cairo_mesh_pattern_t *pattern);
|
||||
|
||||
|
||||
/**
|
||||
* _cairo_pdf_shading_init_alpha:
|
||||
* @shading: a #cairo_pdf_shading_t to initialize
|
||||
* @pattern: the #cairo_mesh_pattern_t to initialize from
|
||||
*
|
||||
* Generate the PDF shading dictionary data for a PDF type 7
|
||||
* shading from alpha part of the specified mesh pattern.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS if successful, possible errors
|
||||
* include %CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_pdf_shading_init_alpha (cairo_pdf_shading_t *shading,
|
||||
const cairo_mesh_pattern_t *pattern);
|
||||
|
||||
/**
|
||||
* _cairo_pdf_shading_fini:
|
||||
* @shading: a #cairo_pdf_shading_t
|
||||
*
|
||||
* Free all resources associated with @shading. After this call,
|
||||
* @shading should not be used again without a subsequent call to
|
||||
* _cairo_pdf_shading_init() again first.
|
||||
**/
|
||||
cairo_private void
|
||||
_cairo_pdf_shading_fini (cairo_pdf_shading_t *shading);
|
||||
|
||||
|
||||
#endif /* CAIRO_PDF_SHADING_H */
|
||||
277
src/cairo-pdf-shading.c
Normal file
277
src/cairo-pdf-shading.c
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Adrian Johnson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Adrian Johnson.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Adrian Johnson <ajohnson@redneon.com>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#if CAIRO_HAS_PDF_OPERATORS
|
||||
|
||||
#include "cairo-pdf-shading-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include <float.h>
|
||||
|
||||
static unsigned char *
|
||||
encode_coordinate (unsigned char *p, double c)
|
||||
{
|
||||
uint32_t f;
|
||||
|
||||
f = c;
|
||||
*p++ = f >> 24;
|
||||
*p++ = (f >> 16) & 0xff;
|
||||
*p++ = (f >> 8) & 0xff;
|
||||
*p++ = f & 0xff;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
encode_point (unsigned char *p, const cairo_point_double_t *point)
|
||||
{
|
||||
p = encode_coordinate (p, point->x);
|
||||
p = encode_coordinate (p, point->y);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
encode_color_component (unsigned char *p, double color)
|
||||
{
|
||||
uint16_t c;
|
||||
|
||||
c = _cairo_color_double_to_short (color);
|
||||
*p++ = c >> 8;
|
||||
*p++ = c & 0xff;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
encode_color (unsigned char *p, const cairo_color_t *color)
|
||||
{
|
||||
p = encode_color_component (p, color->red);
|
||||
p = encode_color_component (p, color->green);
|
||||
p = encode_color_component (p, color->blue);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static unsigned char *
|
||||
encode_alpha (unsigned char *p, const cairo_color_t *color)
|
||||
{
|
||||
p = encode_color_component (p, color->alpha);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_shading_generate_decode_array (cairo_pdf_shading_t *shading,
|
||||
const cairo_mesh_pattern_t *mesh,
|
||||
cairo_bool_t is_alpha)
|
||||
{
|
||||
unsigned int num_color_components, i;
|
||||
cairo_bool_t is_valid;
|
||||
|
||||
if (is_alpha)
|
||||
num_color_components = 1;
|
||||
else
|
||||
num_color_components = 3;
|
||||
|
||||
shading->decode_array_length = 4 + num_color_components * 2;
|
||||
shading->decode_array = _cairo_malloc_ab (shading->decode_array_length,
|
||||
sizeof (double));
|
||||
if (unlikely (shading->decode_array == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
is_valid = _cairo_mesh_pattern_coord_box (mesh,
|
||||
&shading->decode_array[0],
|
||||
&shading->decode_array[2],
|
||||
&shading->decode_array[1],
|
||||
&shading->decode_array[3]);
|
||||
|
||||
assert (is_valid);
|
||||
assert (shading->decode_array[1] - shading->decode_array[0] >= DBL_EPSILON);
|
||||
assert (shading->decode_array[3] - shading->decode_array[2] >= DBL_EPSILON);
|
||||
|
||||
for (i = 0; i < num_color_components; i++) {
|
||||
shading->decode_array[4 + 2*i] = 0;
|
||||
shading->decode_array[5 + 2*i] = 1;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* The ISO32000 specification mandates this order for the points which
|
||||
* define the patch. */
|
||||
static const int pdf_points_order_i[16] = {
|
||||
0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2 };
|
||||
static const int pdf_points_order_j[16] = {
|
||||
0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1 };
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_shading_generate_data (cairo_pdf_shading_t *shading,
|
||||
const cairo_mesh_pattern_t *mesh,
|
||||
cairo_bool_t is_alpha)
|
||||
{
|
||||
const cairo_mesh_patch_t *patch;
|
||||
double x_off, y_off, x_scale, y_scale;
|
||||
unsigned int num_patches;
|
||||
unsigned int num_color_components;
|
||||
unsigned char *p;
|
||||
unsigned int i, j;
|
||||
|
||||
if (is_alpha)
|
||||
num_color_components = 1;
|
||||
else
|
||||
num_color_components = 3;
|
||||
|
||||
num_patches = _cairo_array_num_elements (&mesh->patches);
|
||||
patch = _cairo_array_index_const (&mesh->patches, 0);
|
||||
|
||||
/* Each patch requires:
|
||||
*
|
||||
* 1 flag - 1 byte
|
||||
* 16 points. Each point is 2 coordinates. Each coordinate is
|
||||
* stored in 4 bytes.
|
||||
*
|
||||
* 4 colors. Each color is stored in 2 bytes * num_color_components.
|
||||
*/
|
||||
shading->data_length = num_patches * (1 + 16 * 2 * 4 + 4 * 2 * num_color_components);
|
||||
shading->data = malloc (shading->data_length);
|
||||
if (unlikely (shading->data == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
x_off = shading->decode_array[0];
|
||||
y_off = shading->decode_array[2];
|
||||
x_scale = UINT32_MAX / (shading->decode_array[1] - x_off);
|
||||
y_scale = UINT32_MAX / (shading->decode_array[3] - y_off);
|
||||
|
||||
p = shading->data;
|
||||
for (i = 0; i < num_patches; i++) {
|
||||
/* edge flag */
|
||||
*p++ = 0;
|
||||
|
||||
/* 16 points */
|
||||
for (j = 0; j < 16; j++) {
|
||||
cairo_point_double_t point;
|
||||
int pi, pj;
|
||||
|
||||
pi = pdf_points_order_i[j];
|
||||
pj = pdf_points_order_j[j];
|
||||
point = patch[i].points[pi][pj];
|
||||
|
||||
/* Transform the point as specified in the decode array */
|
||||
point.x -= x_off;
|
||||
point.y -= y_off;
|
||||
point.x *= x_scale;
|
||||
point.y *= y_scale;
|
||||
|
||||
/* Make sure that rounding errors don't cause
|
||||
* wraparounds */
|
||||
point.x = _cairo_restrict_value (point.x, 0, UINT32_MAX);
|
||||
point.y = _cairo_restrict_value (point.y, 0, UINT32_MAX);
|
||||
|
||||
p = encode_point (p, &point);
|
||||
}
|
||||
|
||||
/* 4 colors */
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (is_alpha)
|
||||
p = encode_alpha (p, &patch[i].colors[j]);
|
||||
else
|
||||
p = encode_color (p, &patch[i].colors[j]);
|
||||
}
|
||||
}
|
||||
|
||||
assert (p == shading->data + shading->data_length);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_shading_init (cairo_pdf_shading_t *shading,
|
||||
const cairo_mesh_pattern_t *mesh,
|
||||
cairo_bool_t is_alpha)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
assert (mesh->base.status == CAIRO_STATUS_SUCCESS);
|
||||
assert (mesh->current_patch == NULL);
|
||||
|
||||
shading->shading_type = 7;
|
||||
|
||||
/*
|
||||
* Coordinates from the minimum to the maximum value of the mesh
|
||||
* map to the [0..UINT32_MAX] range and are represented as
|
||||
* uint32_t values.
|
||||
*
|
||||
* Color components are represented as uint16_t (in a 0.16 fixed
|
||||
* point format, as in the rest of cairo).
|
||||
*/
|
||||
shading->bits_per_coordinate = 32;
|
||||
shading->bits_per_component = 16;
|
||||
shading->bits_per_flag = 8;
|
||||
|
||||
shading->decode_array = NULL;
|
||||
shading->data = NULL;
|
||||
|
||||
status = _cairo_pdf_shading_generate_decode_array (shading, mesh, is_alpha);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_pdf_shading_generate_data (shading, mesh, is_alpha);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_pdf_shading_init_color (cairo_pdf_shading_t *shading,
|
||||
const cairo_mesh_pattern_t *pattern)
|
||||
{
|
||||
return _cairo_pdf_shading_init (shading, pattern, FALSE);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_pdf_shading_init_alpha (cairo_pdf_shading_t *shading,
|
||||
const cairo_mesh_pattern_t *pattern)
|
||||
{
|
||||
return _cairo_pdf_shading_init (shading, pattern, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_pdf_shading_fini (cairo_pdf_shading_t *shading)
|
||||
{
|
||||
free (shading->data);
|
||||
free (shading->decode_array);
|
||||
}
|
||||
|
||||
#endif /* CAIRO_HAS_PDF_OPERATORS */
|
||||
|
|
@ -44,6 +44,7 @@
|
|||
#include "cairo-pdf.h"
|
||||
#include "cairo-pdf-surface-private.h"
|
||||
#include "cairo-pdf-operators-private.h"
|
||||
#include "cairo-pdf-shading-private.h"
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
#include "cairo-composite-rectangles-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
|
@ -1275,7 +1276,8 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
|
|||
|
||||
/* gradient patterns require an smask object to implement transparency */
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
|
||||
pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
|
||||
pattern->type == CAIRO_PATTERN_TYPE_RADIAL ||
|
||||
pattern->type == CAIRO_PATTERN_TYPE_MESH)
|
||||
{
|
||||
double min_alpha;
|
||||
|
||||
|
|
@ -3339,6 +3341,150 @@ _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface,
|
|||
return _cairo_output_stream_get_status (surface->output);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
|
||||
cairo_pdf_pattern_t *pdf_pattern)
|
||||
{
|
||||
cairo_matrix_t pat_to_pdf;
|
||||
cairo_status_t status;
|
||||
cairo_pattern_t *pattern = pdf_pattern->pattern;
|
||||
cairo_pdf_shading_t shading;
|
||||
int i;
|
||||
cairo_pdf_resource_t res;
|
||||
|
||||
pat_to_pdf = pattern->matrix;
|
||||
status = cairo_matrix_invert (&pat_to_pdf);
|
||||
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
|
||||
|
||||
status = _cairo_pdf_shading_init_color (&shading, (cairo_mesh_pattern_t *) pattern);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
res = _cairo_pdf_surface_new_object (surface);
|
||||
if (unlikely (res.id == 0))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\n"
|
||||
"<< /ShadingType %d\n"
|
||||
" /ColorSpace /DeviceRGB\n"
|
||||
" /BitsPerCoordinate %d\n"
|
||||
" /BitsPerComponent %d\n"
|
||||
" /BitsPerFlag %d\n"
|
||||
" /Decode [",
|
||||
res.id,
|
||||
shading.shading_type,
|
||||
shading.bits_per_coordinate,
|
||||
shading.bits_per_component,
|
||||
shading.bits_per_flag);
|
||||
|
||||
for (i = 0; i < shading.decode_array_length; i++)
|
||||
_cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"]\n"
|
||||
" /Length %ld\n"
|
||||
">>\n"
|
||||
"stream\n",
|
||||
shading.data_length);
|
||||
|
||||
_cairo_output_stream_write (surface->output, shading.data, shading.data_length);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"\nendstream\n"
|
||||
"endobj\n");
|
||||
|
||||
_cairo_pdf_shading_fini (&shading);
|
||||
|
||||
_cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res);
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\n"
|
||||
"<< /Type /Pattern\n"
|
||||
" /PatternType 2\n"
|
||||
" /Matrix [ %f %f %f %f %f %f ]\n"
|
||||
" /Shading %d 0 R\n"
|
||||
">>\n"
|
||||
"endobj\n",
|
||||
pdf_pattern->pattern_res.id,
|
||||
pat_to_pdf.xx, pat_to_pdf.yx,
|
||||
pat_to_pdf.xy, pat_to_pdf.yy,
|
||||
pat_to_pdf.x0, pat_to_pdf.y0,
|
||||
res.id);
|
||||
|
||||
if (pdf_pattern->gstate_res.id != 0) {
|
||||
cairo_pdf_resource_t mask_resource;
|
||||
|
||||
/* Create pattern for SMask. */
|
||||
res = _cairo_pdf_surface_new_object (surface);
|
||||
if (unlikely (res.id == 0))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
status = _cairo_pdf_shading_init_alpha (&shading, (cairo_mesh_pattern_t *) pattern);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\n"
|
||||
"<< /ShadingType %d\n"
|
||||
" /ColorSpace /DeviceGray\n"
|
||||
" /BitsPerCoordinate %d\n"
|
||||
" /BitsPerComponent %d\n"
|
||||
" /BitsPerFlag %d\n"
|
||||
" /Decode [",
|
||||
res.id,
|
||||
shading.shading_type,
|
||||
shading.bits_per_coordinate,
|
||||
shading.bits_per_component,
|
||||
shading.bits_per_flag);
|
||||
|
||||
for (i = 0; i < shading.decode_array_length; i++)
|
||||
_cairo_output_stream_printf (surface->output, "%f ", shading.decode_array[i]);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"]\n"
|
||||
" /Length %ld\n"
|
||||
">>\n"
|
||||
"stream\n",
|
||||
shading.data_length);
|
||||
|
||||
_cairo_output_stream_write (surface->output, shading.data, shading.data_length);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"\nendstream\n"
|
||||
"endobj\n");
|
||||
_cairo_pdf_shading_fini (&shading);
|
||||
|
||||
mask_resource = _cairo_pdf_surface_new_object (surface);
|
||||
if (unlikely (mask_resource.id == 0))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
"%d 0 obj\n"
|
||||
"<< /Type /Pattern\n"
|
||||
" /PatternType 2\n"
|
||||
" /Matrix [ %f %f %f %f %f %f ]\n"
|
||||
" /Shading %d 0 R\n"
|
||||
">>\n"
|
||||
"endobj\n",
|
||||
mask_resource.id,
|
||||
pat_to_pdf.xx, pat_to_pdf.yx,
|
||||
pat_to_pdf.xy, pat_to_pdf.yy,
|
||||
pat_to_pdf.x0, pat_to_pdf.y0,
|
||||
res.id);
|
||||
|
||||
status = cairo_pdf_surface_emit_transparency_group (surface,
|
||||
pdf_pattern->gstate_res,
|
||||
mask_resource);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
return _cairo_output_stream_get_status (surface->output);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern)
|
||||
{
|
||||
|
|
@ -3366,6 +3512,10 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern
|
|||
status = _cairo_pdf_surface_emit_gradient (surface, pdf_pattern);
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_MESH:
|
||||
status = _cairo_pdf_surface_emit_mesh_pattern (surface, pdf_pattern);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
|
||||
|
|
@ -5379,6 +5529,7 @@ _pattern_supported (const cairo_pattern_t *pattern)
|
|||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
case CAIRO_PATTERN_TYPE_MESH:
|
||||
return TRUE;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
#include "cairo-ps.h"
|
||||
#include "cairo-ps-surface-private.h"
|
||||
#include "cairo-pdf-operators-private.h"
|
||||
#include "cairo-pdf-shading-private.h"
|
||||
#include "cairo-composite-rectangles-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
|
|
@ -1750,6 +1751,7 @@ pattern_supported (cairo_ps_surface_t *surface, const cairo_pattern_t *pattern)
|
|||
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
case CAIRO_PATTERN_TYPE_MESH:
|
||||
return _gradient_pattern_supported (surface, pattern);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
|
|
@ -3372,6 +3374,81 @@ _cairo_ps_surface_emit_gradient (cairo_ps_surface_t *surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t *surface,
|
||||
cairo_mesh_pattern_t *pattern)
|
||||
{
|
||||
cairo_matrix_t pat_to_ps;
|
||||
cairo_status_t status;
|
||||
cairo_pdf_shading_t shading;
|
||||
unsigned char *data_compressed;
|
||||
unsigned long data_compressed_size;
|
||||
int i;
|
||||
|
||||
if (_cairo_array_num_elements (&pattern->patches) == 0)
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
pat_to_ps = pattern->base.matrix;
|
||||
status = cairo_matrix_invert (&pat_to_ps);
|
||||
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
|
||||
|
||||
status = _cairo_pdf_shading_init_color (&shading, pattern);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"<< /PatternType 2\n"
|
||||
" /Shading\n"
|
||||
" << /ShadingType %d\n"
|
||||
" /ColorSpace /DeviceRGB\n"
|
||||
" /DataSource currentfile /ASCII85Decode filter /LZWDecode filter\n"
|
||||
" /BitsPerCoordinate %d\n"
|
||||
" /BitsPerComponent %d\n"
|
||||
" /BitsPerFlag %d\n"
|
||||
" /Decode [",
|
||||
shading.shading_type,
|
||||
shading.bits_per_coordinate,
|
||||
shading.bits_per_component,
|
||||
shading.bits_per_flag);
|
||||
|
||||
for (i = 0; i < shading.decode_array_length; i++)
|
||||
_cairo_output_stream_printf (surface->stream, "%f ", shading.decode_array[i]);
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"]\n"
|
||||
" >>\n"
|
||||
">>\n");
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"[ %f %f %f %f %f %f ]\n",
|
||||
pat_to_ps.xx, pat_to_ps.yx,
|
||||
pat_to_ps.xy, pat_to_ps.yy,
|
||||
pat_to_ps.x0, pat_to_ps.y0);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"makepattern\n");
|
||||
|
||||
data_compressed_size = shading.data_length;
|
||||
data_compressed = _cairo_lzw_compress (shading.data, &data_compressed_size);
|
||||
if (unlikely (data_compressed == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
status = _cairo_ps_surface_emit_base85_string (surface,
|
||||
data_compressed,
|
||||
data_compressed_size,
|
||||
FALSE);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"\n"
|
||||
"setpattern\n");
|
||||
|
||||
free (data_compressed);
|
||||
_cairo_pdf_shading_fini (&shading);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
|
||||
const cairo_pattern_t *pattern,
|
||||
|
|
@ -3430,6 +3507,13 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_MESH:
|
||||
status = _cairo_ps_surface_emit_mesh_pattern (surface,
|
||||
(cairo_mesh_pattern_t *) pattern);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
break;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue