зеркало из https://github.com/mozilla/pjs.git
b=411224, r=vlad: 411224-cairo-upgrade-1.5.5
This commit is contained in:
Родитель
7e9c4c2a2c
Коммит
37c1190c3f
|
@ -7,8 +7,8 @@ http://www.cairographics.org/.
|
|||
|
||||
VERSIONS:
|
||||
|
||||
cairo (1.5.x - 1.5.2-55-g39b8ddf)
|
||||
pixman (0.9.x - pixman-0.9.6-13-g4193b3c)
|
||||
cairo (1.5.x - 1.5.4-141-g57c2b75)
|
||||
pixman (0.9.x - pixman-0.9.6-25-ge0af592)
|
||||
glitz 0.5.2 (cvs - 2006-01-10)
|
||||
|
||||
***** NOTE FOR VISUAL C++ 6.0 *****
|
||||
|
|
|
@ -121,30 +121,39 @@ CSRCS = \
|
|||
|
||||
EXPORTS = cairo.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
|
||||
|
||||
PSPDF_BASE_CSRCS = \
|
||||
cairo-base85-stream.c \
|
||||
cairo-type1-subset.c \
|
||||
cairo-type1-fallback.c \
|
||||
cairo-truetype-subset.c \
|
||||
cairo-cff-subset.c \
|
||||
$(NULL)
|
||||
|
||||
PDF_CSRCS = \
|
||||
cairo-pdf-surface.c \
|
||||
cairo-pdf-operators.c \
|
||||
$(NULL)
|
||||
|
||||
PS_CSRCS = cairo-ps-surface.c
|
||||
|
||||
PDF_EXPORTS = cairo-pdf.h
|
||||
PS_EXPORTS = cairo-ps.h
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
CSRCS += cairo-win32-font.c \
|
||||
cairo-win32-surface.c \
|
||||
CSRCS += cairo-win32.c \
|
||||
cairo-win32-font.c \
|
||||
cairo-win32-surface.c \
|
||||
cairo-win32-printing-surface.c
|
||||
EXPORTS += cairo-win32.h
|
||||
CSRCS += cairo-base85-stream.c \
|
||||
cairo-pdf-surface.c \
|
||||
cairo-type1-fallback.c \
|
||||
cairo-truetype-subset.c \
|
||||
cairo-cff-subset.c
|
||||
EXPORTS += cairo-pdf.h
|
||||
CSRCS += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS)
|
||||
EXPORTS += $(PDF_EXPORTS)
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
|
||||
CSRCS += cairo-os2-surface.c
|
||||
EXPORTS += cairo-os2.h cairo-os2-private.h
|
||||
CSRCS += cairo-base85-stream.c \
|
||||
cairo-pdf-surface.c \
|
||||
cairo-type1-subset.c \
|
||||
cairo-type1-fallback.c \
|
||||
cairo-truetype-subset.c \
|
||||
cairo-cff-subset.c
|
||||
EXPORTS += cairo-pdf.h
|
||||
CSRCS += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS)
|
||||
EXPORTS += $(PDF_EXPORTS)
|
||||
endif
|
||||
|
||||
ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
|
||||
|
@ -158,14 +167,8 @@ EXPORTS += cairo-beos.h
|
|||
endif
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
|
||||
CSRCS += cairo-base85-stream.c \
|
||||
cairo-pdf-surface.c \
|
||||
cairo-ps-surface.c \
|
||||
cairo-type1-subset.c \
|
||||
cairo-type1-fallback.c \
|
||||
cairo-truetype-subset.c \
|
||||
cairo-cff-subset.c
|
||||
EXPORTS += cairo-ps.h cairo-pdf.h
|
||||
CSRCS += $(PSPDF_BASE_CSRCS) $(PDF_CSRCS) $(PS_CSRCS)
|
||||
EXPORTS += $(PDF_EXPORTS) $(PS_EXPORTS)
|
||||
endif
|
||||
|
||||
ifdef BUILD_CAIRO_SVG
|
||||
|
|
|
@ -57,31 +57,42 @@ typedef struct {
|
|||
cairo_rectangle_int_t current_clip;
|
||||
cairo_box_t page_bbox;
|
||||
|
||||
cairo_bool_t has_ctm;
|
||||
cairo_matrix_t ctm;
|
||||
|
||||
} cairo_analysis_surface_t;
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
|
||||
cairo_pattern_t *pattern)
|
||||
{
|
||||
cairo_surface_t *analysis = &surface->base;
|
||||
cairo_surface_pattern_t *surface_pattern;
|
||||
cairo_surface_t *meta_surface;
|
||||
cairo_surface_t *analysis;
|
||||
cairo_status_t status;
|
||||
cairo_bool_t old_has_ctm;
|
||||
cairo_matrix_t old_ctm, p2d;
|
||||
|
||||
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
|
||||
surface_pattern = (cairo_surface_pattern_t *) pattern;
|
||||
assert (_cairo_surface_is_meta (surface_pattern->surface));
|
||||
|
||||
meta_surface = surface_pattern->surface;
|
||||
analysis = _cairo_analysis_surface_create (surface->target,
|
||||
surface->width, surface->height);
|
||||
if (analysis == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
old_ctm = surface->ctm;
|
||||
old_has_ctm = surface->has_ctm;
|
||||
p2d = pattern->matrix;
|
||||
status = cairo_matrix_invert (&p2d);
|
||||
/* _cairo_pattern_set_matrix guarantees invertibility */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
status = _cairo_meta_surface_replay_analyze_meta_pattern (meta_surface, analysis);
|
||||
cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
|
||||
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
|
||||
|
||||
status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface,
|
||||
analysis);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = analysis->status;
|
||||
cairo_surface_destroy (analysis);
|
||||
status = analysis->status;
|
||||
|
||||
surface->ctm = old_ctm;
|
||||
surface->has_ctm = old_has_ctm;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -97,6 +108,28 @@ _cairo_analysis_surface_add_operation (cairo_analysis_surface_t *surface,
|
|||
if (rect->width == 0 || rect->height == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->has_ctm) {
|
||||
double x1, y1, x2, y2;
|
||||
|
||||
x1 = rect->x;
|
||||
y1 = rect->y;
|
||||
x2 = rect->x + rect->width;
|
||||
y2 = rect->y + rect->height;
|
||||
_cairo_matrix_transform_bounding_box (&surface->ctm,
|
||||
&x1, &y1, &x2, &y2,
|
||||
NULL);
|
||||
rect->x = floor (x1);
|
||||
rect->y = floor (y1);
|
||||
|
||||
x2 = ceil (x2) - rect->x;
|
||||
y2 = ceil (y2) - rect->y;
|
||||
if (x2 <= 0 || y2 <= 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
rect->width = x2;
|
||||
rect->height = y2;
|
||||
}
|
||||
|
||||
bbox.p1.x = _cairo_fixed_from_int (rect->x);
|
||||
bbox.p1.y = _cairo_fixed_from_int (rect->y);
|
||||
bbox.p2.x = _cairo_fixed_from_int (rect->x + rect->width);
|
||||
|
@ -188,28 +221,24 @@ _cairo_analysis_surface_intersect_clip_path (void *abstract_surface,
|
|||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
double x1, y1, x2, y2;
|
||||
cairo_rectangle_int_t extent;
|
||||
cairo_status_t status;
|
||||
|
||||
if (path == NULL) {
|
||||
surface->current_clip.x = 0;
|
||||
surface->current_clip.y = 0;
|
||||
surface->current_clip.width = surface->width;
|
||||
surface->current_clip.width = surface->width;
|
||||
surface->current_clip.height = surface->height;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
} else {
|
||||
status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2);
|
||||
if (status)
|
||||
return status;
|
||||
_cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2);
|
||||
|
||||
extent.x = floor (x1);
|
||||
extent.y = floor (y1);
|
||||
extent.width = ceil (x2) - extent.x;
|
||||
extent.width = ceil (x2) - extent.x;
|
||||
extent.height = ceil (y2) - extent.y;
|
||||
|
||||
_cairo_rectangle_intersect (&surface->current_clip, &extent);
|
||||
}
|
||||
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -382,7 +411,7 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
|
|||
tolerance,
|
||||
&traps);
|
||||
|
||||
if (status) {
|
||||
if (status || traps.num_traps == 0) {
|
||||
_cairo_traps_fini (&traps);
|
||||
return status;
|
||||
}
|
||||
|
@ -405,9 +434,9 @@ _cairo_analysis_surface_fill (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status, backend_status;
|
||||
|
@ -454,7 +483,7 @@ _cairo_analysis_surface_fill (void *abstract_surface,
|
|||
tolerance,
|
||||
&traps);
|
||||
|
||||
if (status) {
|
||||
if (status || traps.num_traps == 0) {
|
||||
_cairo_traps_fini (&traps);
|
||||
return status;
|
||||
}
|
||||
|
@ -577,6 +606,8 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
|
|||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
cairo_matrix_init_identity (&surface->ctm);
|
||||
surface->has_ctm = FALSE;
|
||||
|
||||
surface->target = target;
|
||||
surface->first_op = TRUE;
|
||||
|
|
|
@ -273,8 +273,7 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
|
|||
|
||||
err = CreateSizedCopyOfStyle (style, &font->size, &font->font_matrix, &font->style);
|
||||
if (err != noErr) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
|
@ -301,8 +300,7 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
|
|||
|
||||
status = _cairo_atsui_font_set_metrics (font);
|
||||
|
||||
font->cgfref = NULL;
|
||||
|
||||
font->cgfref = 0;
|
||||
FAIL:
|
||||
if (status) {
|
||||
if (font) {
|
||||
|
@ -453,6 +451,7 @@ _cairo_atsui_font_fini(void *abstract_font)
|
|||
ATSUDisposeStyle(font->unscaled_style);
|
||||
if (font->cgfref)
|
||||
CGFontRelease(font->cgfref);
|
||||
|
||||
}
|
||||
|
||||
static GlyphID
|
||||
|
|
|
@ -1421,7 +1421,7 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
|
|||
{
|
||||
int intersections;
|
||||
cairo_status_t status;
|
||||
cairo_bo_edge_t stack_edges[CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_bo_edge_t)];
|
||||
cairo_bo_edge_t stack_edges[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_edge_t)];
|
||||
cairo_bo_edge_t *edges;
|
||||
cairo_fixed_t xmin = 0x7FFFFFFF;
|
||||
cairo_fixed_t ymin = 0x7FFFFFFF;
|
||||
|
|
|
@ -704,7 +704,7 @@ _cairo_clip_int_rect_to_user (cairo_gstate_t *gstate,
|
|||
return is_tight;
|
||||
}
|
||||
|
||||
cairo_private cairo_rectangle_list_t*
|
||||
cairo_rectangle_list_t *
|
||||
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
|
||||
{
|
||||
cairo_rectangle_list_t *list;
|
||||
|
|
|
@ -70,12 +70,14 @@ CAIRO_BEGIN_DECLS
|
|||
#endif
|
||||
|
||||
/* slim_internal.h */
|
||||
#define CAIRO_HAS_HIDDEN_SYMBOLS 1
|
||||
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) && !defined(__sun)
|
||||
#define cairo_private_no_warn __attribute__((__visibility__("hidden")))
|
||||
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
|
||||
#define cairo_private_no_warn __hidden
|
||||
#else /* not gcc >= 3.3 and not Sun Studio >= 8 */
|
||||
#define cairo_private_no_warn
|
||||
#undef CAIRO_HAS_HIDDEN_SYMBOLS
|
||||
#endif
|
||||
|
||||
#ifndef WARN_UNUSED_RESULT
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -34,6 +34,16 @@
|
|||
* Carl D. Worth <cworth@isi.edu>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Environment variables affecting the backend:
|
||||
*
|
||||
* CAIRO_DIRECTFB_NO_ACCEL (boolean)
|
||||
* if found, disables acceleration at all
|
||||
*
|
||||
* CAIRO_DIRECTFB_ARGB_FONT (boolean)
|
||||
* if found, enables using ARGB fonts instead of A8
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_DIRECTFB_H
|
||||
#define CAIRO_DIRECTFB_H
|
||||
|
||||
|
@ -46,7 +56,7 @@
|
|||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface);
|
||||
cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *surface);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
|
|
|
@ -53,9 +53,9 @@
|
|||
|
||||
#define CAIRO_VERSION_MAJOR 1
|
||||
#define CAIRO_VERSION_MINOR 5
|
||||
#define CAIRO_VERSION_MICRO 3
|
||||
#define CAIRO_VERSION_MICRO 5
|
||||
|
||||
#define CAIRO_VERSION_STRING "1.5.3"
|
||||
#define CAIRO_VERSION_STRING "1.5.5"
|
||||
|
||||
@PS_SURFACE_FEATURE@
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ typedef cairo_int128_t cairo_fixed_96_32_t;
|
|||
* making sure that you compute a double-to-fixed magic number.
|
||||
* (see below).
|
||||
*/
|
||||
#define CAIRO_FIXED_FRAC_BITS 8
|
||||
#define CAIRO_FIXED_FRAC_BITS 16
|
||||
|
||||
/* A signed type CAIRO_FIXED_BITS in size; the main fixed point type */
|
||||
typedef int32_t cairo_fixed_t;
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
#ifndef CAIRO_FREELIST_H
|
||||
#define CAIRO_FREELIST_H
|
||||
|
||||
#include "cairoint.h"
|
||||
#include <stddef.h>
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
/* Opaque implementation types. */
|
||||
typedef struct _cairo_freelist cairo_freelist_t;
|
||||
|
|
|
@ -64,10 +64,6 @@
|
|||
*/
|
||||
#define MAX_OPEN_FACES 10
|
||||
|
||||
/* This is the maximum font size we allow to be passed to FT_Set_Char_Size
|
||||
*/
|
||||
#define MAX_FONT_SIZE 1000
|
||||
|
||||
/*
|
||||
* The simple 2x2 matrix is converted into separate scale and shape
|
||||
* factors so that hinting works right
|
||||
|
@ -670,18 +666,9 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
|
|||
FT_Set_Transform(unscaled->face, &mat, NULL);
|
||||
|
||||
if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
|
||||
double x_scale = sf.x_scale;
|
||||
double y_scale = sf.y_scale;
|
||||
if (x_scale > MAX_FONT_SIZE) {
|
||||
x_scale = MAX_FONT_SIZE;
|
||||
}
|
||||
if (y_scale > MAX_FONT_SIZE) {
|
||||
y_scale = MAX_FONT_SIZE;
|
||||
}
|
||||
|
||||
error = FT_Set_Char_Size (unscaled->face,
|
||||
x_scale * 64.0,
|
||||
y_scale * 64.0,
|
||||
sf.x_scale * 64.0,
|
||||
sf.y_scale * 64.0,
|
||||
0, 0);
|
||||
if (error)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
@ -1508,6 +1495,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
|
|||
font_matrix, ctm, options,
|
||||
&cairo_ft_scaled_font_backend);
|
||||
if (status) {
|
||||
_cairo_unscaled_font_destroy (&unscaled->base);
|
||||
free (scaled_font);
|
||||
goto FAIL;
|
||||
}
|
||||
|
@ -1515,34 +1503,11 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
|
|||
status = _cairo_ft_unscaled_font_set_scale (unscaled,
|
||||
&scaled_font->base.scale);
|
||||
if (status) {
|
||||
_cairo_unscaled_font_destroy (&unscaled->base);
|
||||
free (scaled_font);
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Force non-AA drawing when using a bitmap strike that
|
||||
* won't be resampled due to non-scaling transform
|
||||
*/
|
||||
if (!unscaled->have_shape &&
|
||||
(scaled_font->ft_options.load_flags & FT_LOAD_NO_BITMAP) == 0 &&
|
||||
scaled_font->ft_options.base.antialias != CAIRO_ANTIALIAS_NONE &&
|
||||
(face->face_flags & FT_FACE_FLAG_FIXED_SIZES))
|
||||
{
|
||||
int i;
|
||||
FT_Size_Metrics *size_metrics = &face->size->metrics;
|
||||
|
||||
for (i = 0; i < face->num_fixed_sizes; i++)
|
||||
{
|
||||
FT_Bitmap_Size *bitmap_size = &face->available_sizes[i];
|
||||
|
||||
if (bitmap_size->x_ppem == size_metrics->x_ppem * 64 &&
|
||||
bitmap_size->y_ppem == size_metrics->y_ppem * 64)
|
||||
{
|
||||
scaled_font->ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
metrics = &face->size->metrics;
|
||||
|
||||
|
@ -2170,7 +2135,7 @@ _cairo_ft_load_truetype_table (void *abstract_font,
|
|||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_int_status_t
|
||||
_cairo_ft_map_glyphs_to_unicode (void *abstract_font,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
|
@ -2184,7 +2149,7 @@ _cairo_ft_map_glyphs_to_unicode (void *abstract_font,
|
|||
|
||||
face = _cairo_ft_unscaled_font_lock_face (unscaled);
|
||||
if (!face)
|
||||
return;
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
count = font_subset->num_glyphs;
|
||||
charcode = FT_Get_First_Char( face, &glyph);
|
||||
|
@ -2197,9 +2162,11 @@ _cairo_ft_map_glyphs_to_unicode (void *abstract_font,
|
|||
break;
|
||||
}
|
||||
}
|
||||
charcode = FT_Get_Next_Char(face, charcode, &glyph);
|
||||
charcode = FT_Get_Next_Char (face, charcode, &glyph);
|
||||
}
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
|
||||
|
|
|
@ -1305,9 +1305,10 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
{
|
||||
if (data_size < size)
|
||||
{
|
||||
void *p;
|
||||
data_size = size;
|
||||
data = realloc (data, data_size);
|
||||
if (!data)
|
||||
p = realloc (data, data_size);
|
||||
if (!p)
|
||||
{
|
||||
_cairo_glitz_pattern_release_surface (src_pattern, src,
|
||||
&attributes);
|
||||
|
@ -1315,6 +1316,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
_cairo_pattern_fini (&tmp_src_pattern.base);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
data = p;
|
||||
|
||||
if (buffer)
|
||||
glitz_buffer_destroy (buffer);
|
||||
|
|
|
@ -35,11 +35,19 @@
|
|||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-gstate-private.h"
|
||||
|
||||
#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE
|
||||
#define ISFINITE(x) isfinite (x)
|
||||
#else
|
||||
#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
|
||||
#endif
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
|
||||
|
||||
|
@ -623,7 +631,7 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
|
|||
{
|
||||
cairo_matrix_t tmp;
|
||||
|
||||
if (! (tx * tx >= 0.) || ! (ty * ty >= 0.)) /* check for NaNs */
|
||||
if (! ISFINITE (tx) || ! ISFINITE (ty))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
@ -631,6 +639,10 @@ _cairo_gstate_translate (cairo_gstate_t *gstate, double tx, double ty)
|
|||
cairo_matrix_init_translate (&tmp, tx, ty);
|
||||
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
|
||||
|
||||
/* paranoid check against gradual numerical instability */
|
||||
if (! _cairo_matrix_is_invertible (&gstate->ctm))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
cairo_matrix_init_translate (&tmp, -tx, -ty);
|
||||
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
|
||||
|
||||
|
@ -644,7 +656,7 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
|
|||
|
||||
if (sx * sy == 0.) /* either sx or sy is 0, or det == 0 due to underflow */
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
if (! (sx * sx > 0.) || ! (sy * sy > 0.)) /* check for NaNs */
|
||||
if (! ISFINITE (sx) || ! ISFINITE (sy))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
@ -652,6 +664,10 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
|
|||
cairo_matrix_init_scale (&tmp, sx, sy);
|
||||
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
|
||||
|
||||
/* paranoid check against gradual numerical instability */
|
||||
if (! _cairo_matrix_is_invertible (&gstate->ctm))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
cairo_matrix_init_scale (&tmp, 1/sx, 1/sy);
|
||||
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
|
||||
|
||||
|
@ -666,7 +682,7 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
|
|||
if (angle == 0.)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (! (angle * angle >= 0.)) /* check for NaNs */
|
||||
if (! ISFINITE (angle))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
@ -674,6 +690,10 @@ _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
|
|||
cairo_matrix_init_rotate (&tmp, angle);
|
||||
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
|
||||
|
||||
/* paranoid check against gradual numerical instability */
|
||||
if (! _cairo_matrix_is_invertible (&gstate->ctm))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
cairo_matrix_init_rotate (&tmp, -angle);
|
||||
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
|
||||
|
||||
|
@ -687,16 +707,20 @@ _cairo_gstate_transform (cairo_gstate_t *gstate,
|
|||
cairo_matrix_t tmp;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
||||
tmp = *matrix;
|
||||
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
|
||||
|
||||
status = cairo_matrix_invert (&tmp);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
||||
cairo_matrix_multiply (&gstate->ctm, matrix, &gstate->ctm);
|
||||
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
|
||||
|
||||
/* paranoid check against gradual numerical instability */
|
||||
if (! _cairo_matrix_is_invertible (&gstate->ctm))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -706,14 +730,15 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (! _cairo_matrix_is_invertible (matrix))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
||||
gstate->ctm = *matrix;
|
||||
|
||||
gstate->ctm_inverse = *matrix;
|
||||
status = cairo_matrix_invert (&gstate->ctm_inverse);
|
||||
if (status)
|
||||
return status;
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1132,9 +1157,7 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate,
|
|||
{
|
||||
cairo_box_t extents;
|
||||
|
||||
_cairo_traps_extents (traps, &extents);
|
||||
|
||||
if (extents.p1.x >= extents.p2.x || extents.p1.y >= extents.p2.y) {
|
||||
if (traps->num_traps == 0) {
|
||||
/* no traps, so we actually won't draw anything */
|
||||
if (x1)
|
||||
*x1 = 0.0;
|
||||
|
@ -1145,6 +1168,8 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate,
|
|||
if (y2)
|
||||
*y2 = 0.0;
|
||||
} else {
|
||||
_cairo_traps_extents (traps, &extents);
|
||||
|
||||
if (x1)
|
||||
*x1 = _cairo_fixed_to_double (extents.p1.x);
|
||||
if (y1)
|
||||
|
@ -1575,7 +1600,6 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
|||
return cairo_scaled_font_status (gstate->scaled_font);
|
||||
}
|
||||
|
||||
#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t)))
|
||||
cairo_status_t
|
||||
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
|
@ -1584,7 +1608,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
cairo_status_t status;
|
||||
cairo_pattern_union_t source_pattern;
|
||||
cairo_glyph_t *transformed_glyphs;
|
||||
cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN];
|
||||
cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
|
||||
|
||||
if (gstate->source->status)
|
||||
return gstate->source->status;
|
||||
|
@ -1597,7 +1621,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
if (num_glyphs <= STACK_GLYPHS_LEN) {
|
||||
if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) {
|
||||
transformed_glyphs = stack_transformed_glyphs;
|
||||
} else {
|
||||
transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
|
||||
|
@ -1636,13 +1660,13 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
|||
{
|
||||
cairo_status_t status;
|
||||
cairo_glyph_t *transformed_glyphs;
|
||||
cairo_glyph_t stack_transformed_glyphs[STACK_GLYPHS_LEN];
|
||||
cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
|
||||
|
||||
status = _cairo_gstate_ensure_scaled_font (gstate);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (num_glyphs < STACK_GLYPHS_LEN)
|
||||
if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs))
|
||||
transformed_glyphs = stack_transformed_glyphs;
|
||||
else
|
||||
transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
|
||||
|
@ -1663,7 +1687,6 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
|||
|
||||
return status;
|
||||
}
|
||||
#undef STACK_GLYPHS_LEN
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_set_antialias (cairo_gstate_t *gstate,
|
||||
|
|
|
@ -724,6 +724,24 @@ _cairo_content_from_format (cairo_format_t format)
|
|||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
}
|
||||
|
||||
cairo_private cairo_format_t
|
||||
_cairo_format_width (cairo_format_t format)
|
||||
{
|
||||
switch (format) {
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
return 32;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
return 24;
|
||||
case CAIRO_FORMAT_A8:
|
||||
return 8;
|
||||
case CAIRO_FORMAT_A1:
|
||||
return 1;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_image_surface_create_similar (void *abstract_src,
|
||||
cairo_content_t content,
|
||||
|
@ -1034,8 +1052,6 @@ _cairo_image_surface_composite (cairo_operator_t op,
|
|||
return status;
|
||||
}
|
||||
|
||||
#define STACK_RECTS_LEN (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_rectangle16_t))
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_image_surface_fill_rectangles (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
|
@ -1046,7 +1062,7 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
|
|||
cairo_image_surface_t *surface = abstract_surface;
|
||||
|
||||
pixman_color_t pixman_color;
|
||||
pixman_rectangle16_t stack_rects[STACK_RECTS_LEN];
|
||||
pixman_rectangle16_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (pixman_rectangle16_t)];
|
||||
pixman_rectangle16_t *pixman_rects = stack_rects;
|
||||
int i;
|
||||
|
||||
|
@ -1085,10 +1101,6 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
#undef STACK_RECTS_LEN
|
||||
|
||||
#define STACK_TRAPS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_trapezoid_t)))
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
||||
cairo_pattern_t *pattern,
|
||||
|
@ -1110,7 +1122,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
pixman_image_t *mask;
|
||||
pixman_format_code_t format;
|
||||
uint32_t *mask_data;
|
||||
pixman_trapezoid_t stack_traps[STACK_TRAPS_LEN];
|
||||
pixman_trapezoid_t stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)];
|
||||
pixman_trapezoid_t *pixman_traps = stack_traps;
|
||||
int mask_stride;
|
||||
int mask_bpp;
|
||||
|
@ -1244,8 +1256,6 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
return status;
|
||||
}
|
||||
|
||||
#undef STACK_TRAPS_LEN
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_image_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
|
|
|
@ -38,6 +38,12 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#if _XOPEN_SOURCE >= 600 || _ISOC99_SOURCE
|
||||
#define ISFINITE(x) isfinite (x)
|
||||
#else
|
||||
#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
|
||||
#endif
|
||||
|
||||
static void
|
||||
_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar);
|
||||
|
||||
|
@ -475,8 +481,7 @@ cairo_matrix_invert (cairo_matrix_t *matrix)
|
|||
if (det == 0)
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
/* this weird construct is for detecting NaNs */
|
||||
if (! (det * det > 0.))
|
||||
if (! ISFINITE (det))
|
||||
return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
|
||||
|
||||
_cairo_matrix_compute_adjoint (matrix);
|
||||
|
@ -493,7 +498,7 @@ _cairo_matrix_is_invertible (const cairo_matrix_t *matrix)
|
|||
|
||||
_cairo_matrix_compute_determinant (matrix, &det);
|
||||
|
||||
return det != 0. && det * det > 0.;
|
||||
return det != 0. && ISFINITE (det);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -517,6 +522,8 @@ _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
|
|||
|
||||
_cairo_matrix_compute_determinant (matrix, &det);
|
||||
|
||||
assert (ISFINITE (det));
|
||||
|
||||
if (det == 0)
|
||||
{
|
||||
*sx = *sy = 0;
|
||||
|
|
|
@ -61,8 +61,7 @@
|
|||
|
||||
typedef enum {
|
||||
CAIRO_META_REPLAY,
|
||||
CAIRO_META_CREATE_REGIONS,
|
||||
CAIRO_META_ANALYZE_META_PATTERN
|
||||
CAIRO_META_CREATE_REGIONS
|
||||
} cairo_meta_replay_type_t;
|
||||
|
||||
static const cairo_surface_backend_t cairo_meta_surface_backend;
|
||||
|
@ -476,7 +475,7 @@ _cairo_meta_surface_show_glyphs (void *abstract_surface,
|
|||
_cairo_pattern_fini (&command->source.base);
|
||||
CLEANUP_COMMAND:
|
||||
free (command);
|
||||
return _cairo_error (status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -853,11 +852,6 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
|
|||
}
|
||||
}
|
||||
|
||||
if (type == CAIRO_META_ANALYZE_META_PATTERN) {
|
||||
if (status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
|
@ -877,16 +871,6 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
|
|||
CAIRO_META_REGION_ALL);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,
|
||||
cairo_surface_t *target)
|
||||
{
|
||||
return _cairo_meta_surface_replay_internal (surface,
|
||||
target,
|
||||
CAIRO_META_ANALYZE_META_PATTERN,
|
||||
CAIRO_META_REGION_ALL);
|
||||
}
|
||||
|
||||
/* Replay meta to surface. When the return status of each operation is
|
||||
* one of CAIRO_STATUS_SUCCESS, CAIRO_INT_STATUS_UNSUPPORTED, or
|
||||
* CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY the status of each operation
|
||||
|
|
|
@ -135,6 +135,74 @@ cairo_os2_fini (void)
|
|||
* as much as possible.
|
||||
*/
|
||||
_heapshrink ();
|
||||
#else
|
||||
/* GCC has a heapmin function that approximately corresponds to
|
||||
* what the Watcom function does
|
||||
*/
|
||||
_heapmin ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* This function calls the allocation function depending on which
|
||||
* method was compiled into the library: it can be native allocation
|
||||
* (DosAllocMem/DosFreeMem) or C-Library based allocation (malloc/free).
|
||||
* Actually, for pixel buffers that we use this function for, cairo
|
||||
* uses _cairo_malloc_abc, so we use that here, too. And use the
|
||||
* change to check the size argument
|
||||
*/
|
||||
void *_buffer_alloc (size_t a, size_t b, const unsigned int size)
|
||||
{
|
||||
/* check length like in the _cairo_malloc_abc macro, but we can leave
|
||||
* away the unsigned casts as our arguments are unsigned already
|
||||
*/
|
||||
size_t nbytes = b &&
|
||||
a >= INT32_MAX / b ? 0 : size &&
|
||||
a*b >= INT32_MAX / size ? 0 : a * b * size;
|
||||
void *buffer = NULL;
|
||||
#ifdef OS2_USE_PLATFORM_ALLOC
|
||||
APIRET rc = NO_ERROR;
|
||||
|
||||
rc = DosAllocMem ((PPVOID)&buffer,
|
||||
nbytes,
|
||||
#ifdef OS2_HIGH_MEMORY /* only if compiled with high-memory support, */
|
||||
OBJ_ANY | /* we can allocate anywhere! */
|
||||
#endif
|
||||
PAG_READ | PAG_WRITE | PAG_COMMIT);
|
||||
if (rc != NO_ERROR) {
|
||||
/* should there for some reason be another error, let's return
|
||||
* a null surface and free the buffer again, because that's
|
||||
* how a malloc failure would look like
|
||||
*/
|
||||
if (rc != ERROR_NOT_ENOUGH_MEMORY && buffer) {
|
||||
DosFreeMem (buffer);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
buffer = malloc (nbytes);
|
||||
#endif
|
||||
|
||||
/* This does not seem to be needed, malloc'd space is usually
|
||||
* already zero'd out!
|
||||
*/
|
||||
/*
|
||||
* memset (buffer, 0x00, nbytes);
|
||||
*/
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function selects the free function depending on which
|
||||
* allocation method was compiled into the library
|
||||
*/
|
||||
void _buffer_free (void *buffer)
|
||||
{
|
||||
#ifdef OS2_USE_PLATFORM_ALLOC
|
||||
DosFreeMem (buffer);
|
||||
#else
|
||||
free (buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -296,9 +364,9 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
|
|||
ULONG ulPixels;
|
||||
|
||||
/* allocate temporary pixel buffer */
|
||||
pchPixBuf = (unsigned char *) _cairo_malloc_abc (surface->bitmap_info.cy,
|
||||
surface->bitmap_info.cx,
|
||||
3);
|
||||
pchPixBuf = (unsigned char *) _buffer_alloc (surface->bitmap_info.cy,
|
||||
surface->bitmap_info.cx,
|
||||
3);
|
||||
pchPixSource = surface->pixels; /* start at beginning of pixel buffer */
|
||||
pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */
|
||||
|
||||
|
@ -330,7 +398,7 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
|
|||
ROP_SRCCOPY,
|
||||
BBO_IGNORE);
|
||||
|
||||
free (pchPixBuf);
|
||||
_buffer_free (pchPixBuf);
|
||||
}
|
||||
|
||||
/* Restore Y inversion */
|
||||
|
@ -714,7 +782,7 @@ cairo_os2_surface_create (HPS hps_client_window,
|
|||
local_os2_surface->bitmap_info.cBitCount = 32;
|
||||
|
||||
/* Allocate memory for pixels */
|
||||
local_os2_surface->pixels = (unsigned char *) _cairo_malloc_abc (height, width, 4);
|
||||
local_os2_surface->pixels = (unsigned char *) _buffer_alloc (height, width, 4);
|
||||
if (!(local_os2_surface->pixels)) {
|
||||
/* Not enough memory for the pixels! */
|
||||
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
|
||||
|
@ -724,13 +792,6 @@ cairo_os2_surface_create (HPS hps_client_window,
|
|||
return (cairo_surface_t *) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
/* This is possibly not needed, malloc'd space is
|
||||
* usually zero'd out!
|
||||
*/
|
||||
/*
|
||||
memset (local_os2_surface->pixels, 0x00, swpTemp.cx * swpTemp.cy * 4);
|
||||
*/
|
||||
|
||||
/* Create image surface from pixel array */
|
||||
local_os2_surface->image_surface = (cairo_image_surface_t *)
|
||||
cairo_image_surface_create_for_data (local_os2_surface->pixels,
|
||||
|
@ -741,7 +802,7 @@ cairo_os2_surface_create (HPS hps_client_window,
|
|||
|
||||
if (local_os2_surface->image_surface->base.status) {
|
||||
/* Could not create image surface! */
|
||||
free (local_os2_surface->pixels);
|
||||
_buffer_free (local_os2_surface->pixels);
|
||||
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
|
||||
DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
|
||||
free (local_os2_surface);
|
||||
|
@ -784,7 +845,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
|
|||
}
|
||||
|
||||
/* Allocate memory for new stuffs */
|
||||
pchNewPixels = (unsigned char *) _cairo_malloc_abc (new_height, new_width, 4);
|
||||
pchNewPixels = (unsigned char *) _buffer_alloc (new_height, new_width, 4);
|
||||
if (!pchNewPixels) {
|
||||
/* Not enough memory for the pixels!
|
||||
* Everything remains the same!
|
||||
|
@ -792,13 +853,6 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
|
|||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* This is possibly not needed, malloc'd space is usually
|
||||
* already zero'd out!
|
||||
*/
|
||||
/*
|
||||
memset (pchNewPixels, 0x00, new_width * new_height * 4);
|
||||
*/
|
||||
|
||||
/* Create image surface from new pixel array */
|
||||
pNewImageSurface = (cairo_image_surface_t *)
|
||||
cairo_image_surface_create_for_data (pchNewPixels,
|
||||
|
@ -811,7 +865,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
|
|||
/* Could not create image surface!
|
||||
* Everything remains the same!
|
||||
*/
|
||||
free (pchNewPixels);
|
||||
_buffer_free (pchNewPixels);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
|
@ -823,7 +877,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
|
|||
* Everything remains the same!
|
||||
*/
|
||||
cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface);
|
||||
free (pchNewPixels);
|
||||
_buffer_free (pchNewPixels);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
|
@ -839,7 +893,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
|
|||
if (rc != NO_ERROR) {
|
||||
/* Either timeout or something wrong... Exit. */
|
||||
cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface);
|
||||
free (pchNewPixels);
|
||||
_buffer_free (pchNewPixels);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
/* Okay, grab mutex and check counter again! */
|
||||
|
@ -850,7 +904,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
|
|||
* Everything remains the same!
|
||||
*/
|
||||
cairo_surface_destroy ((cairo_surface_t *) pNewImageSurface);
|
||||
free (pchNewPixels);
|
||||
_buffer_free (pchNewPixels);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
|
@ -858,7 +912,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
|
|||
/* Destroy old image surface */
|
||||
cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface));
|
||||
/* Destroy old pixel buffer */
|
||||
free (local_os2_surface->pixels);
|
||||
_buffer_free (local_os2_surface->pixels);
|
||||
/* Set new image surface */
|
||||
local_os2_surface->image_surface = pNewImageSurface;
|
||||
/* Set new pixel buffer */
|
||||
|
@ -957,7 +1011,7 @@ _cairo_os2_surface_finish (void *abstract_surface)
|
|||
/* Destroy old image surface */
|
||||
cairo_surface_destroy ((cairo_surface_t *) (local_os2_surface->image_surface));
|
||||
/* Destroy old pixel buffer */
|
||||
free (local_os2_surface->pixels);
|
||||
_buffer_free (local_os2_surface->pixels);
|
||||
DosCloseMutexSem (local_os2_surface->hmtx_use_private_fields);
|
||||
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
|
||||
|
||||
|
|
|
@ -38,8 +38,10 @@
|
|||
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <locale.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
|
@ -538,8 +540,14 @@ _cairo_output_stream_create_for_filename (const char *filename)
|
|||
|
||||
file = fopen (filename, "wb");
|
||||
if (file == NULL) {
|
||||
_cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
|
||||
switch (errno) {
|
||||
case ENOMEM:
|
||||
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
default:
|
||||
_cairo_error_throw (CAIRO_STATUS_WRITE_ERROR);
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
|
||||
}
|
||||
}
|
||||
|
||||
stream = malloc (sizeof *stream);
|
||||
|
|
|
@ -110,18 +110,22 @@ struct _cairo_paginated_surface_backend {
|
|||
*
|
||||
* 6. Replays a subset of the meta-surface operations to the target surface
|
||||
*
|
||||
* 7. Replays the remaining operations to an image surface, sets an
|
||||
* 7. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_FALLBACK
|
||||
*
|
||||
* 8. Replays the remaining operations to an image surface, sets an
|
||||
* appropriate clip on the target, then paints the resulting image
|
||||
* surface to the target.
|
||||
*
|
||||
* So, the target will see drawing operations during two separate
|
||||
* stages, (ANALYZE and RENDER). During the ANALYZE phase the target
|
||||
* should not actually perform any rendering, (for example, if
|
||||
* performing output to a file, no output should be generated during
|
||||
* this stage). Instead the drawing functions simply need to return
|
||||
* CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate
|
||||
* whether rendering would be supported. And it should do this as
|
||||
* quickly as possible.
|
||||
* So, the target will see drawing operations during three separate
|
||||
* stages, (ANALYZE, RENDER and FALLBACK). During the ANALYZE phase
|
||||
* the target should not actually perform any rendering, (for example,
|
||||
* if performing output to a file, no output should be generated
|
||||
* during this stage). Instead the drawing functions simply need to
|
||||
* return CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to
|
||||
* indicate whether rendering would be supported. And it should do
|
||||
* this as quickly as possible. The FALLBACK phase allows the surface
|
||||
* to distinguish fallback images from native rendering in case they
|
||||
* need to be handled as a special case.
|
||||
*
|
||||
* NOTE: The paginated surface layer assumes that the target surface
|
||||
* is "blank" by default at the beginning of each page, without any
|
||||
|
|
|
@ -149,7 +149,7 @@ _cairo_paginated_surface_set_size (cairo_surface_t *surface,
|
|||
width, height);
|
||||
status = cairo_surface_status (paginated_surface->meta);
|
||||
if (status)
|
||||
return status;
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ _cairo_paginated_surface_finish (void *abstract_surface)
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->page_is_blank == FALSE || surface->page_num == 1)
|
||||
status = _cairo_paginated_surface_show_page (abstract_surface);
|
||||
status = cairo_surface_show_page (abstract_surface);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
cairo_surface_finish (surface->target);
|
||||
|
@ -293,7 +293,8 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
analysis = _cairo_analysis_surface_create (surface->target,
|
||||
surface->width, surface->height);
|
||||
if (analysis == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return _cairo_surface_set_error (surface->target,
|
||||
CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
|
||||
status = _cairo_meta_surface_replay_and_create_regions (surface->meta, analysis);
|
||||
|
@ -341,6 +342,7 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
status = _cairo_meta_surface_replay_region (surface->meta,
|
||||
surface->target,
|
||||
CAIRO_META_REGION_NATIVE);
|
||||
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
if (status)
|
||||
goto FAIL;
|
||||
}
|
||||
|
@ -364,7 +366,9 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
cairo_box_int_t *boxes;
|
||||
int num_boxes, i;
|
||||
|
||||
/* Reset clip region before drawing the fall back images */
|
||||
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK);
|
||||
|
||||
/* Reset clip region before drawing the fall back images */
|
||||
status = _cairo_surface_intersect_clip_path (surface->target,
|
||||
NULL,
|
||||
CAIRO_FILL_RULE_WINDING,
|
||||
|
@ -614,43 +618,9 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface,
|
|||
static cairo_surface_t *
|
||||
_cairo_paginated_surface_snapshot (void *abstract_other)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_paginated_surface_t *other = abstract_other;
|
||||
|
||||
/* XXX: Just making a snapshot of other->meta is what we really
|
||||
* want. But this currently triggers a bug somewhere (the "mask"
|
||||
* test from the test suite segfaults).
|
||||
*
|
||||
* For now, we'll create a new image surface and replay onto
|
||||
* that. It would be tempting to replay into other->image and then
|
||||
* return a snapshot of that, but that will cause the self-copy
|
||||
* test to fail, (since our replay will be affected by a clip that
|
||||
* should not have any effect on the use of the resulting snapshot
|
||||
* as a source).
|
||||
*/
|
||||
|
||||
#if 0
|
||||
return _cairo_surface_snapshot (other->meta);
|
||||
#else
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
status = _cairo_surface_get_extents (other->target, &extents);
|
||||
if (status)
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
|
||||
surface = _cairo_paginated_surface_create_image_surface (other,
|
||||
extents.width,
|
||||
extents.height);
|
||||
|
||||
status = _cairo_meta_surface_replay (other->meta, surface);
|
||||
if (status) {
|
||||
cairo_surface_destroy (surface);
|
||||
surface = (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
return surface;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_paginated_surface_backend = {
|
||||
|
|
|
@ -148,7 +148,7 @@ _cairo_path_bounder_close_path (void *closure)
|
|||
}
|
||||
|
||||
/* XXX: Perhaps this should compute a PixRegion rather than 4 doubles */
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2)
|
||||
|
@ -165,18 +165,16 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
|
|||
_cairo_path_bounder_curve_to,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder);
|
||||
if (status) {
|
||||
*x1 = *y1 = *x2 = *y2 = 0.0;
|
||||
_cairo_path_bounder_fini (&bounder);
|
||||
return status;
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (! bounder.has_point) {
|
||||
*x1 = *y1 = *x2 = *y2 = 0.;
|
||||
} else {
|
||||
*x1 = _cairo_fixed_to_double (bounder.min_x);
|
||||
*y1 = _cairo_fixed_to_double (bounder.min_y);
|
||||
*x2 = _cairo_fixed_to_double (bounder.max_x);
|
||||
*y2 = _cairo_fixed_to_double (bounder.max_y);
|
||||
}
|
||||
|
||||
*x1 = _cairo_fixed_to_double (bounder.min_x);
|
||||
*y1 = _cairo_fixed_to_double (bounder.min_y);
|
||||
*x2 = _cairo_fixed_to_double (bounder.max_x);
|
||||
*y2 = _cairo_fixed_to_double (bounder.max_y);
|
||||
|
||||
_cairo_path_bounder_fini (&bounder);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -205,6 +205,22 @@ _cairo_stroker_face_clockwise (cairo_stroke_face_t *in, cairo_stroke_face_t *out
|
|||
return _cairo_slope_clockwise (&in_slope, &out_slope);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_slope_compare_sgn
|
||||
*
|
||||
* Return -1, 0 or 1 depending on the relative slopes of
|
||||
* two lines.
|
||||
*/
|
||||
static int
|
||||
_cairo_slope_compare_sgn (double dx1, double dy1, double dx2, double dy2)
|
||||
{
|
||||
double c = (dx1 * dy2 - dx2 * dy1);
|
||||
|
||||
if (c > 0) return 1;
|
||||
if (c < 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_stroke_face_t *out)
|
||||
{
|
||||
|
@ -272,9 +288,6 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
|
|||
double in_dot_out = ((-in->usr_vector.x * out->usr_vector.x)+
|
||||
(-in->usr_vector.y * out->usr_vector.y));
|
||||
double ml = stroker->style->miter_limit;
|
||||
double tolerance_squared = stroker->tolerance * stroker->tolerance;
|
||||
double line_width_squared = (stroker->style->line_width *
|
||||
stroker->style->line_width);
|
||||
|
||||
/* Check the miter limit -- lines meeting at an acute angle
|
||||
* can generate long miters, the limit converts them to bevel
|
||||
|
@ -332,84 +345,17 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
|
|||
*
|
||||
* 2 <= ml² (1 - in · out)
|
||||
*
|
||||
*
|
||||
* That gives us the condition to avoid generating miters that
|
||||
* are too large from angles that are too large. But we also
|
||||
* need to avoid generating miters when the angle is very small.
|
||||
*
|
||||
* The miter formed from a tiny angle is also tiny, so the
|
||||
* miter limit is not a concern. But with a tiny angle we will
|
||||
* be computing the intersection of two lines that are very
|
||||
* near parallel. Also, the limits of the fixed-point grid on
|
||||
* the input face coordinates mean that the resulting
|
||||
* intersection could be wildly wrong. (See the
|
||||
* get-path-extents test case for a call to cairo_arc that
|
||||
* results in two problematic faces.)
|
||||
*
|
||||
* Fortunately we can also derive an expression for when using
|
||||
* a bevel join instead of a miter will introduce an error no
|
||||
* larger than the tolerance. Consider the same join from
|
||||
* before but with the miter now chopped off and replaced with
|
||||
* a bevel join. The drawing is zoomed in a bit again, the
|
||||
* point marked as '*' is the center of the stroke---the point
|
||||
* where the two line segments of interest intersect:
|
||||
*
|
||||
* ----- .
|
||||
* ^ ..
|
||||
* | . .
|
||||
* | . .
|
||||
* 1/2 . .
|
||||
* miter . . |
|
||||
* length . . |
|
||||
* | .______. ___v___
|
||||
* | | . \ 1/2 bevel
|
||||
* v | . \ width
|
||||
* ---- * \ -------
|
||||
* | \ ^
|
||||
*
|
||||
*
|
||||
* The length of interest here is the vertical length of the
|
||||
* miter that is eliminated. It's length can be obtained by
|
||||
* starting with 1/2 the miter length and the subtracting off
|
||||
* the vertical length that is included by the bevel join,
|
||||
* (here termed 1/2 bevel width). To determine this new bevel
|
||||
* width, we have a small right triangle shown, the hypotenuse
|
||||
* of which has a length of 1/2 the line width, and the small
|
||||
* angle at the upper right of the figure is psi/2.
|
||||
*
|
||||
* So we have:
|
||||
*
|
||||
* sin (psi/2) = (bevel_width / 2) / (line_width / 2)
|
||||
*
|
||||
* And we can determine when the miter is required by
|
||||
* calculating when the eliminated portion of the miter is
|
||||
* greater than the tolerance:
|
||||
*
|
||||
* (miter_length / 2) - (bevel_width / 2) > tolerance
|
||||
*
|
||||
* Substituting in the above expressions for miter_length and
|
||||
* bevel_width:
|
||||
*
|
||||
* (line_width/2) / sin (psi/2) - (line_width/2) * sin (psi/2) > tolerance
|
||||
* 1 / sin(psi/2) - sin (psi/2) > 2 * tolerance / line_width
|
||||
* 1 / sin²(psi/2) -2 + sin²(psi/2) > 4 * (tolerance/line_width)²
|
||||
*
|
||||
* Use identity: sin²(psi/2) = (1-cos(psi))/2
|
||||
|
||||
* 2/(1 - cos(psi)) - 2 + (1-cos(psi))/2 > 4 * (tolerance/line_width)²
|
||||
* 4/(1 - cos(psi)) - 4 + (1-cos(psi)) > 8 * (tolerance/line_width)²
|
||||
* 4/(1 - cos(psi)) + (1-cos(psi)) > 8 * ((tolerance/line_width)² + 0.5)
|
||||
*/
|
||||
if ((2 <= ml * ml * (1 - in_dot_out)) &&
|
||||
((8 * (tolerance_squared / line_width_squared + 0.5)) <
|
||||
4 / (1 - in_dot_out) + (1 - in_dot_out))
|
||||
)
|
||||
if (2 <= ml * ml * (1 - in_dot_out))
|
||||
{
|
||||
double x1, y1, x2, y2;
|
||||
double mx, my;
|
||||
double dx1, dx2, dy1, dy2;
|
||||
cairo_point_t outer;
|
||||
cairo_point_t quad[4];
|
||||
double ix, iy;
|
||||
double fdx1, fdy1, fdx2, fdy2;
|
||||
double mdx, mdy;
|
||||
|
||||
/*
|
||||
* we've got the points already transformed to device
|
||||
|
@ -447,17 +393,46 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
|
|||
mx = (my - y2) * dx2 / dy2 + x2;
|
||||
|
||||
/*
|
||||
* Draw the quadrilateral
|
||||
* When the two outer edges are nearly parallel, slight
|
||||
* perturbations in the position of the outer points of the lines
|
||||
* caused by representing them in fixed point form can cause the
|
||||
* intersection point of the miter to move a large amount. If
|
||||
* that moves the miter intersection from between the two faces,
|
||||
* then draw a bevel instead.
|
||||
*/
|
||||
outer.x = _cairo_fixed_from_double (mx);
|
||||
outer.y = _cairo_fixed_from_double (my);
|
||||
|
||||
quad[0] = in->point;
|
||||
quad[1] = *inpt;
|
||||
quad[2] = outer;
|
||||
quad[3] = *outpt;
|
||||
ix = _cairo_fixed_to_double (in->point.x);
|
||||
iy = _cairo_fixed_to_double (in->point.y);
|
||||
|
||||
return _cairo_traps_tessellate_convex_quad (stroker->traps, quad);
|
||||
/* slope of one face */
|
||||
fdx1 = x1 - ix; fdy1 = y1 - iy;
|
||||
|
||||
/* slope of the other face */
|
||||
fdx2 = x2 - ix; fdy2 = y2 - iy;
|
||||
|
||||
/* slope from the intersection to the miter point */
|
||||
mdx = mx - ix; mdy = my - iy;
|
||||
|
||||
/*
|
||||
* Make sure the miter point line lies between the two
|
||||
* faces by comparing the slopes
|
||||
*/
|
||||
if (_cairo_slope_compare_sgn (fdx1, fdy1, mdx, mdy) !=
|
||||
_cairo_slope_compare_sgn (fdx2, fdy2, mdx, mdy))
|
||||
{
|
||||
/*
|
||||
* Draw the quadrilateral
|
||||
*/
|
||||
outer.x = _cairo_fixed_from_double (mx);
|
||||
outer.y = _cairo_fixed_from_double (my);
|
||||
|
||||
quad[0] = in->point;
|
||||
quad[1] = *inpt;
|
||||
quad[2] = outer;
|
||||
quad[3] = *outpt;
|
||||
|
||||
return _cairo_traps_tessellate_convex_quad (stroker->traps, quad);
|
||||
}
|
||||
}
|
||||
/* fall through ... */
|
||||
}
|
||||
|
|
|
@ -91,8 +91,6 @@ _cairo_pattern_set_error (cairo_pattern_t *pattern,
|
|||
static void
|
||||
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
|
||||
{
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
pattern->type = type;
|
||||
CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
|
||||
pattern->status = CAIRO_STATUS_SUCCESS;
|
||||
|
@ -213,6 +211,42 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
|
|||
}
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_pattern_create_copy (cairo_pattern_t **pattern,
|
||||
const cairo_pattern_t *other)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (other->status)
|
||||
return other->status;
|
||||
|
||||
switch (other->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
*pattern = malloc (sizeof (cairo_solid_pattern_t));
|
||||
break;
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
*pattern = malloc (sizeof (cairo_surface_pattern_t));
|
||||
break;
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
*pattern = malloc (sizeof (cairo_linear_pattern_t));
|
||||
break;
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
*pattern = malloc (sizeof (cairo_radial_pattern_t));
|
||||
break;
|
||||
}
|
||||
if (*pattern == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
status = _cairo_pattern_init_copy (*pattern, other);
|
||||
if (status) {
|
||||
free (*pattern);
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
|
||||
const cairo_color_t *color,
|
||||
|
@ -339,6 +373,8 @@ _cairo_pattern_create_in_error (cairo_status_t status)
|
|||
if (status == CAIRO_STATUS_NO_MEMORY)
|
||||
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
|
||||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK),
|
||||
CAIRO_CONTENT_COLOR);
|
||||
if (pattern->status == CAIRO_STATUS_SUCCESS)
|
||||
|
@ -379,6 +415,8 @@ cairo_pattern_create_rgb (double red, double green, double blue)
|
|||
|
||||
_cairo_color_init_rgb (&color, red, green, blue);
|
||||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
pattern = _cairo_pattern_create_solid (&color,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
if (pattern->status)
|
||||
|
@ -423,6 +461,8 @@ cairo_pattern_create_rgba (double red, double green, double blue,
|
|||
|
||||
_cairo_color_init_rgba (&color, red, green, blue, alpha);
|
||||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
pattern = _cairo_pattern_create_solid (&color,
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
if (pattern->status)
|
||||
|
@ -464,6 +504,8 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
|
|||
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
_cairo_pattern_init_for_surface (pattern, surface);
|
||||
|
||||
return &pattern->base;
|
||||
|
@ -507,6 +549,8 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
|
|||
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
_cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
|
||||
|
||||
return &pattern->base.base;
|
||||
|
@ -552,6 +596,8 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
|
|||
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
_cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
|
||||
|
||||
return &pattern->base.base;
|
||||
|
@ -1782,7 +1828,8 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
attributes);
|
||||
} break;
|
||||
default:
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
ASSERT_NOT_REACHED;
|
||||
status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Red Hat, Inc
|
||||
* Copyright © 2006 Red Hat, Inc
|
||||
* Copyright © 2007 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 University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Kristian Høgsberg <krh@redhat.com>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Adrian Johnson <ajohnson@redneon.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_PDF_OPERATORS_H
|
||||
#define CAIRO_PDF_OPERATORS_H
|
||||
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
typedef cairo_status_t
|
||||
(*cairo_pdf_operators_use_font_subset_t) (unsigned int font_id,
|
||||
unsigned int subset_id,
|
||||
void *closure);
|
||||
|
||||
typedef struct _cairo_pdf_operators {
|
||||
cairo_output_stream_t *stream;
|
||||
cairo_matrix_t cairo_to_pdf;
|
||||
cairo_scaled_font_subsets_t *font_subsets;
|
||||
cairo_pdf_operators_use_font_subset_t use_font_subset;
|
||||
void *use_font_subset_closure;
|
||||
} cairo_pdf_operators_t;
|
||||
|
||||
cairo_private void
|
||||
_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_output_stream_t *stream,
|
||||
cairo_matrix_t cairo_to_pdf,
|
||||
cairo_scaled_font_subsets_t *font_subsets);
|
||||
|
||||
cairo_private void
|
||||
_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators);
|
||||
|
||||
cairo_private void
|
||||
_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_pdf_operators_use_font_subset_t use_font_subset,
|
||||
void *closure);
|
||||
|
||||
cairo_private void
|
||||
_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_output_stream_t *stream);
|
||||
|
||||
|
||||
cairo_private void
|
||||
_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_matrix_t cairo_to_pdf);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operator_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
#endif /* CAIRO_PDF_OPERATORS_H */
|
|
@ -0,0 +1,532 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Red Hat, Inc
|
||||
* Copyright © 2006 Red Hat, Inc
|
||||
* Copyright © 2007 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 University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Kristian Høgsberg <krh@redhat.com>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Adrian Johnson <ajohnson@redneon.com>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-pdf-operators-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
|
||||
void
|
||||
_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_output_stream_t *stream,
|
||||
cairo_matrix_t cairo_to_pdf,
|
||||
cairo_scaled_font_subsets_t *font_subsets)
|
||||
{
|
||||
pdf_operators->stream = stream;
|
||||
pdf_operators->cairo_to_pdf = cairo_to_pdf;
|
||||
pdf_operators->font_subsets = font_subsets;
|
||||
pdf_operators->use_font_subset = NULL;
|
||||
pdf_operators->use_font_subset_closure = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_pdf_operators_set_font_subsets_callback (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_pdf_operators_use_font_subset_t use_font_subset,
|
||||
void *closure)
|
||||
{
|
||||
pdf_operators->use_font_subset = use_font_subset;
|
||||
pdf_operators->use_font_subset_closure = closure;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_pdf_operators_set_stream (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_output_stream_t *stream)
|
||||
{
|
||||
pdf_operators->stream = stream;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_pdf_operators_set_cairo_to_pdf_matrix (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_matrix_t cairo_to_pdf)
|
||||
{
|
||||
pdf_operators->cairo_to_pdf = cairo_to_pdf;
|
||||
}
|
||||
|
||||
typedef struct _pdf_path_info {
|
||||
cairo_output_stream_t *output;
|
||||
cairo_matrix_t *cairo_to_pdf;
|
||||
cairo_matrix_t *ctm_inverse;
|
||||
} pdf_path_info_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
pdf_path_info_t *info = closure;
|
||||
double x = _cairo_fixed_to_double (point->x);
|
||||
double y = _cairo_fixed_to_double (point->y);
|
||||
|
||||
if (info->cairo_to_pdf)
|
||||
cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
|
||||
if (info->ctm_inverse)
|
||||
cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
|
||||
|
||||
_cairo_output_stream_printf (info->output,
|
||||
"%f %f m ", x, y);
|
||||
|
||||
return _cairo_output_stream_get_status (info->output);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
pdf_path_info_t *info = closure;
|
||||
double x = _cairo_fixed_to_double (point->x);
|
||||
double y = _cairo_fixed_to_double (point->y);
|
||||
|
||||
if (info->cairo_to_pdf)
|
||||
cairo_matrix_transform_point (info->cairo_to_pdf, &x, &y);
|
||||
if (info->ctm_inverse)
|
||||
cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
|
||||
|
||||
_cairo_output_stream_printf (info->output,
|
||||
"%f %f l ", x, y);
|
||||
|
||||
return _cairo_output_stream_get_status (info->output);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_path_curve_to (void *closure,
|
||||
cairo_point_t *b,
|
||||
cairo_point_t *c,
|
||||
cairo_point_t *d)
|
||||
{
|
||||
pdf_path_info_t *info = closure;
|
||||
double bx = _cairo_fixed_to_double (b->x);
|
||||
double by = _cairo_fixed_to_double (b->y);
|
||||
double cx = _cairo_fixed_to_double (c->x);
|
||||
double cy = _cairo_fixed_to_double (c->y);
|
||||
double dx = _cairo_fixed_to_double (d->x);
|
||||
double dy = _cairo_fixed_to_double (d->y);
|
||||
|
||||
if (info->cairo_to_pdf) {
|
||||
cairo_matrix_transform_point (info->cairo_to_pdf, &bx, &by);
|
||||
cairo_matrix_transform_point (info->cairo_to_pdf, &cx, &cy);
|
||||
cairo_matrix_transform_point (info->cairo_to_pdf, &dx, &dy);
|
||||
}
|
||||
if (info->ctm_inverse) {
|
||||
cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
|
||||
cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
|
||||
cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (info->output,
|
||||
"%f %f %f %f %f %f c ",
|
||||
bx, by, cx, cy, dx, dy);
|
||||
return _cairo_output_stream_get_status (info->output);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_path_close_path (void *closure)
|
||||
{
|
||||
pdf_path_info_t *info = closure;
|
||||
|
||||
_cairo_output_stream_printf (info->output,
|
||||
"h\r\n");
|
||||
|
||||
return _cairo_output_stream_get_status (info->output);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_pdf_operators_clip (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule)
|
||||
{
|
||||
const char *pdf_operator;
|
||||
|
||||
if (! path->has_current_point) {
|
||||
/* construct an empty path */
|
||||
_cairo_output_stream_printf (pdf_operators->stream, "0 0 m ");
|
||||
} else {
|
||||
pdf_path_info_t info;
|
||||
cairo_status_t status;
|
||||
|
||||
info.output = pdf_operators->stream;
|
||||
info.cairo_to_pdf = &pdf_operators->cairo_to_pdf;
|
||||
info.ctm_inverse = NULL;
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_pdf_path_move_to,
|
||||
_cairo_pdf_path_line_to,
|
||||
_cairo_pdf_path_curve_to,
|
||||
_cairo_pdf_path_close_path,
|
||||
&info);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
switch (fill_rule) {
|
||||
case CAIRO_FILL_RULE_WINDING:
|
||||
pdf_operator = "W";
|
||||
break;
|
||||
case CAIRO_FILL_RULE_EVEN_ODD:
|
||||
pdf_operator = "W*";
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%s n\r\n",
|
||||
pdf_operator);
|
||||
|
||||
return _cairo_output_stream_get_status (pdf_operators->stream);
|
||||
}
|
||||
|
||||
static int
|
||||
_cairo_pdf_line_cap (cairo_line_cap_t cap)
|
||||
{
|
||||
switch (cap) {
|
||||
case CAIRO_LINE_CAP_BUTT:
|
||||
return 0;
|
||||
case CAIRO_LINE_CAP_ROUND:
|
||||
return 1;
|
||||
case CAIRO_LINE_CAP_SQUARE:
|
||||
return 2;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_cairo_pdf_line_join (cairo_line_join_t join)
|
||||
{
|
||||
switch (join) {
|
||||
case CAIRO_LINE_JOIN_MITER:
|
||||
return 0;
|
||||
case CAIRO_LINE_JOIN_ROUND:
|
||||
return 1;
|
||||
case CAIRO_LINE_JOIN_BEVEL:
|
||||
return 2;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_operators_emit_stroke_style (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_stroke_style_t *style)
|
||||
{
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%f w\r\n",
|
||||
style->line_width);
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%d J\r\n",
|
||||
_cairo_pdf_line_cap (style->line_cap));
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%d j\r\n",
|
||||
_cairo_pdf_line_join (style->line_join));
|
||||
|
||||
if (style->num_dashes) {
|
||||
unsigned int d;
|
||||
_cairo_output_stream_printf (pdf_operators->stream, "[");
|
||||
for (d = 0; d < style->num_dashes; d++)
|
||||
_cairo_output_stream_printf (pdf_operators->stream, " %f", style->dash[d]);
|
||||
_cairo_output_stream_printf (pdf_operators->stream, "] %f d\r\n",
|
||||
style->dash_offset);
|
||||
} else {
|
||||
_cairo_output_stream_printf (pdf_operators->stream, "[] 0.0 d\r\n");
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%f M ",
|
||||
style->miter_limit);
|
||||
|
||||
return _cairo_output_stream_get_status (pdf_operators->stream);
|
||||
}
|
||||
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_pdf_operator_stroke (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse)
|
||||
{
|
||||
pdf_path_info_t info;
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t m;
|
||||
|
||||
status = _cairo_pdf_operators_emit_stroke_style (pdf_operators, style);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
info.output = pdf_operators->stream;
|
||||
info.cairo_to_pdf = NULL;
|
||||
info.ctm_inverse = ctm_inverse;
|
||||
|
||||
cairo_matrix_multiply (&m, ctm, &pdf_operators->cairo_to_pdf);
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"q %f %f %f %f %f %f cm\r\n",
|
||||
m.xx, m.yx, m.xy, m.yy,
|
||||
m.x0, m.y0);
|
||||
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_pdf_path_move_to,
|
||||
_cairo_pdf_path_line_to,
|
||||
_cairo_pdf_path_curve_to,
|
||||
_cairo_pdf_path_close_path,
|
||||
&info);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream, "S Q\r\n");
|
||||
|
||||
return _cairo_output_stream_get_status (pdf_operators->stream);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_pdf_operators_fill (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule)
|
||||
{
|
||||
const char *pdf_operator;
|
||||
cairo_status_t status;
|
||||
pdf_path_info_t info;
|
||||
|
||||
info.output = pdf_operators->stream;
|
||||
info.cairo_to_pdf = &pdf_operators->cairo_to_pdf;
|
||||
info.ctm_inverse = NULL;
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_pdf_path_move_to,
|
||||
_cairo_pdf_path_line_to,
|
||||
_cairo_pdf_path_curve_to,
|
||||
_cairo_pdf_path_close_path,
|
||||
&info);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
switch (fill_rule) {
|
||||
case CAIRO_FILL_RULE_WINDING:
|
||||
pdf_operator = "f";
|
||||
break;
|
||||
case CAIRO_FILL_RULE_EVEN_ODD:
|
||||
pdf_operator = "f*";
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%s\r\n",
|
||||
pdf_operator);
|
||||
|
||||
return _cairo_output_stream_get_status (pdf_operators->stream);
|
||||
}
|
||||
|
||||
#define GLYPH_POSITION_TOLERANCE 0.001
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_pdf_operators_show_glyphs (cairo_pdf_operators_t *pdf_operators,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
unsigned int current_subset_id = (unsigned int)-1;
|
||||
cairo_scaled_font_subsets_glyph_t subset_glyph;
|
||||
cairo_bool_t diagonal, in_TJ;
|
||||
cairo_status_t status;
|
||||
double Tlm_x = 0, Tlm_y = 0;
|
||||
double Tm_x = 0, y;
|
||||
int i, hex_width;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
cairo_matrix_transform_point (&pdf_operators->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"BT\r\n");
|
||||
|
||||
if (scaled_font->scale.xy == 0.0 &&
|
||||
scaled_font->scale.yx == 0.0)
|
||||
diagonal = TRUE;
|
||||
else
|
||||
diagonal = FALSE;
|
||||
|
||||
in_TJ = FALSE;
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
status = _cairo_scaled_font_subsets_map_glyph (pdf_operators->font_subsets,
|
||||
scaled_font, glyphs[i].index,
|
||||
&subset_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (subset_glyph.is_composite)
|
||||
hex_width = 4;
|
||||
else
|
||||
hex_width = 2;
|
||||
|
||||
if (subset_glyph.is_scaled == FALSE) {
|
||||
y = 0.0;
|
||||
cairo_matrix_transform_distance (&scaled_font->scale,
|
||||
&subset_glyph.x_advance,
|
||||
&y);
|
||||
}
|
||||
|
||||
if (subset_glyph.subset_id != current_subset_id) {
|
||||
if (in_TJ) {
|
||||
_cairo_output_stream_printf (pdf_operators->stream, ">] TJ\r\n");
|
||||
in_TJ = FALSE;
|
||||
}
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"/f-%d-%d 1 Tf\r\n",
|
||||
subset_glyph.font_id,
|
||||
subset_glyph.subset_id);
|
||||
if (pdf_operators->use_font_subset) {
|
||||
status = pdf_operators->use_font_subset (subset_glyph.font_id,
|
||||
subset_glyph.subset_id,
|
||||
pdf_operators->use_font_subset_closure);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (subset_glyph.subset_id != current_subset_id || !diagonal) {
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%f %f %f %f %f %f Tm\r\n",
|
||||
scaled_font->scale.xx,
|
||||
-scaled_font->scale.yx,
|
||||
-scaled_font->scale.xy,
|
||||
scaled_font->scale.yy,
|
||||
glyphs[i].x,
|
||||
glyphs[i].y);
|
||||
current_subset_id = subset_glyph.subset_id;
|
||||
Tlm_x = glyphs[i].x;
|
||||
Tlm_y = glyphs[i].y;
|
||||
Tm_x = Tlm_x;
|
||||
}
|
||||
|
||||
if (diagonal) {
|
||||
if (i < num_glyphs - 1 &&
|
||||
fabs((glyphs[i].y - glyphs[i+1].y)/scaled_font->scale.yy) < GLYPH_POSITION_TOLERANCE &&
|
||||
fabs((glyphs[i].x - glyphs[i+1].x)/scaled_font->scale.xx) < 10)
|
||||
{
|
||||
if (!in_TJ) {
|
||||
if (i != 0) {
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%f %f Td\r\n",
|
||||
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
|
||||
(glyphs[i].y - Tlm_y)/scaled_font->scale.yy);
|
||||
|
||||
Tlm_x = glyphs[i].x;
|
||||
Tlm_y = glyphs[i].y;
|
||||
Tm_x = Tlm_x;
|
||||
}
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"[<%0*x",
|
||||
hex_width,
|
||||
subset_glyph.subset_glyph_index);
|
||||
Tm_x += subset_glyph.x_advance;
|
||||
in_TJ = TRUE;
|
||||
} else {
|
||||
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
|
||||
double delta = glyphs[i].x - Tm_x;
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"> %f <",
|
||||
-1000.0*delta/scaled_font->scale.xx);
|
||||
Tm_x += delta;
|
||||
}
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%0*x",
|
||||
hex_width,
|
||||
subset_glyph.subset_glyph_index);
|
||||
Tm_x += subset_glyph.x_advance;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in_TJ) {
|
||||
if (fabs((glyphs[i].x - Tm_x)/scaled_font->scale.xx) > GLYPH_POSITION_TOLERANCE) {
|
||||
double delta = glyphs[i].x - Tm_x;
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"> %f <",
|
||||
-1000.0*delta/scaled_font->scale.xx);
|
||||
Tm_x += delta;
|
||||
}
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%0*x>] TJ\r\n",
|
||||
hex_width,
|
||||
subset_glyph.subset_glyph_index);
|
||||
Tm_x += subset_glyph.x_advance;
|
||||
in_TJ = FALSE;
|
||||
} else {
|
||||
if (i != 0) {
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"%f %f Td ",
|
||||
(glyphs[i].x - Tlm_x)/scaled_font->scale.xx,
|
||||
(glyphs[i].y - Tlm_y)/-scaled_font->scale.yy);
|
||||
Tlm_x = glyphs[i].x;
|
||||
Tlm_y = glyphs[i].y;
|
||||
Tm_x = Tlm_x;
|
||||
}
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"<%0*x> Tj ",
|
||||
hex_width,
|
||||
subset_glyph.subset_glyph_index);
|
||||
Tm_x += subset_glyph.x_advance;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"<%0*x> Tj\r\n",
|
||||
hex_width,
|
||||
subset_glyph.subset_glyph_index);
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (pdf_operators->stream,
|
||||
"ET\r\n");
|
||||
|
||||
return _cairo_output_stream_get_status (pdf_operators->stream);
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Red Hat, Inc
|
||||
* Copyright © 2006 Red Hat, Inc
|
||||
* Copyright © 2007 Adrian Johnson
|
||||
* Copyright © 2007, 2008 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
|
||||
|
@ -44,6 +45,8 @@
|
|||
#include "cairo-pdf.h"
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
#include "cairo-pdf-operators-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
|
||||
typedef struct _cairo_pdf_resource {
|
||||
unsigned int id;
|
||||
|
@ -57,6 +60,37 @@ typedef struct _cairo_pdf_group_resources {
|
|||
cairo_array_t fonts;
|
||||
} cairo_pdf_group_resources_t;
|
||||
|
||||
typedef struct _cairo_pdf_pattern {
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_pdf_resource_t pattern_res;
|
||||
cairo_pdf_resource_t gstate_res;
|
||||
} cairo_pdf_pattern_t;
|
||||
|
||||
typedef enum _cairo_pdf_operation {
|
||||
PDF_PAINT,
|
||||
PDF_MASK,
|
||||
PDF_FILL,
|
||||
PDF_STROKE,
|
||||
PDF_SHOW_GLYPHS
|
||||
} cairo_pdf_operation_t;
|
||||
|
||||
typedef struct _cairo_pdf_smask_group
|
||||
{
|
||||
cairo_pdf_resource_t group_res;
|
||||
cairo_pdf_operation_t operation;
|
||||
cairo_pattern_t *source;
|
||||
cairo_pdf_resource_t source_res;
|
||||
cairo_pattern_t *mask;
|
||||
cairo_path_fixed_t path;
|
||||
cairo_fill_rule_t fill_rule;
|
||||
cairo_stroke_style_t *style;
|
||||
cairo_matrix_t ctm;
|
||||
cairo_matrix_t ctm_inverse;
|
||||
cairo_glyph_t *glyphs;
|
||||
int num_glyphs;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
} cairo_pdf_smask_group_t;
|
||||
|
||||
typedef struct _cairo_pdf_surface cairo_pdf_surface_t;
|
||||
|
||||
struct _cairo_pdf_surface {
|
||||
|
@ -74,8 +108,9 @@ struct _cairo_pdf_surface {
|
|||
cairo_array_t pages;
|
||||
cairo_array_t rgb_linear_functions;
|
||||
cairo_array_t alpha_linear_functions;
|
||||
cairo_array_t patterns;
|
||||
cairo_array_t smask_groups;
|
||||
cairo_array_t knockout_group;
|
||||
cairo_array_t content_group;
|
||||
|
||||
cairo_scaled_font_subsets_t *font_subsets;
|
||||
cairo_array_t fonts;
|
||||
|
@ -85,6 +120,11 @@ struct _cairo_pdf_surface {
|
|||
|
||||
cairo_bool_t compress_content;
|
||||
|
||||
cairo_pdf_resource_t content;
|
||||
cairo_pdf_resource_t content_resources;
|
||||
cairo_pdf_group_resources_t resources;
|
||||
cairo_bool_t has_fallback_images;
|
||||
|
||||
struct {
|
||||
cairo_bool_t active;
|
||||
cairo_pdf_resource_t self;
|
||||
|
@ -99,32 +139,11 @@ struct _cairo_pdf_surface {
|
|||
cairo_output_stream_t *stream;
|
||||
cairo_output_stream_t *mem_stream;
|
||||
cairo_output_stream_t *old_output;
|
||||
cairo_pdf_group_resources_t resources;
|
||||
cairo_pdf_resource_t resource;
|
||||
cairo_bool_t is_knockout;
|
||||
cairo_pdf_resource_t first_object;
|
||||
} group_stream;
|
||||
|
||||
struct {
|
||||
cairo_bool_t active;
|
||||
cairo_output_stream_t *stream;
|
||||
cairo_output_stream_t *mem_stream;
|
||||
cairo_output_stream_t *old_output;
|
||||
cairo_pdf_group_resources_t resources;
|
||||
} content_stream;
|
||||
|
||||
struct {
|
||||
cairo_pattern_type_t type;
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
double alpha;
|
||||
cairo_pdf_resource_t smask;
|
||||
cairo_pdf_resource_t pattern;
|
||||
} emitted_pattern;
|
||||
|
||||
cairo_array_t *current_group;
|
||||
cairo_pdf_group_resources_t *current_resources;
|
||||
|
||||
cairo_pdf_operators_t pdf_operators;
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
|
||||
cairo_bool_t force_fallbacks;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -275,8 +275,14 @@ cairo_surface_write_to_png (cairo_surface_t *surface,
|
|||
cairo_status_t status;
|
||||
|
||||
fp = fopen (filename, "wb");
|
||||
if (fp == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
|
||||
if (fp == NULL) {
|
||||
switch (errno) {
|
||||
case ENOMEM:
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
default:
|
||||
return _cairo_error (CAIRO_STATUS_WRITE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
status = write_png (surface, stdio_write_func, fp);
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ typedef struct cairo_ps_surface {
|
|||
cairo_array_t *dsc_comment_target;
|
||||
|
||||
cairo_ps_level_t ps_level;
|
||||
cairo_ps_level_t ps_level_used;
|
||||
|
||||
cairo_surface_t *paginated_surface;
|
||||
} cairo_ps_surface_t;
|
||||
|
|
|
@ -47,12 +47,18 @@
|
|||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <zlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define DEBUG_PS 0
|
||||
|
||||
#ifndef HAVE_CTIME_R
|
||||
#define ctime_r(T, BUF) ctime (T)
|
||||
#endif
|
||||
|
||||
typedef enum _cairo_image_transparency {
|
||||
CAIRO_IMAGE_IS_OPAQUE,
|
||||
CAIRO_IMAGE_HAS_BILEVEL_ALPHA,
|
||||
|
@ -318,18 +324,19 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface,
|
|||
static void
|
||||
_cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
|
||||
{
|
||||
char ctime_buf[26];
|
||||
time_t now;
|
||||
char **comments;
|
||||
int i, num_comments;
|
||||
const char *level;
|
||||
int level;
|
||||
const char *eps_header = "";
|
||||
|
||||
now = time (NULL);
|
||||
|
||||
if (surface->ps_level == CAIRO_PS_LEVEL_2)
|
||||
level = "2";
|
||||
if (surface->ps_level_used == CAIRO_PS_LEVEL_2)
|
||||
level = 2;
|
||||
else
|
||||
level = "3";
|
||||
level = 3;
|
||||
|
||||
if (surface->eps)
|
||||
eps_header = " EPSF-3.0";
|
||||
|
@ -342,7 +349,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
|
|||
"%%%%BoundingBox: %d %d %d %d\n",
|
||||
eps_header,
|
||||
cairo_version_string (),
|
||||
ctime (&now),
|
||||
ctime_r (&now, ctime_buf),
|
||||
surface->num_pages,
|
||||
surface->bbox_x1,
|
||||
surface->bbox_y1,
|
||||
|
@ -351,7 +358,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
|
|||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"%%%%DocumentData: Clean7Bit\n"
|
||||
"%%%%LanguageLevel: %s\n",
|
||||
"%%%%LanguageLevel: %d\n",
|
||||
level);
|
||||
|
||||
num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
|
||||
|
@ -375,6 +382,14 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
|
|||
"/dict_count countdictstack def\n"
|
||||
"/op_count count 1 sub def\n"
|
||||
"userdict begin\n");
|
||||
} else {
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/languagelevel where{pop languagelevel}{1}ifelse %d lt{/Helvetica\n"
|
||||
"findfont 12 scalefont setfont 50 500 moveto\n"
|
||||
"(This print job requires a PostScript Language Level %d printer.)show\n"
|
||||
"showpage quit}if\n",
|
||||
level,
|
||||
level);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
|
@ -569,7 +584,8 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
|
|||
static cairo_int_status_t
|
||||
_cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index)
|
||||
unsigned long glyph_index,
|
||||
cairo_box_t *bbox)
|
||||
{
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_status_t status;
|
||||
|
@ -582,6 +598,7 @@ _cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t *surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
*bbox = scaled_glyph->bbox;
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"0 0 %f %f %f %f setcachedevice\n",
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
|
||||
|
@ -594,6 +611,8 @@ _cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t *surface,
|
|||
surface->final_stream,
|
||||
scaled_glyph->path,
|
||||
CAIRO_LINE_CAP_ROUND);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"F\n");
|
||||
|
@ -604,13 +623,15 @@ _cairo_ps_surface_emit_outline_glyph_data (cairo_ps_surface_t *surface,
|
|||
static cairo_int_status_t
|
||||
_cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph_index)
|
||||
unsigned long glyph_index,
|
||||
cairo_box_t *bbox)
|
||||
{
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_status_t status;
|
||||
cairo_image_surface_t *image;
|
||||
unsigned char *row, *byte;
|
||||
int rows, cols;
|
||||
double x_advance, y_advance;
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyph_index,
|
||||
|
@ -620,6 +641,11 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
*bbox = scaled_glyph->bbox;
|
||||
x_advance = scaled_glyph->metrics.x_advance;
|
||||
y_advance = scaled_glyph->metrics.y_advance;
|
||||
cairo_matrix_transform_distance (&scaled_font->ctm, &x_advance, &y_advance);
|
||||
|
||||
image = scaled_glyph->surface;
|
||||
if (image->format != CAIRO_FORMAT_A1) {
|
||||
image = _cairo_image_surface_clone (image, CAIRO_FORMAT_A1);
|
||||
|
@ -628,11 +654,12 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
|
|||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"0 0 %f %f %f %f setcachedevice\n",
|
||||
"%f 0 %f %f %f %f setcachedevice\n",
|
||||
x_advance,
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
|
||||
- _cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
|
||||
- _cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
|
||||
_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"<<\n"
|
||||
|
@ -678,20 +705,25 @@ static cairo_status_t
|
|||
_cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long scaled_font_glyph_index,
|
||||
unsigned int subset_glyph_index)
|
||||
unsigned int subset_glyph_index,
|
||||
cairo_box_t *bbox)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"\t\t{ %% %d\n", subset_glyph_index);
|
||||
|
||||
status = _cairo_ps_surface_emit_outline_glyph_data (surface,
|
||||
scaled_font,
|
||||
scaled_font_glyph_index);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
|
||||
scaled_font,
|
||||
scaled_font_glyph_index);
|
||||
if (subset_glyph_index != 0) {
|
||||
status = _cairo_ps_surface_emit_outline_glyph_data (surface,
|
||||
scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
bbox);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
status = _cairo_ps_surface_emit_bitmap_glyph_data (surface,
|
||||
scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
bbox);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"\t\t}\n");
|
||||
|
@ -711,47 +743,84 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
|||
cairo_status_t status;
|
||||
cairo_matrix_t matrix;
|
||||
unsigned int i;
|
||||
cairo_box_t font_bbox = {{0,0},{0,0}};
|
||||
cairo_box_t bbox = {{0,0},{0,0}};
|
||||
|
||||
#if DEBUG_PS
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"%% _cairo_ps_surface_emit_type3_font_subset\n");
|
||||
#endif
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/CairoFont-%d-%d <<\n",
|
||||
font_subset->font_id,
|
||||
font_subset->subset_id);
|
||||
|
||||
matrix = font_subset->scaled_font->scale;
|
||||
status = cairo_matrix_invert (&matrix);
|
||||
/* _cairo_scaled_font_init ensures the matrix is invertible */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"\t/FontType\t3\n"
|
||||
"\t/FontMatrix\t[%f %f %f %f 0 0]\n"
|
||||
"\t/Encoding\t[0]\n"
|
||||
"\t/FontBBox\t[0 0 10 10]\n"
|
||||
"\t/Glyphs [\n",
|
||||
"8 dict begin\n"
|
||||
"/FontType 3 def\n"
|
||||
"/FontMatrix [%f %f %f %f 0 0] def\n"
|
||||
"/Encoding 256 array def\n"
|
||||
"0 1 255 { Encoding exch /.notdef put } for\n",
|
||||
matrix.xx,
|
||||
matrix.yx,
|
||||
-matrix.xy,
|
||||
-matrix.yy);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||
status = _cairo_ps_surface_emit_glyph (surface,
|
||||
font_subset->scaled_font,
|
||||
font_subset->glyphs[i], i);
|
||||
if (status)
|
||||
return status;
|
||||
for (i = 1; i < font_subset->num_glyphs; i++) {
|
||||
if (font_subset->glyph_names != NULL) {
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"Encoding %d /%s put\n",
|
||||
i, font_subset->glyph_names[i]);
|
||||
} else {
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"Encoding %d /g%d put\n", i, i);
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"\t]\n"
|
||||
"\t/BuildChar {\n"
|
||||
"\t\texch /Glyphs get\n"
|
||||
"\t\texch get exec\n"
|
||||
"\t}\n"
|
||||
">> definefont pop\n");
|
||||
"/Glyphs [\n");
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||
status = _cairo_ps_surface_emit_glyph (surface,
|
||||
font_subset->scaled_font,
|
||||
font_subset->glyphs[i], i,
|
||||
&bbox);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (i == 0) {
|
||||
font_bbox.p1.x = bbox.p1.x;
|
||||
font_bbox.p1.y = bbox.p1.y;
|
||||
font_bbox.p2.x = bbox.p2.x;
|
||||
font_bbox.p2.y = bbox.p2.y;
|
||||
} else {
|
||||
if (bbox.p1.x < font_bbox.p1.x)
|
||||
font_bbox.p1.x = bbox.p1.x;
|
||||
if (bbox.p1.y < font_bbox.p1.y)
|
||||
font_bbox.p1.y = bbox.p1.y;
|
||||
if (bbox.p2.x > font_bbox.p2.x)
|
||||
font_bbox.p2.x = bbox.p2.x;
|
||||
if (bbox.p2.y > font_bbox.p2.y)
|
||||
font_bbox.p2.y = bbox.p2.y;
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"] def\n"
|
||||
"/FontBBox [%f %f %f %f] def\n"
|
||||
"/BuildChar {\n"
|
||||
" exch /Glyphs get\n"
|
||||
" exch get exec\n"
|
||||
"} bind def\n"
|
||||
"currentdict\n"
|
||||
"end\n"
|
||||
"/CairoFont-%d-%d exch definefont pop\n",
|
||||
_cairo_fixed_to_double (font_bbox.p1.x),
|
||||
_cairo_fixed_to_double (font_bbox.p1.y),
|
||||
_cairo_fixed_to_double (font_bbox.p2.x),
|
||||
_cairo_fixed_to_double (font_bbox.p2.y),
|
||||
font_subset->font_id,
|
||||
font_subset->subset_id);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -830,15 +899,20 @@ BAIL:
|
|||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_body (cairo_ps_surface_t *surface)
|
||||
{
|
||||
char buf[4096];
|
||||
int n;
|
||||
|
||||
if (ferror (surface->tmpfile) != 0)
|
||||
return _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
|
||||
|
||||
rewind (surface->tmpfile);
|
||||
while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0)
|
||||
_cairo_output_stream_write (surface->final_stream, buf, n);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -878,8 +952,17 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
surface->final_stream = stream;
|
||||
|
||||
surface->tmpfile = tmpfile ();
|
||||
if (surface->tmpfile == NULL)
|
||||
if (surface->tmpfile == NULL) {
|
||||
switch (errno) {
|
||||
case ENOMEM:
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
break;
|
||||
default:
|
||||
status = _cairo_error (CAIRO_STATUS_TEMP_FILE_ERROR);
|
||||
break;
|
||||
}
|
||||
goto CLEANUP_SURFACE;
|
||||
}
|
||||
|
||||
surface->stream = _cairo_output_stream_create_for_file (surface->tmpfile);
|
||||
status = _cairo_output_stream_get_status (surface->stream);
|
||||
|
@ -892,6 +975,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
|
||||
surface->eps = FALSE;
|
||||
surface->ps_level = CAIRO_PS_LEVEL_3;
|
||||
surface->ps_level_used = CAIRO_PS_LEVEL_2;
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
|
||||
|
@ -1436,11 +1520,16 @@ _cairo_ps_surface_finish (void *abstract_surface)
|
|||
_cairo_ps_surface_emit_header (surface);
|
||||
|
||||
status = _cairo_ps_surface_emit_font_subsets (surface);
|
||||
if (status)
|
||||
goto CLEANUP;
|
||||
|
||||
_cairo_ps_surface_emit_body (surface);
|
||||
status = _cairo_ps_surface_emit_body (surface);
|
||||
if (status)
|
||||
goto CLEANUP;
|
||||
|
||||
_cairo_ps_surface_emit_footer (surface);
|
||||
|
||||
CLEANUP:
|
||||
status2 = _cairo_output_stream_destroy (surface->stream);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
|
@ -1515,7 +1604,6 @@ static cairo_status_t
|
|||
_analyze_image_transparency (cairo_image_surface_t *image,
|
||||
cairo_image_transparency_t *transparency)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int x, y;
|
||||
|
||||
if (image->format == CAIRO_FORMAT_RGB24) {
|
||||
|
@ -1547,9 +1635,8 @@ _analyze_image_transparency (cairo_image_surface_t *image,
|
|||
}
|
||||
}
|
||||
}
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -1580,10 +1667,12 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
|
|||
break;
|
||||
|
||||
case CAIRO_IMAGE_HAS_BILEVEL_ALPHA:
|
||||
if (surface->ps_level == CAIRO_PS_LEVEL_2)
|
||||
if (surface->ps_level == CAIRO_PS_LEVEL_2) {
|
||||
status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
|
||||
else
|
||||
} else {
|
||||
surface->ps_level_used = CAIRO_PS_LEVEL_3;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAIRO_IMAGE_HAS_ALPHA:
|
||||
|
@ -1646,6 +1735,7 @@ _gradient_pattern_supported (cairo_ps_surface_t *surface,
|
|||
if (surface->ps_level == CAIRO_PS_LEVEL_2)
|
||||
return FALSE;
|
||||
|
||||
surface->ps_level_used = CAIRO_PS_LEVEL_3;
|
||||
extend = cairo_pattern_get_extend (pattern);
|
||||
|
||||
if (extend == CAIRO_EXTEND_REPEAT ||
|
||||
|
@ -1706,19 +1796,16 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
|
|||
op == CAIRO_OPERATOR_OVER))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (op == CAIRO_OPERATOR_SOURCE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
|
||||
|
||||
if ( _cairo_surface_is_meta (surface_pattern->surface))
|
||||
return CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN;
|
||||
else
|
||||
return _cairo_ps_surface_analyze_surface_pattern_transparency (surface,
|
||||
surface_pattern);
|
||||
}
|
||||
|
||||
if (op == CAIRO_OPERATOR_SOURCE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If
|
||||
* the pattern contains transparency, we return
|
||||
* CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis
|
||||
|
@ -1729,6 +1816,13 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
|
|||
* background to convert the pattern to opaque.
|
||||
*/
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
|
||||
|
||||
return _cairo_ps_surface_analyze_surface_pattern_transparency (surface,
|
||||
surface_pattern);
|
||||
}
|
||||
|
||||
if (_cairo_pattern_is_opaque (pattern))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
else
|
||||
|
@ -1889,10 +1983,8 @@ _cairo_ps_surface_flatten_image_transparency (cairo_ps_surface_t *surface,
|
|||
opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
||||
image->width,
|
||||
image->height);
|
||||
if (opaque->status) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return status;
|
||||
}
|
||||
if (opaque->status)
|
||||
return opaque->status;
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
|
||||
|
||||
|
@ -1930,8 +2022,8 @@ fail:
|
|||
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface,
|
||||
unsigned char *data,
|
||||
unsigned long length)
|
||||
unsigned char *data,
|
||||
unsigned long length)
|
||||
{
|
||||
cairo_output_stream_t *base85_stream, *string_array_stream;
|
||||
cairo_status_t status, status2;
|
||||
|
@ -1962,7 +2054,7 @@ static cairo_status_t
|
|||
_cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
||||
cairo_image_surface_t *image,
|
||||
const char *name,
|
||||
cairo_operator_t op)
|
||||
cairo_operator_t op)
|
||||
{
|
||||
cairo_status_t status;
|
||||
unsigned char *rgb, *rgb_compressed;
|
||||
|
@ -1988,10 +2080,14 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
|||
if (op == CAIRO_OPERATOR_SOURCE ||
|
||||
transparency == CAIRO_IMAGE_HAS_ALPHA ||
|
||||
(transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA &&
|
||||
surface->ps_level == CAIRO_PS_LEVEL_2)) {
|
||||
_cairo_ps_surface_flatten_image_transparency (surface,
|
||||
image,
|
||||
&opaque_image);
|
||||
surface->ps_level == CAIRO_PS_LEVEL_2))
|
||||
{
|
||||
status = _cairo_ps_surface_flatten_image_transparency (surface,
|
||||
image,
|
||||
&opaque_image);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
use_mask = FALSE;
|
||||
} else if (transparency == CAIRO_IMAGE_IS_OPAQUE) {
|
||||
opaque_image = image;
|
||||
|
@ -2193,7 +2289,7 @@ _cairo_ps_surface_emit_image_surface (cairo_ps_surface_t *surface,
|
|||
cairo_surface_pattern_t *pattern,
|
||||
int *width,
|
||||
int *height,
|
||||
cairo_operator_t op)
|
||||
cairo_operator_t op)
|
||||
{
|
||||
cairo_image_surface_t *image;
|
||||
void *image_extra;
|
||||
|
@ -2205,7 +2301,7 @@ _cairo_ps_surface_emit_image_surface (cairo_ps_surface_t *surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_ps_surface_emit_image (surface, image, "CairoPattern", op);
|
||||
status = _cairo_ps_surface_emit_image (surface, image, "CairoPattern", op);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
|
@ -2248,7 +2344,9 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
|
|||
surface->height);
|
||||
}
|
||||
|
||||
status = _cairo_meta_surface_replay (meta_surface, &surface->base);
|
||||
status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
|
||||
CAIRO_META_REGION_NATIVE);
|
||||
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -2263,11 +2361,11 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
|
|||
}
|
||||
|
||||
static void
|
||||
_cairo_ps_surface_flatten_transparency (cairo_ps_surface_t *surface,
|
||||
const cairo_color_t *color,
|
||||
double *red,
|
||||
double *green,
|
||||
double *blue)
|
||||
_cairo_ps_surface_flatten_transparency (cairo_ps_surface_t *surface,
|
||||
const cairo_color_t *color,
|
||||
double *red,
|
||||
double *green,
|
||||
double *blue)
|
||||
{
|
||||
*red = color->red;
|
||||
*green = color->green;
|
||||
|
@ -2309,7 +2407,7 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
|
|||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
cairo_operator_t op)
|
||||
cairo_operator_t op)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int pattern_width = 0; /* squelch bogus compiler warning */
|
||||
|
@ -2327,9 +2425,13 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
|||
|
||||
status = _cairo_ps_surface_emit_meta_surface (surface,
|
||||
meta_surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
pattern_width = pattern_extents.width;
|
||||
pattern_height = pattern_extents.height;
|
||||
} else {
|
||||
|
@ -2475,7 +2577,7 @@ _cairo_ps_surface_emit_pattern_stops (cairo_ps_surface_t *surface,
|
|||
|
||||
allstops = _cairo_malloc_ab ((pattern->n_stops + 2), sizeof (cairo_ps_color_stop_t));
|
||||
if (allstops == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
stops = &allstops[1];
|
||||
n_stops = pattern->n_stops;
|
||||
|
@ -2531,6 +2633,9 @@ _cairo_ps_surface_emit_linear_pattern (cairo_ps_surface_t *surface,
|
|||
cairo_status_t status;
|
||||
cairo_matrix_t inverse = pattern->base.base.matrix;
|
||||
|
||||
if (pattern->base.n_stops == 0)
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
extend = cairo_pattern_get_extend (&pattern->base.base);
|
||||
|
||||
status = cairo_matrix_invert (&inverse);
|
||||
|
@ -2586,6 +2691,9 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
|
|||
cairo_status_t status;
|
||||
cairo_matrix_t inverse = pattern->base.base.matrix;
|
||||
|
||||
if (pattern->base.n_stops == 0)
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
extend = cairo_pattern_get_extend (&pattern->base.base);
|
||||
|
||||
status = cairo_matrix_invert (&inverse);
|
||||
|
@ -2658,11 +2766,17 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
|
|||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
_cairo_ps_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern);
|
||||
status = _cairo_ps_surface_emit_linear_pattern (surface,
|
||||
(cairo_linear_pattern_t *) pattern);
|
||||
if (status)
|
||||
return status;
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
_cairo_ps_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
|
||||
status = _cairo_ps_surface_emit_radial_pattern (surface,
|
||||
(cairo_radial_pattern_t *) pattern);
|
||||
if (status)
|
||||
return status;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2777,6 +2891,9 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
_cairo_rectangle_intersect (&extents, &pattern_extents);
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -2920,13 +3037,24 @@ _cairo_ps_surface_stroke (void *abstract_surface,
|
|||
}
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, op);
|
||||
if (status)
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (status) {
|
||||
if (dash != style->dash)
|
||||
free (dash);
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"gsave\n");
|
||||
status = _cairo_ps_surface_emit_path (surface, stream, path,
|
||||
style->line_cap);
|
||||
if (status) {
|
||||
if (dash != style->dash)
|
||||
free (dash);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch to user space to set line parameters
|
||||
|
@ -2963,7 +3091,8 @@ _cairo_ps_surface_stroke (void *abstract_surface,
|
|||
"stroke\n");
|
||||
_cairo_output_stream_printf (stream,
|
||||
"grestore\n");
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -2991,6 +3120,9 @@ _cairo_ps_surface_fill (void *abstract_surface,
|
|||
#endif
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -3060,6 +3192,9 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
num_glyphs_unsigned = num_glyphs;
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -3073,6 +3208,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
&subset_glyph);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
||||
glyph_ids[i].subset_id = subset_glyph.subset_id;
|
||||
glyph_ids[i].glyph_id = subset_glyph.subset_glyph_index;
|
||||
}
|
||||
|
@ -3149,7 +3285,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
} else {
|
||||
for (j = i; j < last+1; j++) {
|
||||
if (j == num_glyphs_unsigned - 1)
|
||||
_cairo_output_stream_printf (word_wrap, "0 ");
|
||||
_cairo_output_stream_printf (word_wrap, "0 0 ");
|
||||
else
|
||||
_cairo_output_stream_printf (word_wrap,
|
||||
"%f %f ",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2006, 2007 Mozilla Corporation
|
||||
* Copyright <EFBFBD> 2006, 2007 Mozilla Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
|
@ -57,6 +57,8 @@
|
|||
#define ND(_x) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define IS_EMPTY(s) ((s)->extents.width == 0 || (s)->extents.height == 0)
|
||||
|
||||
/* This method is private, but it exists. Its params are are exposed
|
||||
* as args to the NS* method, but not as CG.
|
||||
*/
|
||||
|
@ -84,7 +86,7 @@ CG_EXTERN CGSize CGContextGetPatternPhase (CGContextRef);
|
|||
|
||||
/* We need to work with the 10.3 SDK as well (and 10.3 machines; luckily, 10.3.9
|
||||
* has all the stuff we care about, just some of it isn't exported in the SDK.
|
||||
*/
|
||||
*/
|
||||
#ifndef kCGBitmapByteOrder32Host
|
||||
#define USE_10_3_WORKAROUNDS
|
||||
#define kCGBitmapAlphaInfoMask 0x1F
|
||||
|
@ -101,6 +103,9 @@ CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
|
|||
/* missing in 10.3.9 */
|
||||
extern void CGContextClipToMask (CGContextRef, CGRect, CGImageRef) __attribute__((weak_import));
|
||||
|
||||
/* 10.5-only optimization */
|
||||
extern void CGContextDrawTiledImage (CGContextRef, CGRect, CGImageRef) __attribute__((weak_import));
|
||||
|
||||
/*
|
||||
* Utility functions
|
||||
*/
|
||||
|
@ -108,6 +113,12 @@ extern void CGContextClipToMask (CGContextRef, CGRect, CGImageRef) __attribute__
|
|||
static void quartz_surface_to_png (cairo_quartz_surface_t *nq, char *dest);
|
||||
static void quartz_image_to_png (CGImageRef, char *dest);
|
||||
|
||||
static cairo_quartz_surface_t *
|
||||
_cairo_quartz_surface_create_internal (CGContextRef cgContext,
|
||||
cairo_content_t content,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
|
||||
/* CoreGraphics limitation with flipped CTM surfaces: height must be less than signed 16-bit max */
|
||||
|
||||
#define CG_MAX_HEIGHT SHRT_MAX
|
||||
|
@ -160,7 +171,7 @@ _cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point)
|
|||
quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
|
||||
double x = _cairo_fixed_to_double (point->x);
|
||||
double y = _cairo_fixed_to_double (point->y);
|
||||
|
||||
|
||||
if (stroke->ctm_inverse)
|
||||
cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
|
||||
|
||||
|
@ -367,94 +378,6 @@ CreateGradientFunction (cairo_gradient_pattern_t *gpat)
|
|||
&callbacks);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat,
|
||||
CGShadingRef *shading)
|
||||
{
|
||||
cairo_matrix_t mat;
|
||||
double x0, y0;
|
||||
|
||||
if (abspat->type != CAIRO_PATTERN_TYPE_LINEAR &&
|
||||
abspat->type != CAIRO_PATTERN_TYPE_RADIAL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* bandaid for mozilla bug 379321, also visible in the
|
||||
* linear-gradient-reflect test.
|
||||
*/
|
||||
if (abspat->extend == CAIRO_EXTEND_REFLECT ||
|
||||
abspat->extend == CAIRO_EXTEND_REPEAT)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* We can only do this if we have an identity pattern matrix;
|
||||
* otherwise fall back through to the generic pattern case.
|
||||
* XXXperf we could optimize this by creating a pattern with the shading;
|
||||
* but we'd need to know the extents to do that.
|
||||
* ... but we don't care; we can use the surface extents for it
|
||||
* XXXtodo - implement gradients with non-identity pattern matrices
|
||||
*/
|
||||
cairo_pattern_get_matrix (abspat, &mat);
|
||||
if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
x0 = mat.x0;
|
||||
y0 = mat.y0;
|
||||
|
||||
if (abspat->type == CAIRO_PATTERN_TYPE_LINEAR) {
|
||||
cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t*) abspat;
|
||||
CGPoint start, end;
|
||||
CGFunctionRef gradFunc;
|
||||
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
|
||||
bool extend = abspat->extend == CAIRO_EXTEND_PAD;
|
||||
|
||||
start = CGPointMake (_cairo_fixed_to_double (lpat->p1.x) - x0,
|
||||
_cairo_fixed_to_double (lpat->p1.y) - y0);
|
||||
end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x) - x0,
|
||||
_cairo_fixed_to_double (lpat->p2.y) - y0);
|
||||
|
||||
cairo_pattern_reference (abspat);
|
||||
gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat);
|
||||
*shading = CGShadingCreateAxial (rgb,
|
||||
start, end,
|
||||
gradFunc,
|
||||
extend, extend);
|
||||
CGColorSpaceRelease(rgb);
|
||||
CGFunctionRelease(gradFunc);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (abspat->type == CAIRO_PATTERN_TYPE_RADIAL) {
|
||||
cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t*) abspat;
|
||||
CGPoint start, end;
|
||||
CGFunctionRef gradFunc;
|
||||
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
|
||||
bool extend = abspat->extend == CAIRO_EXTEND_PAD;
|
||||
|
||||
start = CGPointMake (_cairo_fixed_to_double (rpat->c1.x) - x0,
|
||||
_cairo_fixed_to_double (rpat->c1.y) - y0);
|
||||
end = CGPointMake (_cairo_fixed_to_double (rpat->c2.x) - x0,
|
||||
_cairo_fixed_to_double (rpat->c2.y) - y0);
|
||||
|
||||
cairo_pattern_reference (abspat);
|
||||
gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
|
||||
*shading = CGShadingCreateRadial (rgb,
|
||||
start,
|
||||
_cairo_fixed_to_double (rpat->r1),
|
||||
end,
|
||||
_cairo_fixed_to_double (rpat->r2),
|
||||
gradFunc,
|
||||
extend, extend);
|
||||
CGColorSpaceRelease(rgb);
|
||||
CGFunctionRelease(gradFunc);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Shouldn't be reached */
|
||||
ASSERT_NOT_REACHED;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* generic cairo surface -> cairo_quartz_surface_t function */
|
||||
static cairo_int_status_t
|
||||
_cairo_quartz_surface_to_quartz (cairo_surface_t *target,
|
||||
|
@ -690,9 +613,123 @@ typedef enum {
|
|||
DO_SHADING,
|
||||
DO_PATTERN,
|
||||
DO_IMAGE,
|
||||
DO_UNSUPPORTED
|
||||
DO_UNSUPPORTED,
|
||||
DO_NOTHING,
|
||||
DO_TILED_IMAGE
|
||||
} cairo_quartz_action_t;
|
||||
|
||||
static cairo_quartz_action_t
|
||||
_cairo_quartz_setup_linear_source (cairo_quartz_surface_t *surface,
|
||||
cairo_linear_pattern_t *lpat)
|
||||
{
|
||||
cairo_pattern_t *abspat = (cairo_pattern_t *) lpat;
|
||||
cairo_matrix_t mat;
|
||||
double x0, y0;
|
||||
CGPoint start, end;
|
||||
CGFunctionRef gradFunc;
|
||||
CGColorSpaceRef rgb;
|
||||
bool extend = abspat->extend == CAIRO_EXTEND_PAD;
|
||||
|
||||
/* bandaid for mozilla bug 379321, also visible in the
|
||||
* linear-gradient-reflect test.
|
||||
*/
|
||||
if (abspat->extend == CAIRO_EXTEND_REFLECT ||
|
||||
abspat->extend == CAIRO_EXTEND_REPEAT)
|
||||
return DO_UNSUPPORTED;
|
||||
|
||||
/* We can only do this if we have an identity pattern matrix;
|
||||
* otherwise fall back through to the generic pattern case.
|
||||
* XXXperf we could optimize this by creating a pattern with the shading;
|
||||
* but we'd need to know the extents to do that.
|
||||
* ... but we don't care; we can use the surface extents for it
|
||||
* XXXtodo - implement gradients with non-identity pattern matrices
|
||||
*/
|
||||
cairo_pattern_get_matrix (abspat, &mat);
|
||||
if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0)
|
||||
return DO_UNSUPPORTED;
|
||||
|
||||
if (!lpat->base.n_stops) {
|
||||
CGContextSetRGBStrokeColor (surface->cgContext, 0., 0., 0., 0.);
|
||||
CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.);
|
||||
return DO_SOLID;
|
||||
}
|
||||
|
||||
x0 = mat.x0;
|
||||
y0 = mat.y0;
|
||||
rgb = CGColorSpaceCreateDeviceRGB();
|
||||
|
||||
start = CGPointMake (_cairo_fixed_to_double (lpat->p1.x) - x0,
|
||||
_cairo_fixed_to_double (lpat->p1.y) - y0);
|
||||
end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x) - x0,
|
||||
_cairo_fixed_to_double (lpat->p2.y) - y0);
|
||||
|
||||
cairo_pattern_reference (abspat);
|
||||
gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat);
|
||||
surface->sourceShading = CGShadingCreateAxial (rgb,
|
||||
start, end,
|
||||
gradFunc,
|
||||
extend, extend);
|
||||
CGColorSpaceRelease(rgb);
|
||||
CGFunctionRelease(gradFunc);
|
||||
|
||||
return DO_SHADING;
|
||||
}
|
||||
|
||||
static cairo_quartz_action_t
|
||||
_cairo_quartz_setup_radial_source (cairo_quartz_surface_t *surface,
|
||||
cairo_radial_pattern_t *rpat)
|
||||
{
|
||||
cairo_pattern_t *abspat = (cairo_pattern_t *)rpat;
|
||||
cairo_matrix_t mat;
|
||||
double x0, y0;
|
||||
CGPoint start, end;
|
||||
CGFunctionRef gradFunc;
|
||||
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
|
||||
bool extend = abspat->extend == CAIRO_EXTEND_PAD;
|
||||
|
||||
/* bandaid for mozilla bug 379321, also visible in the
|
||||
* linear-gradient-reflect test.
|
||||
*/
|
||||
if (abspat->extend == CAIRO_EXTEND_REFLECT ||
|
||||
abspat->extend == CAIRO_EXTEND_REPEAT)
|
||||
return DO_UNSUPPORTED;
|
||||
|
||||
/* XXXtodo - implement gradients with non-identity pattern matrices
|
||||
*/
|
||||
cairo_pattern_get_matrix (abspat, &mat);
|
||||
if (mat.xx != 1.0 || mat.yy != 1.0 || mat.xy != 0.0 || mat.yx != 0.0)
|
||||
return DO_UNSUPPORTED;
|
||||
|
||||
if (!rpat->base.n_stops) {
|
||||
CGContextSetRGBStrokeColor (surface->cgContext, 0., 0., 0., 0.);
|
||||
CGContextSetRGBFillColor (surface->cgContext, 0., 0., 0., 0.);
|
||||
return DO_SOLID;
|
||||
}
|
||||
|
||||
x0 = mat.x0;
|
||||
y0 = mat.y0;
|
||||
rgb = CGColorSpaceCreateDeviceRGB();
|
||||
|
||||
start = CGPointMake (_cairo_fixed_to_double (rpat->c1.x) - x0,
|
||||
_cairo_fixed_to_double (rpat->c1.y) - y0);
|
||||
end = CGPointMake (_cairo_fixed_to_double (rpat->c2.x) - x0,
|
||||
_cairo_fixed_to_double (rpat->c2.y) - y0);
|
||||
|
||||
cairo_pattern_reference (abspat);
|
||||
gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
|
||||
surface->sourceShading = CGShadingCreateRadial (rgb,
|
||||
start,
|
||||
_cairo_fixed_to_double (rpat->r1),
|
||||
end,
|
||||
_cairo_fixed_to_double (rpat->r2),
|
||||
gradFunc,
|
||||
extend, extend);
|
||||
CGColorSpaceRelease(rgb);
|
||||
CGFunctionRelease(gradFunc);
|
||||
|
||||
return DO_SHADING;
|
||||
}
|
||||
|
||||
static cairo_quartz_action_t
|
||||
_cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
|
||||
cairo_pattern_t *source)
|
||||
|
@ -714,21 +751,17 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
|
|||
solid->color.alpha);
|
||||
|
||||
return DO_SOLID;
|
||||
} else if (source->type == CAIRO_PATTERN_TYPE_LINEAR ||
|
||||
source->type == CAIRO_PATTERN_TYPE_RADIAL)
|
||||
} else if (source->type == CAIRO_PATTERN_TYPE_LINEAR)
|
||||
{
|
||||
CGShadingRef shading = NULL;
|
||||
cairo_int_status_t status;
|
||||
cairo_linear_pattern_t *lpat = (cairo_linear_pattern_t *)source;
|
||||
return _cairo_quartz_setup_linear_source (surface, lpat);
|
||||
|
||||
status = _cairo_quartz_cairo_gradient_pattern_to_quartz (source, &shading);
|
||||
if (status)
|
||||
return DO_UNSUPPORTED;
|
||||
} else if (source->type == CAIRO_PATTERN_TYPE_RADIAL) {
|
||||
cairo_radial_pattern_t *rpat = (cairo_radial_pattern_t *)source;
|
||||
return _cairo_quartz_setup_radial_source (surface, rpat);
|
||||
|
||||
surface->sourceShading = shading;
|
||||
|
||||
return DO_SHADING;
|
||||
} else if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
source->extend == CAIRO_EXTEND_NONE)
|
||||
(source->extend == CAIRO_EXTEND_NONE || (CGContextDrawTiledImage && source->extend == CAIRO_EXTEND_REPEAT)))
|
||||
{
|
||||
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source;
|
||||
cairo_surface_t *pat_surf = spat->surface;
|
||||
|
@ -742,6 +775,11 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
|
|||
if (status)
|
||||
return DO_UNSUPPORTED;
|
||||
|
||||
surface->sourceImageSurface = (cairo_surface_t *)quartz_surf;
|
||||
|
||||
if (IS_EMPTY(quartz_surf))
|
||||
return DO_NOTHING;
|
||||
|
||||
img = CGBitmapContextCreateImage (quartz_surf->cgContext);
|
||||
if (!img)
|
||||
return DO_UNSUPPORTED;
|
||||
|
@ -757,9 +795,10 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
|
|||
|
||||
surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height);
|
||||
|
||||
surface->sourceImageSurface = (cairo_surface_t *)quartz_surf;
|
||||
|
||||
return DO_IMAGE;
|
||||
if (source->extend == CAIRO_EXTEND_NONE)
|
||||
return DO_IMAGE;
|
||||
else
|
||||
return DO_TILED_IMAGE;
|
||||
} else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
float patternAlpha = 1.0f;
|
||||
CGColorSpaceRef patternSpace;
|
||||
|
@ -845,6 +884,13 @@ _cairo_quartz_get_image (cairo_quartz_surface_t *surface,
|
|||
unsigned char *imageData;
|
||||
cairo_image_surface_t *isurf;
|
||||
|
||||
if (IS_EMPTY(surface)) {
|
||||
*image_out = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
|
||||
if (data_out)
|
||||
*data_out = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (CGBitmapContextGetBitsPerPixel(surface->cgContext) != 0) {
|
||||
unsigned int stride;
|
||||
unsigned int bitinfo;
|
||||
|
@ -927,6 +973,9 @@ _cairo_quartz_surface_finish (void *abstract_surface)
|
|||
|
||||
ND((stderr, "_cairo_quartz_surface_finish[%p] cgc: %p\n", surface, surface->cgContext));
|
||||
|
||||
if (IS_EMPTY(surface))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* Restore our saved gstate that we use to reset clipping */
|
||||
CGContextRestoreGState (surface->cgContext);
|
||||
|
||||
|
@ -1006,6 +1055,11 @@ _cairo_quartz_surface_release_dest_image (void *abstract_surface,
|
|||
|
||||
//ND((stderr, "%p _cairo_quartz_surface_release_dest_image\n", surface));
|
||||
|
||||
if (IS_EMPTY(surface)) {
|
||||
cairo_surface_destroy ((cairo_surface_t*) image);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CGBitmapContextGetData (surface->cgContext)) {
|
||||
CGDataProviderRef dataProvider;
|
||||
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
|
||||
|
@ -1059,7 +1113,7 @@ _cairo_quartz_surface_create_similar (void *abstract_surface,
|
|||
format = CAIRO_FORMAT_A8;
|
||||
else
|
||||
return NULL;
|
||||
|
||||
|
||||
// verify width and height of surface
|
||||
if (!verify_surface_size(width, height)) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
@ -1080,7 +1134,8 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
|
|||
{
|
||||
cairo_quartz_surface_t *new_surface = NULL;
|
||||
cairo_format_t new_format;
|
||||
|
||||
CGImageRef quartz_image = NULL;
|
||||
|
||||
*clone_out = NULL;
|
||||
|
||||
// verify width and height of surface
|
||||
|
@ -1088,10 +1143,14 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
CGImageRef quartz_image = NULL;
|
||||
|
||||
if (cairo_surface_get_type(src) == CAIRO_SURFACE_TYPE_QUARTZ) {
|
||||
cairo_quartz_surface_t *qsurf = (cairo_quartz_surface_t *) src;
|
||||
|
||||
if (IS_EMPTY(qsurf)) {
|
||||
*clone_out = (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, qsurf->extents.width, qsurf->extents.height);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
quartz_image = CGBitmapContextCreateImage (qsurf->cgContext);
|
||||
new_format = CAIRO_FORMAT_ARGB32; /* XXX bogus; recover a real format from the image */
|
||||
} else if (_cairo_surface_is_image (src)) {
|
||||
|
@ -1101,6 +1160,11 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
|
|||
CGBitmapInfo bitinfo;
|
||||
int bitsPerComponent, bitsPerPixel;
|
||||
|
||||
if (isurf->width == 0 || isurf->height == 0) {
|
||||
*clone_out = (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, CAIRO_CONTENT_COLOR_ALPHA, isurf->width, isurf->height);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (isurf->format == CAIRO_FORMAT_ARGB32) {
|
||||
cgColorspace = CGColorSpaceCreateDeviceRGB();
|
||||
bitinfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
|
||||
|
@ -1193,6 +1257,9 @@ _cairo_quartz_surface_paint (void *abstract_surface,
|
|||
|
||||
ND((stderr, "%p _cairo_quartz_surface_paint op %d source->type %d\n", surface, op, source->type));
|
||||
|
||||
if (IS_EMPTY(surface))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -1207,20 +1274,33 @@ _cairo_quartz_surface_paint (void *abstract_surface,
|
|||
surface->extents.height));
|
||||
} else if (action == DO_SHADING) {
|
||||
CGContextDrawShading (surface->cgContext, surface->sourceShading);
|
||||
} else if (action == DO_IMAGE) {
|
||||
} else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
(cairo_surface_pattern_t *) source;
|
||||
cairo_surface_t *pat_surf = surface_pattern->surface;
|
||||
|
||||
CGContextSaveGState (surface->cgContext);
|
||||
|
||||
if (action == DO_IMAGE && op != CAIRO_OPERATOR_OVER) {
|
||||
CGContextSetRGBFillColor (surface->cgContext, 0.0, 0.0, 0.0, 0.0);
|
||||
CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
|
||||
surface->extents.y,
|
||||
surface->extents.width,
|
||||
surface->extents.height));
|
||||
}
|
||||
|
||||
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
|
||||
if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
|
||||
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
|
||||
CGContextScaleCTM (surface->cgContext, 1, -1);
|
||||
}
|
||||
|
||||
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
if (action == DO_IMAGE)
|
||||
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
else
|
||||
CGContextDrawTiledImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
CGContextRestoreGState (surface->cgContext);
|
||||
} else {
|
||||
} else if (action != DO_NOTHING) {
|
||||
rv = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -1246,6 +1326,9 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
|
||||
ND((stderr, "%p _cairo_quartz_surface_fill op %d source->type %d\n", surface, op, source->type));
|
||||
|
||||
if (IS_EMPTY(surface))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -1255,10 +1338,6 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op));
|
||||
|
||||
action = _cairo_quartz_setup_source (surface, source);
|
||||
if (action == DO_UNSUPPORTED) {
|
||||
CGContextRestoreGState (surface->cgContext);
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
CGContextBeginPath (surface->cgContext);
|
||||
|
||||
|
@ -1283,7 +1362,7 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
CGContextEOClip (surface->cgContext);
|
||||
|
||||
CGContextDrawShading (surface->cgContext, surface->sourceShading);
|
||||
} else if (action == DO_IMAGE) {
|
||||
} else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
(cairo_surface_pattern_t *) source;
|
||||
cairo_surface_t *pat_surf = surface_pattern->surface;
|
||||
|
@ -1291,14 +1370,26 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
CGContextClip (surface->cgContext);
|
||||
else
|
||||
CGContextEOClip (surface->cgContext);
|
||||
|
||||
if (action == DO_IMAGE && op != CAIRO_OPERATOR_OVER) {
|
||||
CGContextSetRGBFillColor (surface->cgContext, 0.0, 0.0, 0.0, 0.0);
|
||||
CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
|
||||
surface->extents.y,
|
||||
surface->extents.width,
|
||||
surface->extents.height));
|
||||
}
|
||||
|
||||
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
|
||||
if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
|
||||
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
|
||||
CGContextScaleCTM (surface->cgContext, 1, -1);
|
||||
}
|
||||
|
||||
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
} else {
|
||||
if (action == DO_IMAGE)
|
||||
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
else
|
||||
CGContextDrawTiledImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
} else if (action != DO_NOTHING) {
|
||||
rv = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -1330,6 +1421,9 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
|
|||
|
||||
ND((stderr, "%p _cairo_quartz_surface_stroke op %d source->type %d\n", surface, op, source->type));
|
||||
|
||||
if (IS_EMPTY(surface))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -1361,7 +1455,7 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
|
|||
|
||||
for (k = 0; k < max_dashes; k++)
|
||||
fdash[k] = (float) style->dash[k % style->num_dashes];
|
||||
|
||||
|
||||
CGContextSetLineDash (surface->cgContext, style->dash_offset, fdash, max_dashes);
|
||||
if (fdash != sdash)
|
||||
free (fdash);
|
||||
|
@ -1370,10 +1464,6 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
|
|||
CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op));
|
||||
|
||||
action = _cairo_quartz_setup_source (surface, source);
|
||||
if (action == DO_UNSUPPORTED) {
|
||||
CGContextRestoreGState (surface->cgContext);
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
CGContextBeginPath (surface->cgContext);
|
||||
|
||||
|
@ -1385,23 +1475,34 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
|
|||
|
||||
if (action == DO_SOLID || action == DO_PATTERN) {
|
||||
CGContextStrokePath (surface->cgContext);
|
||||
} else if (action == DO_IMAGE) {
|
||||
} else if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
|
||||
CGContextReplacePathWithStrokedPath (surface->cgContext);
|
||||
CGContextClip (surface->cgContext);
|
||||
|
||||
if (action == DO_IMAGE && op != CAIRO_OPERATOR_OVER) {
|
||||
CGContextSetRGBFillColor (surface->cgContext, 0.0, 0.0, 0.0, 0.0);
|
||||
CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
|
||||
surface->extents.y,
|
||||
surface->extents.width,
|
||||
surface->extents.height));
|
||||
}
|
||||
|
||||
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
|
||||
if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
|
||||
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
|
||||
CGContextScaleCTM (surface->cgContext, 1, -1);
|
||||
}
|
||||
|
||||
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
if (action == DO_IMAGE)
|
||||
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
else
|
||||
CGContextDrawTiledImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
} else if (action == DO_SHADING) {
|
||||
CGContextReplacePathWithStrokedPath (surface->cgContext);
|
||||
CGContextClip (surface->cgContext);
|
||||
|
||||
CGContextDrawShading (surface->cgContext, surface->sourceShading);
|
||||
} else {
|
||||
} else if (action != DO_NOTHING) {
|
||||
rv = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -1437,6 +1538,9 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
float xprev, yprev;
|
||||
int i;
|
||||
|
||||
if (IS_EMPTY(surface))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (num_glyphs <= 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -1451,16 +1555,17 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
action = _cairo_quartz_setup_source (surface, source);
|
||||
if (action == DO_SOLID || action == DO_PATTERN) {
|
||||
CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
|
||||
} else if (action == DO_IMAGE || action == DO_SHADING) {
|
||||
} else if (action == DO_IMAGE || action == DO_TILED_IMAGE || action == DO_SHADING) {
|
||||
CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
|
||||
} else {
|
||||
/* Unsupported */
|
||||
rv = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (action != DO_NOTHING)
|
||||
rv = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto BAIL;
|
||||
}
|
||||
|
||||
CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op));
|
||||
|
||||
/* this doesn't addref */
|
||||
CGFontRef cgfref = _cairo_atsui_scaled_font_get_cg_font_ref (scaled_font);
|
||||
CGContextSetFont (surface->cgContext, cgfref);
|
||||
|
||||
|
@ -1470,9 +1575,9 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
* text matrix?
|
||||
*/
|
||||
//ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y));
|
||||
cairoTextTransform = CGAffineTransformMake (scaled_font->font_matrix.xx,
|
||||
cairoTextTransform = CGAffineTransformMake (scaled_font->font_matrix.xx,
|
||||
scaled_font->font_matrix.yx,
|
||||
scaled_font->font_matrix.xy,
|
||||
scaled_font->font_matrix.xy,
|
||||
scaled_font->font_matrix.yy,
|
||||
0., 0.);
|
||||
|
||||
|
@ -1532,14 +1637,25 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
cg_advances,
|
||||
num_glyphs);
|
||||
|
||||
if (action == DO_IMAGE) {
|
||||
if (action == DO_IMAGE || action == DO_TILED_IMAGE) {
|
||||
if (action == DO_IMAGE && op != CAIRO_OPERATOR_OVER) {
|
||||
CGContextSetRGBFillColor (surface->cgContext, 0.0, 0.0, 0.0, 0.0);
|
||||
CGContextFillRect (surface->cgContext, CGRectMake(surface->extents.x,
|
||||
surface->extents.y,
|
||||
surface->extents.width,
|
||||
surface->extents.height));
|
||||
}
|
||||
|
||||
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
|
||||
if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
|
||||
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
|
||||
CGContextScaleCTM (surface->cgContext, 1, -1);
|
||||
}
|
||||
|
||||
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
if (action == DO_IMAGE)
|
||||
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
else
|
||||
CGContextDrawTiledImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
|
||||
} else if (action == DO_SHADING) {
|
||||
CGContextDrawShading (surface->cgContext, surface->sourceShading);
|
||||
}
|
||||
|
@ -1554,7 +1670,7 @@ BAIL:
|
|||
}
|
||||
|
||||
_cairo_quartz_teardown_source (surface, source);
|
||||
|
||||
|
||||
CGContextRestoreGState (surface->cgContext);
|
||||
|
||||
return rv;
|
||||
|
@ -1582,6 +1698,10 @@ _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
// everything would be masked out, so do nothing
|
||||
if (IS_EMPTY(quartz_surf))
|
||||
goto BAIL;
|
||||
|
||||
img = CGBitmapContextCreateImage (quartz_surf->cgContext);
|
||||
if (!img) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
@ -1611,6 +1731,9 @@ _cairo_quartz_surface_mask (void *abstract_surface,
|
|||
|
||||
ND((stderr, "%p _cairo_quartz_surface_mask op %d source->type %d mask->type %d\n", surface, op, source->type, mask->type));
|
||||
|
||||
if (IS_EMPTY(surface))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||
/* This is easy; we just need to paint with the alpha. */
|
||||
cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
|
||||
|
@ -1655,6 +1778,9 @@ _cairo_quartz_surface_intersect_clip_path (void *abstract_surface,
|
|||
|
||||
ND((stderr, "%p _cairo_quartz_surface_intersect_clip_path path: %p\n", surface, path));
|
||||
|
||||
if (IS_EMPTY(surface))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (path == NULL) {
|
||||
/* If we're being asked to reset the clip, we can only do it
|
||||
* by restoring the gstate to our previous saved one, and
|
||||
|
@ -1671,7 +1797,7 @@ _cairo_quartz_surface_intersect_clip_path (void *abstract_surface,
|
|||
stroke.ctm_inverse = NULL;
|
||||
|
||||
/* path must not be empty. */
|
||||
CGContextMoveToPoint (surface->cgContext, 0, 0);
|
||||
CGContextMoveToPoint (surface->cgContext, 0, 0);
|
||||
status = _cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
|
||||
if (status)
|
||||
return status;
|
||||
|
@ -1719,7 +1845,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
|
|||
_cairo_quartz_surface_fill,
|
||||
#if CAIRO_HAS_ATSUI_FONT
|
||||
_cairo_quartz_surface_show_glyphs,
|
||||
#else
|
||||
#else
|
||||
NULL, /* surface_show_glyphs */
|
||||
#endif /* CAIRO_HAS_ATSUI_FONT */
|
||||
|
||||
|
@ -1729,7 +1855,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
|
|||
NULL /* fill_stroke */
|
||||
};
|
||||
|
||||
static cairo_quartz_surface_t *
|
||||
cairo_quartz_surface_t *
|
||||
_cairo_quartz_surface_create_internal (CGContextRef cgContext,
|
||||
cairo_content_t content,
|
||||
unsigned int width,
|
||||
|
@ -1754,6 +1880,13 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
|
|||
surface->extents.width = width;
|
||||
surface->extents.height = height;
|
||||
|
||||
if (IS_EMPTY(surface)) {
|
||||
surface->cgContext = NULL;
|
||||
surface->cgContextBaseCTM = CGAffineTransformIdentity;
|
||||
surface->imageData = NULL;
|
||||
return surface;
|
||||
}
|
||||
|
||||
/* Save so we can always get back to a known-good CGContext -- this is
|
||||
* required for proper behaviour of intersect_clip_path(NULL)
|
||||
*/
|
||||
|
@ -1766,7 +1899,7 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
|
|||
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* cairo_quartz_surface_create_for_cg_context
|
||||
* @cgContext: the existing CGContext for which to create the surface
|
||||
|
@ -1781,7 +1914,7 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
|
|||
* this function is called:
|
||||
*
|
||||
* <informalexample><programlisting>
|
||||
* GContextTranslateCTM (cgContext, 0.0, height);
|
||||
* CGContextTranslateCTM (cgContext, 0.0, height);
|
||||
* CGContextScaleCTM (cgContext, 1.0, -1.0);
|
||||
* </programlisting></informalexample>
|
||||
*
|
||||
|
@ -1806,7 +1939,7 @@ cairo_quartz_surface_create_for_cg_context (CGContextRef cgContext,
|
|||
CGContextRetain (cgContext);
|
||||
|
||||
surf = _cairo_quartz_surface_create_internal (cgContext, CAIRO_CONTENT_COLOR_ALPHA,
|
||||
width, height);
|
||||
width, height);
|
||||
if (!surf) {
|
||||
CGContextRelease (cgContext);
|
||||
// create_internal will have set an error
|
||||
|
@ -1850,6 +1983,11 @@ cairo_quartz_surface_create (cairo_format_t format,
|
|||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
return (cairo_surface_t*) _cairo_quartz_surface_create_internal (NULL, _cairo_content_from_format (format),
|
||||
width, height);
|
||||
}
|
||||
|
||||
if (format == CAIRO_FORMAT_ARGB32) {
|
||||
cgColorspace = CGColorSpaceCreateDeviceRGB();
|
||||
stride = width * 4;
|
||||
|
@ -1886,6 +2024,8 @@ cairo_quartz_surface_create (cairo_format_t format,
|
|||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
/* zero the memory to match the image surface behaviour */
|
||||
memset (imageData, 0, height * stride);
|
||||
|
||||
cgc = CGBitmapContextCreate (imageData,
|
||||
width,
|
||||
|
@ -1907,7 +2047,7 @@ cairo_quartz_surface_create (cairo_format_t format,
|
|||
CGContextScaleCTM (cgc, 1.0, -1.0);
|
||||
|
||||
surf = _cairo_quartz_surface_create_internal (cgc, _cairo_content_from_format (format),
|
||||
width, height);
|
||||
width, height);
|
||||
if (!surf) {
|
||||
CGContextRelease (cgc);
|
||||
free (imageData);
|
||||
|
|
|
@ -52,14 +52,12 @@ _cairo_region_init_rect (cairo_region_t *region,
|
|||
rect->width, rect->height);
|
||||
}
|
||||
|
||||
#define STACK_BOXES_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_box16_t)))
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_region_init_boxes (cairo_region_t *region,
|
||||
cairo_box_int_t *boxes,
|
||||
int count)
|
||||
{
|
||||
pixman_box16_t stack_pboxes[STACK_BOXES_LEN];
|
||||
pixman_box16_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box16_t)];
|
||||
pixman_box16_t *pboxes = stack_pboxes;
|
||||
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
int i;
|
||||
|
|
|
@ -493,10 +493,11 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
|
|||
|
||||
_cairo_hash_table_foreach (subsets->unscaled_sub_fonts, _cairo_sub_font_pluck, subsets->unscaled_sub_fonts);
|
||||
_cairo_hash_table_destroy (subsets->unscaled_sub_fonts);
|
||||
|
||||
free (subsets);
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long scaled_font_glyph_index,
|
||||
|
@ -547,7 +548,9 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
|||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
if (status == 0 && subsets->type != CAIRO_SUBSETS_SCALED) {
|
||||
if (status == CAIRO_STATUS_SUCCESS &&
|
||||
subsets->type != CAIRO_SUBSETS_SCALED)
|
||||
{
|
||||
/* Path available. Add to unscaled subset. */
|
||||
key.is_scaled = FALSE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
|
@ -722,20 +725,16 @@ _cairo_string_init_key (cairo_string_entry_t *key, char *s)
|
|||
key->string = s;
|
||||
}
|
||||
|
||||
static cairo_string_entry_t *
|
||||
create_string_entry (char *s)
|
||||
static cairo_status_t
|
||||
create_string_entry (char *s, cairo_string_entry_t **entry)
|
||||
{
|
||||
cairo_string_entry_t *entry;
|
||||
*entry = malloc (sizeof (cairo_string_entry_t));
|
||||
if (*entry == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
entry = malloc (sizeof (cairo_string_entry_t));
|
||||
if (entry == NULL) {
|
||||
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
_cairo_string_init_key (*entry, s);
|
||||
|
||||
_cairo_string_init_key (entry, s);
|
||||
|
||||
return entry;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
|
@ -748,37 +747,42 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
|
|||
cairo_string_entry_t key, *entry;
|
||||
char buf[30];
|
||||
|
||||
if (subset->to_unicode == NULL) {
|
||||
if (subset->to_unicode == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (_cairo_truetype_create_glyph_to_unicode_map (subset) != CAIRO_STATUS_SUCCESS) {
|
||||
status = _cairo_truetype_create_glyph_to_unicode_map (subset);
|
||||
if (status) {
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
backend = subset->scaled_font->backend;
|
||||
if (backend->map_glyphs_to_unicode == NULL) {
|
||||
if (backend->map_glyphs_to_unicode == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
backend->map_glyphs_to_unicode (subset->scaled_font, subset);
|
||||
}
|
||||
|
||||
subset->glyph_names = calloc (subset->num_glyphs, sizeof (char *));
|
||||
status = backend->map_glyphs_to_unicode (subset->scaled_font, subset);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
names = _cairo_hash_table_create (_cairo_string_equal);
|
||||
if (names == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto FAIL1;
|
||||
if (names == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
subset->glyph_names = calloc (subset->num_glyphs, sizeof (char *));
|
||||
if (subset->glyph_names == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto CLEANUP_HASH;
|
||||
}
|
||||
|
||||
subset->glyph_names[0] = strdup (".notdef");
|
||||
if (subset->glyph_names[0] == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto FAIL1;
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto CLEANUP_HASH;
|
||||
}
|
||||
|
||||
entry = create_string_entry (subset->glyph_names[0]);
|
||||
if (entry == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto FAIL2;
|
||||
}
|
||||
status = create_string_entry (subset->glyph_names[0], &entry);
|
||||
if (status)
|
||||
goto CLEANUP_HASH;
|
||||
|
||||
status = _cairo_hash_table_insert (names, &entry->base);
|
||||
if (status) {
|
||||
|
@ -786,7 +790,7 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
|
|||
goto CLEANUP_HASH;
|
||||
}
|
||||
|
||||
for (i = 0; i < subset->num_glyphs; i++) {
|
||||
for (i = 1; i < subset->num_glyphs; i++) {
|
||||
if (subset->to_unicode[i] <= 0xffff) {
|
||||
snprintf (buf, sizeof(buf), "uni%04X", (unsigned int)(subset->to_unicode[i]));
|
||||
_cairo_string_init_key (&key, buf);
|
||||
|
@ -800,15 +804,13 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
|
|||
|
||||
subset->glyph_names[i] = strdup (buf);
|
||||
if (subset->glyph_names[i] == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto CLEANUP_HASH;
|
||||
}
|
||||
|
||||
entry = create_string_entry (subset->glyph_names[i]);
|
||||
if (entry == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
status = create_string_entry (subset->glyph_names[i], &entry);
|
||||
if (status)
|
||||
goto CLEANUP_HASH;
|
||||
}
|
||||
|
||||
status = _cairo_hash_table_insert (names, &entry->base);
|
||||
if (status) {
|
||||
|
@ -816,30 +818,30 @@ _cairo_scaled_font_subset_create_glyph_names (cairo_scaled_font_subset_t *subset
|
|||
goto CLEANUP_HASH;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
CLEANUP_HASH:
|
||||
while (1) {
|
||||
entry = _cairo_hash_table_random_entry (names, NULL);
|
||||
if (entry == NULL)
|
||||
break;
|
||||
|
||||
_cairo_hash_table_remove (names, (cairo_hash_entry_t *) entry);
|
||||
free (entry);
|
||||
}
|
||||
_cairo_hash_table_destroy (names);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
FAIL2:
|
||||
for (i = 0; i < subset->num_glyphs; i++) {
|
||||
if (subset->glyph_names[i] != NULL)
|
||||
free (subset->glyph_names[i]);
|
||||
if (subset->glyph_names != NULL) {
|
||||
for (i = 0; i < subset->num_glyphs; i++) {
|
||||
if (subset->glyph_names[i] != NULL)
|
||||
free (subset->glyph_names[i]);
|
||||
}
|
||||
|
||||
free (subset->glyph_names);
|
||||
subset->glyph_names = NULL;
|
||||
}
|
||||
|
||||
FAIL1:
|
||||
free (subset->glyph_names);
|
||||
subset->glyph_names = NULL;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -608,6 +608,9 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
|||
if (! _cairo_matrix_is_invertible (font_matrix))
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
|
||||
if (! _cairo_matrix_is_invertible (ctm))
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
|
||||
font_map = _cairo_scaled_font_map_lock ();
|
||||
if (font_map == NULL)
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
|
@ -1170,7 +1173,9 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
{
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *mask = NULL;
|
||||
cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */
|
||||
cairo_surface_pattern_t mask_pattern;
|
||||
cairo_solid_pattern_t white_pattern;
|
||||
int i;
|
||||
|
||||
/* These operators aren't interpreted the same way by the backends;
|
||||
|
@ -1200,6 +1205,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
|
||||
|
||||
_cairo_cache_freeze (scaled_font->glyphs);
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
|
@ -1218,26 +1225,67 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
glyph_surface = scaled_glyph->surface;
|
||||
|
||||
/* Create the mask using the format from the first glyph */
|
||||
/* To start, create the mask using the format from the first
|
||||
* glyph. Later we'll deal with different formats. */
|
||||
if (mask == NULL) {
|
||||
mask = cairo_image_surface_create (glyph_surface->format,
|
||||
mask_format = glyph_surface->format;
|
||||
mask = cairo_image_surface_create (mask_format,
|
||||
width, height);
|
||||
if (mask->status) {
|
||||
status = mask->status;
|
||||
goto CLEANUP_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
status = _cairo_surface_fill_rectangle (mask,
|
||||
CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
0, 0,
|
||||
width, height);
|
||||
if (status)
|
||||
/* If we have glyphs of different formats, we "upgrade" the mask
|
||||
* to the wider of the formats. */
|
||||
if (glyph_surface->format != mask_format &&
|
||||
_cairo_format_width (mask_format) < _cairo_format_width (glyph_surface->format) )
|
||||
{
|
||||
cairo_surface_t *new_mask;
|
||||
cairo_surface_pattern_t mask_pattern;
|
||||
|
||||
switch (glyph_surface->format) {
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
case CAIRO_FORMAT_A8:
|
||||
case CAIRO_FORMAT_A1:
|
||||
mask_format = glyph_surface->format;
|
||||
break;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
mask_format = CAIRO_FORMAT_ARGB32;
|
||||
break;
|
||||
}
|
||||
|
||||
new_mask = cairo_image_surface_create (mask_format,
|
||||
width, height);
|
||||
if (new_mask->status) {
|
||||
status = new_mask->status;
|
||||
cairo_surface_destroy (new_mask);
|
||||
goto CLEANUP_MASK;
|
||||
if (glyph_surface->format == CAIRO_FORMAT_ARGB32)
|
||||
pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)->
|
||||
pixman_image, TRUE);
|
||||
}
|
||||
|
||||
_cairo_pattern_init_for_surface (&mask_pattern, mask);
|
||||
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
|
||||
&white_pattern.base,
|
||||
&mask_pattern.base,
|
||||
new_mask,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
width, height);
|
||||
|
||||
_cairo_pattern_fini (&mask_pattern.base);
|
||||
|
||||
if (status) {
|
||||
cairo_surface_destroy (new_mask);
|
||||
goto CLEANUP_MASK;
|
||||
}
|
||||
|
||||
cairo_surface_destroy (mask);
|
||||
mask = new_mask;
|
||||
}
|
||||
|
||||
/* round glyph locations to the nearest pixel */
|
||||
|
@ -1248,21 +1296,24 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
|
||||
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
|
||||
&white_pattern.base,
|
||||
&glyph_pattern.base,
|
||||
NULL,
|
||||
mask,
|
||||
0, 0,
|
||||
0, 0,
|
||||
x - dest_x,
|
||||
y - dest_y,
|
||||
x - dest_x, y - dest_y,
|
||||
glyph_surface->width,
|
||||
glyph_surface->height);
|
||||
|
||||
_cairo_pattern_fini (&glyph_pattern.base);
|
||||
|
||||
if (status)
|
||||
goto CLEANUP_MASK;
|
||||
}
|
||||
|
||||
if (mask_format == CAIRO_FORMAT_ARGB32)
|
||||
pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)->
|
||||
pixman_image, TRUE);
|
||||
_cairo_pattern_init_for_surface (&mask_pattern, mask);
|
||||
|
||||
status = _cairo_surface_composite (op, pattern, &mask_pattern.base,
|
||||
|
@ -1277,6 +1328,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
CLEANUP_MASK:
|
||||
_cairo_cache_thaw (scaled_font->glyphs);
|
||||
|
||||
_cairo_pattern_fini (&white_pattern.base);
|
||||
|
||||
if (mask != NULL)
|
||||
cairo_surface_destroy (mask);
|
||||
return _cairo_scaled_font_set_error (scaled_font, status);
|
||||
|
|
|
@ -1051,7 +1051,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
image->height);
|
||||
if (cairo_surface_status (snapshot)) {
|
||||
_cairo_surface_release_source_image (surface,
|
||||
image, &image_extra);
|
||||
image, image_extra);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
|
@ -1069,7 +1069,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
_cairo_surface_release_source_image (surface,
|
||||
image, &image_extra);
|
||||
image, image_extra);
|
||||
|
||||
if (status) {
|
||||
cairo_surface_destroy (snapshot);
|
||||
|
|
|
@ -86,7 +86,7 @@ DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
|
|||
static cairo_status_t
|
||||
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
|
||||
cairo_surface_t *destination,
|
||||
cairo_pattern_t *pattern_out);
|
||||
cairo_pattern_t **pattern_out);
|
||||
|
||||
/**
|
||||
* _cairo_surface_set_error:
|
||||
|
@ -931,7 +931,7 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface)
|
|||
* @surface as a source. _cairo_surface_release_source_image() must be called
|
||||
* when finished.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS if a an image was stored in @image_out.
|
||||
* Return value: %CAIRO_STATUS_SUCCESS if an image was stored in @image_out.
|
||||
* %CAIRO_INT_STATUS_UNSUPPORTED if an image cannot be retrieved for the specified
|
||||
* surface. Or %CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
|
@ -942,6 +942,9 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface,
|
|||
{
|
||||
assert (!surface->finished);
|
||||
|
||||
if (surface->backend->acquire_source_image == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
return _cairo_surface_set_error (surface,
|
||||
surface->backend->acquire_source_image (surface,
|
||||
image_out, image_extra));
|
||||
|
@ -1005,6 +1008,9 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
|
|||
{
|
||||
assert (!surface->finished);
|
||||
|
||||
if (surface->backend->acquire_dest_image == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
return _cairo_surface_set_error (surface,
|
||||
surface->backend->acquire_dest_image (surface,
|
||||
interest_rect,
|
||||
|
@ -1286,7 +1292,7 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
|
|||
{
|
||||
int num_boxes;
|
||||
cairo_box_int_t *boxes = NULL;
|
||||
cairo_rectangle_int_t stack_rects[CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_rectangle_int_t)];
|
||||
cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
|
||||
cairo_rectangle_int_t *rects = stack_rects;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
@ -1389,24 +1395,24 @@ _cairo_surface_paint (cairo_surface_t *surface,
|
|||
cairo_pattern_t *source)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_pattern_union_t dev_source;
|
||||
cairo_pattern_t *dev_source;
|
||||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
||||
if (status)
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
if (surface->backend->paint) {
|
||||
status = surface->backend->paint (surface, op, &dev_source.base);
|
||||
status = surface->backend->paint (surface, op, dev_source);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
status = _cairo_surface_fallback_paint (surface, op, &dev_source.base);
|
||||
status = _cairo_surface_fallback_paint (surface, op, dev_source);
|
||||
|
||||
FINISH:
|
||||
_cairo_pattern_fini (&dev_source.base);
|
||||
cairo_pattern_destroy (dev_source);
|
||||
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
@ -1418,31 +1424,31 @@ _cairo_surface_mask (cairo_surface_t *surface,
|
|||
cairo_pattern_t *mask)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_pattern_union_t dev_source;
|
||||
cairo_pattern_union_t dev_mask;
|
||||
cairo_pattern_t *dev_source;
|
||||
cairo_pattern_t *dev_mask;
|
||||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
||||
if (status)
|
||||
goto FINISH;
|
||||
|
||||
status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask);
|
||||
if (status)
|
||||
goto CLEANUP_SOURCE;
|
||||
|
||||
if (surface->backend->mask) {
|
||||
status = surface->backend->mask (surface, op, &dev_source.base, &dev_mask.base);
|
||||
status = surface->backend->mask (surface, op, dev_source, dev_mask);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
goto CLEANUP_MASK;
|
||||
}
|
||||
|
||||
status = _cairo_surface_fallback_mask (surface, op, &dev_source.base, &dev_mask.base);
|
||||
status = _cairo_surface_fallback_mask (surface, op, dev_source, dev_mask);
|
||||
|
||||
CLEANUP_MASK:
|
||||
_cairo_pattern_fini (&dev_mask.base);
|
||||
cairo_pattern_destroy (dev_mask);
|
||||
CLEANUP_SOURCE:
|
||||
_cairo_pattern_fini (&dev_source.base);
|
||||
cairo_pattern_destroy (dev_source);
|
||||
FINISH:
|
||||
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
@ -1467,29 +1473,29 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
|
|||
cairo_status_t status;
|
||||
|
||||
if (surface->backend->fill_stroke) {
|
||||
cairo_pattern_union_t dev_stroke_source;
|
||||
cairo_pattern_union_t dev_fill_source;
|
||||
cairo_pattern_t *dev_stroke_source;
|
||||
cairo_pattern_t *dev_fill_source;
|
||||
cairo_matrix_t dev_ctm = *stroke_ctm;
|
||||
cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
|
||||
|
||||
status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source);
|
||||
if (status)
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source);
|
||||
if (status) {
|
||||
_cairo_pattern_fini (&dev_stroke_source.base);
|
||||
cairo_pattern_destroy (dev_stroke_source);
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
||||
status = surface->backend->fill_stroke (surface, fill_op, &dev_fill_source.base,
|
||||
status = surface->backend->fill_stroke (surface, fill_op, dev_fill_source,
|
||||
fill_rule, fill_tolerance, fill_antialias,
|
||||
path, stroke_op, &dev_stroke_source.base, stroke_style,
|
||||
path, stroke_op, dev_stroke_source, stroke_style,
|
||||
&dev_ctm, &dev_ctm_inverse, stroke_tolerance,
|
||||
stroke_antialias);
|
||||
|
||||
_cairo_pattern_fini (&dev_stroke_source.base);
|
||||
_cairo_pattern_fini (&dev_fill_source.base);
|
||||
cairo_pattern_destroy (dev_stroke_source);
|
||||
cairo_pattern_destroy (dev_fill_source);
|
||||
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
@ -1521,7 +1527,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
|
|||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_pattern_union_t dev_source;
|
||||
cairo_pattern_t *dev_source;
|
||||
cairo_path_fixed_t *dev_path = path;
|
||||
cairo_path_fixed_t real_dev_path;
|
||||
cairo_matrix_t dev_ctm = *ctm;
|
||||
|
@ -1529,12 +1535,12 @@ _cairo_surface_stroke (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
||||
if (status)
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
if (surface->backend->stroke) {
|
||||
status = surface->backend->stroke (surface, op, &dev_source.base,
|
||||
status = surface->backend->stroke (surface, op, dev_source,
|
||||
path, stroke_style,
|
||||
&dev_ctm, &dev_ctm_inverse,
|
||||
tolerance, antialias);
|
||||
|
@ -1543,7 +1549,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
|
|||
goto FINISH;
|
||||
}
|
||||
|
||||
status = _cairo_surface_fallback_stroke (surface, op, &dev_source.base,
|
||||
status = _cairo_surface_fallback_stroke (surface, op, dev_source,
|
||||
path, stroke_style,
|
||||
&dev_ctm, &dev_ctm_inverse,
|
||||
tolerance, antialias);
|
||||
|
@ -1551,7 +1557,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
|
|||
FINISH:
|
||||
if (dev_path == &real_dev_path)
|
||||
_cairo_path_fixed_fini (&real_dev_path);
|
||||
_cairo_pattern_fini (&dev_source.base);
|
||||
cairo_pattern_destroy (dev_source);
|
||||
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
@ -1566,16 +1572,16 @@ _cairo_surface_fill (cairo_surface_t *surface,
|
|||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_pattern_union_t dev_source;
|
||||
cairo_pattern_t *dev_source;
|
||||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source);
|
||||
if (status)
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
if (surface->backend->fill) {
|
||||
status = surface->backend->fill (surface, op, &dev_source.base,
|
||||
status = surface->backend->fill (surface, op, dev_source,
|
||||
path, fill_rule,
|
||||
tolerance, antialias);
|
||||
|
||||
|
@ -1583,12 +1589,12 @@ _cairo_surface_fill (cairo_surface_t *surface,
|
|||
goto FINISH;
|
||||
}
|
||||
|
||||
status = _cairo_surface_fallback_fill (surface, op, &dev_source.base,
|
||||
status = _cairo_surface_fallback_fill (surface, op, dev_source,
|
||||
path, fill_rule,
|
||||
tolerance, antialias);
|
||||
|
||||
FINISH:
|
||||
_cairo_pattern_fini (&dev_source.base);
|
||||
cairo_pattern_destroy (dev_source);
|
||||
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
@ -2039,7 +2045,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
|
|||
{
|
||||
cairo_status_t status;
|
||||
cairo_scaled_font_t *dev_scaled_font = scaled_font;
|
||||
cairo_pattern_union_t dev_source;
|
||||
cairo_pattern_t *dev_source;
|
||||
cairo_matrix_t font_matrix;
|
||||
|
||||
assert (! surface->is_snapshot);
|
||||
|
@ -2049,7 +2055,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
|
|||
|
||||
status = _cairo_surface_copy_pattern_for_destination (source,
|
||||
surface,
|
||||
&dev_source.base);
|
||||
&dev_source);
|
||||
if (status)
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
|
@ -2074,7 +2080,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
|
|||
}
|
||||
status = cairo_scaled_font_status (dev_scaled_font);
|
||||
if (status) {
|
||||
_cairo_pattern_fini (&dev_source.base);
|
||||
cairo_pattern_destroy (dev_source);
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
||||
|
@ -2083,12 +2089,12 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
|
|||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (surface->backend->show_glyphs)
|
||||
status = surface->backend->show_glyphs (surface, op, &dev_source.base,
|
||||
status = surface->backend->show_glyphs (surface, op, dev_source,
|
||||
glyphs, num_glyphs,
|
||||
dev_scaled_font);
|
||||
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
status = _cairo_surface_fallback_show_glyphs (surface, op, &dev_source.base,
|
||||
status = _cairo_surface_fallback_show_glyphs (surface, op, dev_source,
|
||||
glyphs, num_glyphs,
|
||||
dev_scaled_font);
|
||||
|
||||
|
@ -2097,7 +2103,7 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
|
|||
if (dev_scaled_font != scaled_font)
|
||||
cairo_scaled_font_destroy (dev_scaled_font);
|
||||
|
||||
_cairo_pattern_fini (&dev_source.base);
|
||||
cairo_pattern_destroy (dev_source);
|
||||
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
@ -2364,11 +2370,11 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
|
|||
static cairo_status_t
|
||||
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
|
||||
cairo_surface_t *destination,
|
||||
cairo_pattern_t *pattern_out)
|
||||
cairo_pattern_t **pattern_out)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_pattern_init_copy (pattern_out, pattern);
|
||||
status = _cairo_pattern_create_copy (pattern_out, pattern);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
@ -2381,7 +2387,7 @@ _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
|
|||
* matrix should always be invertible. */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
_cairo_pattern_transform (pattern_out, &device_to_surface);
|
||||
_cairo_pattern_transform (*pattern_out, &device_to_surface);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
|
@ -1032,7 +1032,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
meta->height_pixels);
|
||||
if (paginated_surface->status) {
|
||||
cairo_surface_destroy (&meta->base);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
return paginated_surface->status;
|
||||
}
|
||||
|
||||
svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface);
|
||||
|
@ -1096,7 +1096,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
if (_cairo_memory_stream_length (contents) > 0) {
|
||||
if (_cairo_svg_surface_store_page (svg_surface) == NULL) {
|
||||
cairo_surface_destroy (paginated_surface);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1538,6 +1538,8 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
|||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (pattern->r1 == pattern->r2) {
|
||||
unsigned int n_stops = pattern->base.n_stops;
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<radialGradient id=\"radial%d\" "
|
||||
"gradientUnits=\"userSpaceOnUse\" "
|
||||
|
@ -1549,8 +1551,7 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
|||
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
|
||||
_cairo_output_stream_printf (document->xml_node_defs, ">\n");
|
||||
|
||||
if (extend == CAIRO_EXTEND_NONE ||
|
||||
pattern->base.n_stops < 1)
|
||||
if (extend == CAIRO_EXTEND_NONE || n_stops < 1)
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<stop offset=\"0\" style=\""
|
||||
"stop-color: rgb(0%%,0%%,0%%); "
|
||||
|
@ -1564,15 +1565,15 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
|||
pattern->base.stops[0].color.green * 100.0,
|
||||
pattern->base.stops[0].color.blue * 100.0,
|
||||
pattern->base.stops[0].color.alpha);
|
||||
if (pattern->base.n_stops > 1)
|
||||
if (n_stops > 1)
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<stop offset=\"0\" style=\""
|
||||
"stop-color: rgb(%f%%,%f%%,%f%%); "
|
||||
"stop-opacity: %f;\"/>\n",
|
||||
pattern->base.stops[1].color.red * 100.0,
|
||||
pattern->base.stops[1].color.green * 100.0,
|
||||
pattern->base.stops[1].color.blue * 100.0,
|
||||
pattern->base.stops[1].color.alpha);
|
||||
pattern->base.stops[n_stops - 1].color.red * 100.0,
|
||||
pattern->base.stops[n_stops - 1].color.green * 100.0,
|
||||
pattern->base.stops[n_stops - 1].color.blue * 100.0,
|
||||
pattern->base.stops[n_stops - 1].color.alpha);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -2377,7 +2378,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
_cairo_memory_stream_length (surface->xml_node) > 0) {
|
||||
if (_cairo_svg_surface_store_page (surface) == NULL) {
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -568,11 +568,13 @@ _cairo_traps_contain (cairo_traps_t *traps, double x, double y)
|
|||
void
|
||||
_cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
|
||||
{
|
||||
*extents = traps->extents;
|
||||
if (traps->num_traps == 0) {
|
||||
extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
|
||||
extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0);
|
||||
} else
|
||||
*extents = traps->extents;
|
||||
}
|
||||
|
||||
#define STACK_BOXES_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(cairo_box_int_t)))
|
||||
|
||||
/**
|
||||
* _cairo_traps_extract_region:
|
||||
* @traps: a #cairo_traps_t
|
||||
|
@ -591,7 +593,7 @@ cairo_int_status_t
|
|||
_cairo_traps_extract_region (cairo_traps_t *traps,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_box_int_t stack_boxes[STACK_BOXES_LEN];
|
||||
cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)];
|
||||
cairo_box_int_t *boxes = stack_boxes;
|
||||
int i, box_count;
|
||||
cairo_int_status_t status;
|
||||
|
|
|
@ -323,7 +323,7 @@ cairo_truetype_font_allocate_write_buffer (cairo_truetype_font_t *font,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
static void
|
||||
cairo_truetype_font_write (cairo_truetype_font_t *font,
|
||||
const void *data,
|
||||
size_t length)
|
||||
|
@ -331,13 +331,11 @@ cairo_truetype_font_write (cairo_truetype_font_t *font,
|
|||
cairo_status_t status;
|
||||
|
||||
if (font->status)
|
||||
return font->status;
|
||||
return;
|
||||
|
||||
status = _cairo_array_append_multiple (&font->output, data, length);
|
||||
if (status)
|
||||
return _cairo_truetype_font_set_error (font, status);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
status = _cairo_truetype_font_set_error (font, status);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -366,22 +364,29 @@ cairo_truetype_font_write_be32 (cairo_truetype_font_t *font,
|
|||
cairo_truetype_font_write (font, &be32_value, sizeof be32_value);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
cairo_truetype_font_align_output (cairo_truetype_font_t *font)
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_align_output (cairo_truetype_font_t *font,
|
||||
unsigned long *aligned)
|
||||
{
|
||||
int length, aligned, pad;
|
||||
int length, pad;
|
||||
unsigned char *padding;
|
||||
|
||||
length = _cairo_array_num_elements (&font->output);
|
||||
aligned = (length + 3) & ~3;
|
||||
pad = aligned - length;
|
||||
*aligned = (length + 3) & ~3;
|
||||
pad = *aligned - length;
|
||||
|
||||
if (pad) {
|
||||
cairo_truetype_font_allocate_write_buffer (font, pad, &padding);
|
||||
cairo_status_t status;
|
||||
|
||||
status = cairo_truetype_font_allocate_write_buffer (font, pad,
|
||||
&padding);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
memset (padding, 0, pad);
|
||||
}
|
||||
|
||||
return aligned;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -575,8 +580,9 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
|
|||
}
|
||||
|
||||
size = end - begin;
|
||||
|
||||
next = cairo_truetype_font_align_output (font);
|
||||
status = cairo_truetype_font_align_output (font, &next);
|
||||
if (status)
|
||||
goto FAIL;
|
||||
|
||||
status = cairo_truetype_font_check_boundary (font, next);
|
||||
if (status)
|
||||
|
@ -598,8 +604,11 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
|
|||
}
|
||||
}
|
||||
|
||||
font->glyphs[i].location =
|
||||
cairo_truetype_font_align_output (font) - start_offset;
|
||||
status = cairo_truetype_font_align_output (font, &next);
|
||||
if (status)
|
||||
goto FAIL;
|
||||
|
||||
font->glyphs[i].location = next - start_offset;
|
||||
|
||||
status = font->status;
|
||||
FAIL:
|
||||
|
@ -881,8 +890,9 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font,
|
|||
if (status)
|
||||
goto FAIL;
|
||||
|
||||
start = cairo_truetype_font_align_output (font);
|
||||
end = start;
|
||||
status = cairo_truetype_font_align_output (font, &start);
|
||||
if (status)
|
||||
goto FAIL;
|
||||
|
||||
end = 0;
|
||||
for (i = 0; i < font->num_tables; i++) {
|
||||
|
@ -891,7 +901,10 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font,
|
|||
goto FAIL;
|
||||
|
||||
end = _cairo_array_num_elements (&font->output);
|
||||
next = cairo_truetype_font_align_output (font);
|
||||
status = cairo_truetype_font_align_output (font, &next);
|
||||
if (status)
|
||||
goto FAIL;
|
||||
|
||||
cairo_truetype_font_update_entry (font, font->truetype_tables[i].pos,
|
||||
font->truetype_tables[i].tag, start, end);
|
||||
status = cairo_truetype_font_check_boundary (font, next);
|
||||
|
|
|
@ -110,6 +110,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
goto fail;
|
||||
|
||||
_cairo_array_init (&font->contents, sizeof (unsigned char));
|
||||
font->output = NULL;
|
||||
|
||||
*subset_return = font;
|
||||
|
||||
|
@ -709,12 +710,13 @@ cairo_type1_font_generate (cairo_type1_font_t *font, const char *name)
|
|||
static cairo_status_t
|
||||
cairo_type1_font_destroy (cairo_type1_font_t *font)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
free (font->widths);
|
||||
cairo_scaled_font_destroy (font->type1_scaled_font);
|
||||
_cairo_array_fini (&font->contents);
|
||||
status = _cairo_output_stream_destroy (font->output);
|
||||
if (font->output)
|
||||
status = _cairo_output_stream_destroy (font->output);
|
||||
free (font);
|
||||
|
||||
return status;
|
||||
|
|
|
@ -147,18 +147,20 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
|||
font->base.y_max = face->bbox.yMax;
|
||||
font->base.ascent = face->ascender;
|
||||
font->base.descent = face->descender;
|
||||
font->base.base_font = strdup (face->family_name);
|
||||
if (font->base.base_font == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; font->base.base_font[j]; j++) {
|
||||
if (font->base.base_font[j] == ' ')
|
||||
continue;
|
||||
font->base.base_font[i++] = font->base.base_font[j];
|
||||
if (face->family_name) {
|
||||
font->base.base_font = strdup (face->family_name);
|
||||
if (font->base.base_font == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto fail2;
|
||||
}
|
||||
for (i = 0, j = 0; font->base.base_font[j]; j++) {
|
||||
if (font->base.base_font[j] == ' ')
|
||||
continue;
|
||||
font->base.base_font[i++] = font->base.base_font[j];
|
||||
}
|
||||
font->base.base_font[i] = '\0';
|
||||
}
|
||||
font->base.base_font[i] = '\0';
|
||||
|
||||
font->glyphs = calloc (face->num_glyphs, sizeof font->glyphs[0]);
|
||||
if (font->glyphs == NULL) {
|
||||
|
@ -180,7 +182,8 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail3:
|
||||
free (font->base.base_font);
|
||||
if (font->base.base_font)
|
||||
free (font->base.base_font);
|
||||
fail2:
|
||||
_cairo_unscaled_font_destroy (unscaled_font);
|
||||
free (font);
|
||||
|
@ -190,16 +193,13 @@ _cairo_type1_font_subset_create (cairo_unscaled_font_t *unscaled_font,
|
|||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
cairo_type1_font_subset_use_glyph (cairo_type1_font_subset_t *font, int glyph)
|
||||
{
|
||||
if (font->glyphs[glyph].subset_index >= 0)
|
||||
return font->glyphs[glyph].subset_index;
|
||||
return;
|
||||
|
||||
font->glyphs[glyph].subset_index = font->num_glyphs;
|
||||
font->num_glyphs++;
|
||||
|
||||
return font->glyphs[glyph].subset_index;
|
||||
font->glyphs[glyph].subset_index = font->num_glyphs++;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
@ -1161,7 +1161,8 @@ cairo_type1_font_subset_destroy (void *abstract_font)
|
|||
|
||||
_cairo_unscaled_font_destroy (font->base.unscaled_font);
|
||||
|
||||
free (font->base.base_font);
|
||||
if (font->base.base_font)
|
||||
free (font->base.base_font);
|
||||
free (font->glyphs);
|
||||
free (font);
|
||||
}
|
||||
|
@ -1178,6 +1179,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
|
|||
unsigned long parent_glyph, length;
|
||||
unsigned int i;
|
||||
cairo_unscaled_font_t *unscaled_font;
|
||||
char buf[30];
|
||||
|
||||
/* XXX: Need to fix this to work with a general cairo_unscaled_font_t. */
|
||||
if (!_cairo_scaled_font_is_ft (scaled_font_subset->scaled_font))
|
||||
|
@ -1201,7 +1203,13 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
|
|||
if (status)
|
||||
goto fail1;
|
||||
|
||||
type1_subset->base_font = strdup (font->base.base_font);
|
||||
if (font->base.base_font) {
|
||||
type1_subset->base_font = strdup (font->base.base_font);
|
||||
} else {
|
||||
snprintf(buf, sizeof (buf), "CairoFont-%u-%u",
|
||||
scaled_font_subset->font_id, scaled_font_subset->subset_id);
|
||||
type1_subset->base_font = strdup (buf);
|
||||
}
|
||||
if (type1_subset->base_font == NULL)
|
||||
goto fail1;
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
/* This is the only header file not including cairoint.h. It only contains
|
||||
* typedefs.*/
|
||||
#include "cairo.h"
|
||||
#include "cairo-fixed-private.h"
|
||||
|
||||
typedef struct _cairo_array cairo_array_t;
|
||||
typedef struct _cairo_hash_table cairo_hash_table_t;
|
||||
|
@ -123,7 +124,8 @@ struct _cairo_cache {
|
|||
|
||||
typedef enum _cairo_paginated_mode {
|
||||
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
|
||||
CAIRO_PAGINATED_MODE_RENDER /* render page contents */
|
||||
CAIRO_PAGINATED_MODE_RENDER, /* render page contents */
|
||||
CAIRO_PAGINATED_MODE_FALLBACK /* paint fallback images */
|
||||
} cairo_paginated_mode_t;
|
||||
|
||||
/* Sure wish C had a real enum type so that this would be distinct
|
||||
|
@ -148,4 +150,172 @@ typedef enum _cairo_internal_surface_type {
|
|||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED
|
||||
} cairo_internal_surface_type_t;
|
||||
|
||||
typedef struct _cairo_region cairo_region_t;
|
||||
|
||||
typedef struct _cairo_point {
|
||||
cairo_fixed_t x;
|
||||
cairo_fixed_t y;
|
||||
} cairo_point_t;
|
||||
|
||||
typedef struct _cairo_slope
|
||||
{
|
||||
cairo_fixed_t dx;
|
||||
cairo_fixed_t dy;
|
||||
} cairo_slope_t, cairo_distance_t;
|
||||
|
||||
typedef struct _cairo_point_double {
|
||||
double x;
|
||||
double y;
|
||||
} cairo_point_double_t;
|
||||
|
||||
typedef struct _cairo_distance_double {
|
||||
double dx;
|
||||
double dy;
|
||||
} cairo_distance_double_t;
|
||||
|
||||
typedef struct _cairo_line {
|
||||
cairo_point_t p1;
|
||||
cairo_point_t p2;
|
||||
} cairo_line_t, cairo_box_t;
|
||||
|
||||
typedef struct _cairo_trapezoid {
|
||||
cairo_fixed_t top, bottom;
|
||||
cairo_line_t left, right;
|
||||
} cairo_trapezoid_t;
|
||||
|
||||
typedef struct _cairo_rectangle_int16 {
|
||||
int16_t x, y;
|
||||
uint16_t width, height;
|
||||
} cairo_rectangle_int16_t, cairo_glyph_size_t;
|
||||
|
||||
typedef struct _cairo_rectangle_int32 {
|
||||
int32_t x, y;
|
||||
uint32_t width, height;
|
||||
} cairo_rectangle_int32_t;
|
||||
|
||||
typedef struct _cairo_point_int16 {
|
||||
int16_t x, y;
|
||||
} cairo_point_int16_t;
|
||||
|
||||
typedef struct _cairo_point_int32 {
|
||||
int16_t x, y;
|
||||
} cairo_point_int32_t;
|
||||
|
||||
typedef struct _cairo_box_int16 {
|
||||
cairo_point_int16_t p1;
|
||||
cairo_point_int16_t p2;
|
||||
} cairo_box_int16_t;
|
||||
|
||||
typedef struct _cairo_box_int32 {
|
||||
cairo_point_int32_t p1;
|
||||
cairo_point_int32_t p2;
|
||||
} cairo_box_int32_t;
|
||||
|
||||
|
||||
#if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16
|
||||
typedef cairo_rectangle_int16_t cairo_rectangle_int_t;
|
||||
typedef cairo_point_int16_t cairo_point_int_t;
|
||||
typedef cairo_box_int16_t cairo_box_int_t;
|
||||
#define CAIRO_RECT_INT_MIN INT16_MIN
|
||||
#define CAIRO_RECT_INT_MAX INT16_MAX
|
||||
#elif CAIRO_FIXED_BITS == 32
|
||||
typedef cairo_rectangle_int32_t cairo_rectangle_int_t;
|
||||
typedef cairo_point_int32_t cairo_point_int_t;
|
||||
typedef cairo_box_int32_t cairo_box_int_t;
|
||||
#define CAIRO_RECT_INT_MIN INT32_MIN
|
||||
#define CAIRO_RECT_INT_MAX INT32_MAX
|
||||
#else
|
||||
#error Not sure how to pick a cairo_rectangle_int_t for your CAIRO_FIXED_BITS!
|
||||
#endif
|
||||
|
||||
typedef enum _cairo_direction {
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
CAIRO_DIRECTION_REVERSE
|
||||
} cairo_direction_t;
|
||||
|
||||
typedef struct _cairo_path_fixed cairo_path_fixed_t;
|
||||
typedef enum _cairo_clip_mode {
|
||||
CAIRO_CLIP_MODE_PATH,
|
||||
CAIRO_CLIP_MODE_REGION,
|
||||
CAIRO_CLIP_MODE_MASK
|
||||
} cairo_clip_mode_t;
|
||||
typedef struct _cairo_clip_path cairo_clip_path_t;
|
||||
|
||||
typedef struct _cairo_edge {
|
||||
cairo_line_t edge;
|
||||
int clockWise;
|
||||
|
||||
cairo_fixed_t current_x;
|
||||
} cairo_edge_t;
|
||||
|
||||
typedef struct _cairo_polygon {
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_point_t first_point;
|
||||
cairo_point_t current_point;
|
||||
cairo_bool_t has_current_point;
|
||||
|
||||
int num_edges;
|
||||
int edges_size;
|
||||
cairo_edge_t *edges;
|
||||
cairo_edge_t edges_embedded[8];
|
||||
} cairo_polygon_t;
|
||||
|
||||
typedef struct _cairo_spline_knots {
|
||||
cairo_point_t a, b, c, d;
|
||||
} cairo_spline_knots_t;
|
||||
typedef struct _cairo_spline {
|
||||
cairo_spline_knots_t knots;
|
||||
|
||||
cairo_slope_t initial_slope;
|
||||
cairo_slope_t final_slope;
|
||||
|
||||
int num_points;
|
||||
int points_size;
|
||||
cairo_point_t *points;
|
||||
cairo_point_t points_embedded[8];
|
||||
} cairo_spline_t;
|
||||
|
||||
typedef struct _cairo_pen_vertex {
|
||||
cairo_point_t point;
|
||||
|
||||
cairo_slope_t slope_ccw;
|
||||
cairo_slope_t slope_cw;
|
||||
} cairo_pen_vertex_t;
|
||||
|
||||
typedef struct _cairo_pen {
|
||||
double radius;
|
||||
double tolerance;
|
||||
|
||||
cairo_pen_vertex_t *vertices;
|
||||
int num_vertices;
|
||||
} cairo_pen_t;
|
||||
|
||||
typedef struct _cairo_color cairo_color_t;
|
||||
typedef struct _cairo_image_surface cairo_image_surface_t;
|
||||
|
||||
typedef struct _cairo_stroke_style {
|
||||
double line_width;
|
||||
cairo_line_cap_t line_cap;
|
||||
cairo_line_join_t line_join;
|
||||
double miter_limit;
|
||||
double *dash;
|
||||
unsigned int num_dashes;
|
||||
double dash_offset;
|
||||
} cairo_stroke_style_t;
|
||||
|
||||
typedef struct _cairo_format_masks {
|
||||
int bpp;
|
||||
unsigned long alpha_mask;
|
||||
unsigned long red_mask;
|
||||
unsigned long green_mask;
|
||||
unsigned long blue_mask;
|
||||
} cairo_format_masks_t;
|
||||
|
||||
typedef enum {
|
||||
CAIRO_STOCK_WHITE,
|
||||
CAIRO_STOCK_BLACK,
|
||||
CAIRO_STOCK_TRANSPARENT
|
||||
} cairo_stock_t;
|
||||
|
||||
#endif /* CAIRO_TYPES_PRIVATE_H */
|
||||
|
|
|
@ -258,6 +258,7 @@ _cairo_utf8_to_ucs4 (const unsigned char *str,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if CAIRO_HAS_UTF8_TO_UTF16
|
||||
/**
|
||||
* _cairo_utf8_to_utf16:
|
||||
* @str: an UTF-8 string
|
||||
|
@ -333,3 +334,4 @@ _cairo_utf8_to_utf16 (const unsigned char *str,
|
|||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,15 @@
|
|||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
/* We require Windows 2000 features such as GetGlyphIndices */
|
||||
#if !defined(WINVER) || (WINVER < 0x0500)
|
||||
# define WINVER 0x0500
|
||||
#endif
|
||||
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
|
||||
# define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-win32-private.h"
|
||||
|
@ -50,7 +59,7 @@
|
|||
#define TT_PRIM_CSPLINE 3
|
||||
#endif
|
||||
|
||||
#define OPENTYPE_CFF_TAG 0x20464643
|
||||
#define CMAP_TAG 0x70616d63
|
||||
|
||||
const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend;
|
||||
|
||||
|
@ -99,9 +108,8 @@ typedef struct {
|
|||
HFONT scaled_hfont;
|
||||
HFONT unscaled_hfont;
|
||||
|
||||
cairo_bool_t is_truetype;
|
||||
cairo_bool_t glyph_indexing;
|
||||
|
||||
cairo_bool_t is_bitmap;
|
||||
cairo_bool_t is_type1;
|
||||
cairo_bool_t delete_scaled_hfont;
|
||||
} cairo_win32_scaled_font_t;
|
||||
|
||||
|
@ -112,6 +120,10 @@ static cairo_status_t
|
|||
_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph);
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph);
|
||||
|
@ -565,6 +577,92 @@ _cairo_win32_scaled_font_fini (void *abstract_font)
|
|||
DeleteObject (scaled_font->unscaled_hfont);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font,
|
||||
double x,
|
||||
double y,
|
||||
const char *utf8,
|
||||
cairo_glyph_t **glyphs,
|
||||
int *num_glyphs)
|
||||
{
|
||||
uint16_t *utf16;
|
||||
int n16;
|
||||
int i;
|
||||
WORD *glyph_indices = NULL;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
double x_pos, y_pos;
|
||||
HDC hdc = NULL;
|
||||
cairo_matrix_t mat;
|
||||
|
||||
status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD));
|
||||
if (!glyph_indices) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto FAIL1;
|
||||
}
|
||||
|
||||
hdc = _get_global_font_dc ();
|
||||
if (!hdc) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto FAIL2;
|
||||
}
|
||||
|
||||
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
|
||||
if (status)
|
||||
goto FAIL2;
|
||||
|
||||
if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) {
|
||||
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW");
|
||||
goto FAIL2;
|
||||
}
|
||||
|
||||
*num_glyphs = n16;
|
||||
*glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t));
|
||||
if (!*glyphs) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto FAIL2;
|
||||
}
|
||||
|
||||
x_pos = x;
|
||||
y_pos = y;
|
||||
mat = scaled_font->base.ctm;
|
||||
cairo_matrix_invert (&mat);
|
||||
for (i = 0; i < n16; i++) {
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
|
||||
(*glyphs)[i].index = glyph_indices[i];
|
||||
(*glyphs)[i].x = x_pos;
|
||||
(*glyphs)[i].y = y_pos;
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (&scaled_font->base,
|
||||
glyph_indices[i],
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
||||
&scaled_glyph);
|
||||
if (status) {
|
||||
free (*glyphs);
|
||||
goto FAIL2;
|
||||
}
|
||||
|
||||
x = scaled_glyph->x_advance;
|
||||
y = scaled_glyph->y_advance;
|
||||
cairo_matrix_transform_distance (&mat, &x, &y);
|
||||
x_pos += x;
|
||||
y_pos += y;
|
||||
}
|
||||
|
||||
cairo_win32_scaled_font_done_font (&scaled_font->base);
|
||||
|
||||
FAIL2:
|
||||
free (glyph_indices);
|
||||
FAIL1:
|
||||
free (utf16);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
|
||||
double x,
|
||||
|
@ -585,6 +683,16 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
|
|||
double x_incr, y_incr;
|
||||
HDC hdc = NULL;
|
||||
|
||||
/* GetCharacterPlacement() returns utf16 instead of glyph indices
|
||||
* for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */
|
||||
if (scaled_font->is_type1)
|
||||
return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font,
|
||||
x,
|
||||
y,
|
||||
utf8,
|
||||
glyphs,
|
||||
num_glyphs);
|
||||
|
||||
/* Compute a vector in user space along the baseline of length one logical space unit */
|
||||
x_incr = 1;
|
||||
y_incr = 0;
|
||||
|
@ -742,11 +850,27 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font)
|
|||
|
||||
}
|
||||
|
||||
scaled_font->is_truetype = (metrics.tmPitchAndFamily & TMPF_TRUETYPE) != 0;
|
||||
scaled_font->glyph_indexing = scaled_font->is_truetype ||
|
||||
(GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR);
|
||||
// XXX in what situations does this OPENTYPE_CFF thing not have the
|
||||
// TMPF_TRUETYPE flag? GetFontData says it only works on Truetype fonts...
|
||||
scaled_font->is_bitmap = !(metrics.tmPitchAndFamily & TMPF_VECTOR);
|
||||
|
||||
/* Need to determine if this is a Type 1 font for the special
|
||||
* handling in _text_to_glyphs. Unlike TrueType or OpenType,
|
||||
* Type1 fonts do not have a "cmap" table (or any other table).
|
||||
* However GetFontData() will retrieve a Type1 font when
|
||||
* requesting that GetFontData() retrieve data from the start of
|
||||
* the file. This is to distinguish Type1 from stroke fonts such
|
||||
* as "Script" and "Modern". The TMPF_TRUETYPE test is redundant
|
||||
* but improves performance for the most common fonts.
|
||||
*/
|
||||
scaled_font->is_type1 = FALSE;
|
||||
if (!(metrics.tmPitchAndFamily & TMPF_TRUETYPE) &&
|
||||
(metrics.tmPitchAndFamily & TMPF_VECTOR))
|
||||
{
|
||||
if ((GetFontData (hdc, CMAP_TAG, 0, NULL, 0) == GDI_ERROR) &&
|
||||
(GetFontData (hdc, 0, 0, NULL, 0) != GDI_ERROR))
|
||||
{
|
||||
scaled_font->is_type1 = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_scaled_font_set_metrics (&scaled_font->base, &extents);
|
||||
|
||||
|
@ -767,7 +891,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f
|
|||
if (!hdc)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
if (!scaled_font->is_truetype) {
|
||||
if (scaled_font->is_bitmap) {
|
||||
/* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */
|
||||
cairo_font_extents_t font_extents;
|
||||
INT width = 0;
|
||||
|
@ -880,7 +1004,6 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
|
|||
GLYPHMETRICS metrics;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
UINT glyph_index_option;
|
||||
|
||||
if (!hdc)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
@ -889,16 +1012,11 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
if (scaled_font->glyph_indexing)
|
||||
glyph_index_option = GGO_GLYPH_INDEX;
|
||||
else
|
||||
glyph_index_option = 0;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
int x = _cairo_lround (glyphs[i].x);
|
||||
int y = _cairo_lround (glyphs[i].y);
|
||||
|
||||
GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | glyph_index_option,
|
||||
GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX,
|
||||
&metrics, 0, NULL, &matrix);
|
||||
|
||||
if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x)
|
||||
|
@ -954,22 +1072,16 @@ _flush_glyphs (cairo_glyph_state_t *state)
|
|||
int dx = 0;
|
||||
WCHAR * elements;
|
||||
int * dx_elements;
|
||||
UINT glyph_index_option;
|
||||
|
||||
status = _cairo_array_append (&state->dx, &dx);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (state->scaled_font->glyph_indexing)
|
||||
glyph_index_option = ETO_GLYPH_INDEX;
|
||||
else
|
||||
glyph_index_option = 0;
|
||||
|
||||
elements = _cairo_array_index (&state->glyphs, 0);
|
||||
dx_elements = _cairo_array_index (&state->dx, 0);
|
||||
if (!ExtTextOutW (state->hdc,
|
||||
state->start_x, state->last_y,
|
||||
glyph_index_option,
|
||||
ETO_GLYPH_INDEX,
|
||||
NULL,
|
||||
elements,
|
||||
state->glyphs.num_elements,
|
||||
|
@ -1157,8 +1269,10 @@ _cairo_win32_scaled_font_glyph_init (void *abstract_font,
|
|||
return status;
|
||||
}
|
||||
|
||||
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
|
||||
ASSERT_NOT_REACHED;
|
||||
if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
|
||||
status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
|
||||
|
@ -1316,18 +1430,143 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font,
|
|||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_scaled_font_map_glyphs_to_unicode (void *abstract_font,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_win32_scaled_font_t *scaled_font = abstract_font;
|
||||
unsigned int i;
|
||||
GLYPHSET *glyph_set;
|
||||
uint16_t *utf16 = NULL;
|
||||
WORD *glyph_indices = NULL;
|
||||
HDC hdc = NULL;
|
||||
int res;
|
||||
unsigned int i, j, k, count, num_glyphs;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (scaled_font->glyph_indexing)
|
||||
return;
|
||||
hdc = _get_global_font_dc ();
|
||||
if (!hdc)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
font_subset->to_unicode[i] = font_subset->glyphs[i];
|
||||
status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
res = GetFontUnicodeRanges(hdc, NULL);
|
||||
if (res == 0) {
|
||||
status = _cairo_win32_print_gdi_error (
|
||||
"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
glyph_set = malloc (res);
|
||||
if (glyph_set == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
res = GetFontUnicodeRanges(hdc, glyph_set);
|
||||
if (res == 0) {
|
||||
status = _cairo_win32_print_gdi_error (
|
||||
"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetFontUnicodeRanges");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
count = font_subset->num_glyphs;
|
||||
for (i = 0; i < glyph_set->cRanges && count > 0; i++) {
|
||||
num_glyphs = glyph_set->ranges[i].cGlyphs;
|
||||
|
||||
utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t));
|
||||
if (utf16 == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD));
|
||||
if (glyph_indices == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
for (j = 0; j < num_glyphs; j++)
|
||||
utf16[j] = glyph_set->ranges[i].wcLow + j;
|
||||
utf16[j] = 0;
|
||||
|
||||
if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) {
|
||||
status = _cairo_win32_print_gdi_error (
|
||||
"_cairo_win32_scaled_font_map_glyphs_to_unicode:GetGlyphIndicesW");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
for (j = 0; j < num_glyphs; j++) {
|
||||
for (k = 0; k < font_subset->num_glyphs; k++) {
|
||||
if (font_subset->glyphs[k] == glyph_indices[j]) {
|
||||
font_subset->to_unicode[k] = utf16[j];
|
||||
count--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free (glyph_indices);
|
||||
glyph_indices = NULL;
|
||||
free (utf16);
|
||||
utf16= NULL;
|
||||
}
|
||||
|
||||
fail2:
|
||||
if (glyph_indices)
|
||||
free (glyph_indices);
|
||||
if (utf16)
|
||||
free (utf16);
|
||||
free (glyph_set);
|
||||
fail1:
|
||||
cairo_win32_scaled_font_done_font (&scaled_font->base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_glyph_t glyph;
|
||||
cairo_win32_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *image;
|
||||
int width, height;
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
|
||||
y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
|
||||
x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x);
|
||||
y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y);
|
||||
width = x2 - x1;
|
||||
height = y2 - y1;
|
||||
|
||||
surface = (cairo_win32_surface_t *)
|
||||
cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
|
||||
|
||||
cr = cairo_create((cairo_surface_t *)surface);
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy(cr);
|
||||
|
||||
glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
|
||||
glyph.x = -x1;
|
||||
glyph.y = -y1;
|
||||
status = _draw_glyphs_on_surface (surface, scaled_font, RGB(0,0,0),
|
||||
0, 0, &glyph, 1);
|
||||
GdiFlush();
|
||||
|
||||
image = _compute_a8_mask (surface);
|
||||
cairo_surface_set_device_offset ((cairo_surface_t *)image, -x1, -y1);
|
||||
_cairo_scaled_glyph_set_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
(cairo_image_surface_t*)image);
|
||||
cairo_surface_destroy (&surface->base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1355,7 +1594,9 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
|
|||
cairo_path_fixed_t *path;
|
||||
cairo_matrix_t transform;
|
||||
cairo_fixed_t x, y;
|
||||
UINT glyph_index_option;
|
||||
|
||||
if (scaled_font->is_bitmap)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
hdc = _get_global_font_dc ();
|
||||
if (!hdc)
|
||||
|
@ -1376,13 +1617,8 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
|
|||
if (status)
|
||||
goto CLEANUP_PATH;
|
||||
|
||||
if (scaled_font->glyph_indexing)
|
||||
glyph_index_option = GGO_GLYPH_INDEX;
|
||||
else
|
||||
glyph_index_option = 0;
|
||||
|
||||
bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
|
||||
GGO_NATIVE | glyph_index_option,
|
||||
GGO_NATIVE | GGO_GLYPH_INDEX,
|
||||
&metrics, 0, NULL, &matrix);
|
||||
|
||||
if (bytesGlyph == GDI_ERROR) {
|
||||
|
@ -1398,7 +1634,7 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
|
|||
}
|
||||
|
||||
if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph),
|
||||
GGO_NATIVE | glyph_index_option,
|
||||
GGO_NATIVE | GGO_GLYPH_INDEX,
|
||||
&metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) {
|
||||
status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path");
|
||||
goto CLEANUP_BUFFER;
|
||||
|
|
|
@ -874,6 +874,7 @@ _cairo_win32_printing_surface_path_line_to (void *closure, cairo_point_t *point)
|
|||
{
|
||||
win32_path_info_t *path_info = closure;
|
||||
|
||||
path_info->surface->path_empty = FALSE;
|
||||
if (path_info->surface->has_ctm) {
|
||||
double x, y;
|
||||
|
||||
|
@ -899,6 +900,7 @@ _cairo_win32_printing_surface_path_curve_to (void *closure,
|
|||
win32_path_info_t *path_info = closure;
|
||||
POINT points[3];
|
||||
|
||||
path_info->surface->path_empty = FALSE;
|
||||
if (path_info->surface->has_ctm) {
|
||||
double x, y;
|
||||
|
||||
|
@ -1244,6 +1246,7 @@ _cairo_win32_printing_surface_fill (void *abstract_surface,
|
|||
|
||||
assert (_cairo_win32_printing_surface_operation_supported (surface, op, source));
|
||||
|
||||
surface->path_empty = TRUE;
|
||||
BeginPath (surface->dc);
|
||||
status = _cairo_win32_printing_surface_emit_path (surface, path);
|
||||
EndPath (surface->dc);
|
||||
|
@ -1266,7 +1269,7 @@ _cairo_win32_printing_surface_fill (void *abstract_surface,
|
|||
|
||||
FillPath (surface->dc);
|
||||
_cairo_win32_printing_surface_done_solid_brush (surface);
|
||||
} else {
|
||||
} else if (surface->path_empty == FALSE) {
|
||||
SaveDC (surface->dc);
|
||||
SelectClipPath (surface->dc, RGN_AND);
|
||||
status = _cairo_win32_printing_surface_paint_pattern (surface, source);
|
||||
|
@ -1358,6 +1361,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
|
|||
old_ctm = surface->ctm;
|
||||
old_has_ctm = surface->has_ctm;
|
||||
surface->has_ctm = TRUE;
|
||||
surface->path_empty = TRUE;
|
||||
BeginPath (surface->dc);
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
|
@ -1373,9 +1377,19 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
|
|||
EndPath (surface->dc);
|
||||
surface->ctm = old_ctm;
|
||||
surface->has_ctm = old_has_ctm;
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
SelectClipPath (surface->dc, RGN_AND);
|
||||
status = _cairo_win32_printing_surface_paint_pattern (surface, source);
|
||||
if (status == CAIRO_STATUS_SUCCESS && surface->path_empty == FALSE) {
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||
status = _cairo_win32_printing_surface_select_solid_brush (surface, source);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
SetPolyFillMode (surface->dc, WINDING);
|
||||
FillPath (surface->dc);
|
||||
_cairo_win32_printing_surface_done_solid_brush (surface);
|
||||
} else {
|
||||
SelectClipPath (surface->dc, RGN_AND);
|
||||
status = _cairo_win32_printing_surface_paint_pattern (surface, source);
|
||||
}
|
||||
}
|
||||
RestoreDC (surface->dc, -1);
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#define SB_NONE 0
|
||||
#endif
|
||||
|
||||
#define WIN32_FONT_LOGICAL_SCALE 1
|
||||
#define WIN32_FONT_LOGICAL_SCALE 32
|
||||
|
||||
typedef struct _cairo_win32_surface {
|
||||
cairo_surface_t base;
|
||||
|
@ -83,6 +83,7 @@ typedef struct _cairo_win32_surface {
|
|||
/* printing surface bits */
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
cairo_content_t content;
|
||||
cairo_bool_t path_empty;
|
||||
cairo_bool_t has_ctm;
|
||||
cairo_matrix_t ctm;
|
||||
int clip_saved_dc;
|
||||
|
|
|
@ -91,7 +91,7 @@ _cairo_win32_print_gdi_error (const char *context)
|
|||
NULL,
|
||||
last_error,
|
||||
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
(LPSTR) &lpMsgBuf,
|
||||
0, NULL)) {
|
||||
fprintf (stderr, "%s: Unknown GDI error", context);
|
||||
} else {
|
||||
|
@ -745,7 +745,7 @@ _composite_alpha_blend (cairo_win32_surface_t *dst,
|
|||
if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId ||
|
||||
os.dwMajorVersion != 4 || os.dwMinorVersion != 10)
|
||||
{
|
||||
HMODULE msimg32_dll = LoadLibrary ("msimg32");
|
||||
HMODULE msimg32_dll = LoadLibraryA ("msimg32");
|
||||
|
||||
if (msimg32_dll != NULL)
|
||||
alpha_blend = (cairo_alpha_blend_func_t)GetProcAddress (msimg32_dll,
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2007 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>
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
/* We require Windows 2000 features such as ETO_PDY */
|
||||
#if !defined(WINVER) || (WINVER < 0x0500)
|
||||
# define WINVER 0x0500
|
||||
#endif
|
||||
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
|
||||
# define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
|
||||
/* tmpfile() replacment for Windows.
|
||||
*
|
||||
* On Windows tmpfile() creates the file in the root directory. This
|
||||
* may fail due to unsufficient privileges.
|
||||
*/
|
||||
FILE *
|
||||
_cairo_win32_tmpfile (void)
|
||||
{
|
||||
DWORD path_len;
|
||||
WCHAR path_name[MAX_PATH + 1];
|
||||
WCHAR file_name[MAX_PATH + 1];
|
||||
HANDLE handle;
|
||||
int fd;
|
||||
FILE *fp;
|
||||
|
||||
path_len = GetTempPathW (MAX_PATH, path_name);
|
||||
if (path_len <= 0 || path_len >= MAX_PATH)
|
||||
return NULL;
|
||||
|
||||
if (GetTempFileNameW (path_name, L"ps_", 0, file_name) == 0)
|
||||
return NULL;
|
||||
|
||||
handle = CreateFileW (file_name,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
|
||||
NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
DeleteFileW (file_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = _open_osfhandle((intptr_t) handle, 0);
|
||||
if (fd < 0) {
|
||||
CloseHandle (handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fp = fdopen(fd, "w+b");
|
||||
if (fp == NULL) {
|
||||
_close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
|
@ -34,6 +34,7 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-xlib-private.h"
|
||||
#include "cairo-xlib-xrender-private.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
|
@ -292,7 +293,14 @@ _cairo_xlib_display_get (Display *dpy)
|
|||
|
||||
display->buggy_repeat = FALSE;
|
||||
if (strstr (ServerVendor (dpy), "X.Org") != NULL) {
|
||||
if (VendorRelease (dpy) <= 60802000)
|
||||
/* When modularized, the X.Org server VendorRelease was
|
||||
* bogusly reset to a very small number, without any change in
|
||||
* the ServerVendor string. We avoid considering the new
|
||||
* servers with the small number as buggy by restricting the
|
||||
* test to known bad releases. But there could be a problem
|
||||
* again in the future if X.Org server versions ever climb
|
||||
* back up to 6.7 or 6.8. */
|
||||
if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) <= 60802000)
|
||||
display->buggy_repeat = TRUE;
|
||||
} else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
|
||||
if (VendorRelease (dpy) <= 40500000)
|
||||
|
|
|
@ -33,16 +33,12 @@
|
|||
#ifndef CAIRO_XLIB_PRIVATE_H
|
||||
#define CAIRO_XLIB_PRIVATE_H
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-xlib.h"
|
||||
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-freelist-private.h"
|
||||
#include "cairo-mutex-private.h"
|
||||
#include "cairo-reference-count-private.h"
|
||||
#include "cairo-xlib-xrender-private.h"
|
||||
|
||||
#include <X11/Xutil.h> /* for XDestroyImage */
|
||||
|
||||
typedef struct _cairo_xlib_display cairo_xlib_display_t;
|
||||
typedef struct _cairo_xlib_hook cairo_xlib_hook_t;
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-xlib-private.h"
|
||||
#include "cairo-xlib-xrender-private.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#define CAIRO_XLIB_SURFACE_PRIVATE_H
|
||||
|
||||
#include "cairo-xlib.h"
|
||||
#include "cairo-xlib-private.h"
|
||||
#include "cairo-xlib-xrender-private.h"
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "cairo-xlib-surface-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
#include <X11/Xutil.h> /* for XDestroyImage */
|
||||
|
||||
/* Xlib doesn't define a typedef, so define one ourselves */
|
||||
typedef int (*cairo_xlib_error_func_t) (Display *display,
|
||||
XErrorEvent *event);
|
||||
|
@ -69,6 +71,10 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
|||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Instead of taking two round trips for each blending request,
|
||||
* assume that if a particular drawable fails GetImage that it will
|
||||
|
@ -1011,6 +1017,7 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface,
|
|||
break;
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
case CAIRO_EXTEND_PAD:
|
||||
default:
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
if (status)
|
||||
|
@ -2423,11 +2430,22 @@ cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
|
|||
return surface->height;
|
||||
}
|
||||
|
||||
typedef struct _cairo_xlib_surface_font_private {
|
||||
Display *dpy;
|
||||
enum {
|
||||
GLYPHSET_INDEX_ARGB32,
|
||||
GLYPHSET_INDEX_A8,
|
||||
GLYPHSET_INDEX_A1,
|
||||
NUM_GLYPHSETS
|
||||
};
|
||||
|
||||
typedef struct _cairo_xlib_font_glyphset_info {
|
||||
GlyphSet glyphset;
|
||||
cairo_format_t format;
|
||||
XRenderPictFormat *xrender_format;
|
||||
} cairo_xlib_font_glyphset_info_t;
|
||||
|
||||
typedef struct _cairo_xlib_surface_font_private {
|
||||
Display *dpy;
|
||||
cairo_xlib_font_glyphset_info_t glyphset_info[NUM_GLYPHSETS];
|
||||
} cairo_xlib_surface_font_private_t;
|
||||
|
||||
static void
|
||||
|
@ -2445,17 +2463,23 @@ _cairo_xlib_surface_remove_scaled_font (Display *dpy,
|
|||
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
||||
|
||||
if (font_private != NULL) {
|
||||
XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset);
|
||||
int i;
|
||||
for (i = 0; i < NUM_GLYPHSETS; i++) {
|
||||
cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i];
|
||||
if (glyphset_info->glyphset) {
|
||||
XRenderFreeGlyphSet (font_private->dpy, glyphset_info->glyphset);
|
||||
}
|
||||
}
|
||||
free (font_private);
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_font_init (Display *dpy,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_format_t format)
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_xlib_surface_font_private_t *font_private;
|
||||
int i;
|
||||
|
||||
font_private = malloc (sizeof (cairo_xlib_surface_font_private_t));
|
||||
if (!font_private)
|
||||
|
@ -2470,9 +2494,18 @@ _cairo_xlib_surface_font_init (Display *dpy,
|
|||
|
||||
|
||||
font_private->dpy = dpy;
|
||||
font_private->format = format;
|
||||
font_private->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy, format);
|
||||
font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->xrender_format);
|
||||
for (i = 0; i < NUM_GLYPHSETS; i++) {
|
||||
cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i];
|
||||
switch (i) {
|
||||
case GLYPHSET_INDEX_ARGB32: glyphset_info->format = CAIRO_FORMAT_ARGB32; break;
|
||||
case GLYPHSET_INDEX_A8: glyphset_info->format = CAIRO_FORMAT_A8; break;
|
||||
case GLYPHSET_INDEX_A1: glyphset_info->format = CAIRO_FORMAT_A1; break;
|
||||
default: ASSERT_NOT_REACHED; break;
|
||||
}
|
||||
glyphset_info->xrender_format = NULL;
|
||||
glyphset_info->glyphset = None;
|
||||
}
|
||||
|
||||
scaled_font->surface_private = font_private;
|
||||
scaled_font->surface_backend = &cairo_xlib_surface_backend;
|
||||
|
||||
|
@ -2491,10 +2524,19 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
|||
|
||||
display = _cairo_xlib_display_get (font_private->dpy);
|
||||
if (display != NULL) {
|
||||
cairo_status_t status = _cairo_xlib_display_queue_resource (display,
|
||||
XRenderFreeGlyphSet,
|
||||
font_private->glyphset);
|
||||
(void) status; /* XXX cannot propagate failure */
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_GLYPHSETS; i++) {
|
||||
cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i];
|
||||
if (glyphset_info->glyphset) {
|
||||
cairo_status_t status;
|
||||
status = _cairo_xlib_display_queue_resource (display,
|
||||
XRenderFreeGlyphSet,
|
||||
glyphset_info->glyphset);
|
||||
(void) status; /* XXX cannot propagate failure */
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_xlib_display_destroy (display);
|
||||
}
|
||||
|
||||
|
@ -2513,6 +2555,19 @@ static void _cairo_xlib_render_free_glyphs (Display *dpy, struct _cairo_xlib_ren
|
|||
&arg->glyph_index, 1);
|
||||
}
|
||||
|
||||
static cairo_xlib_font_glyphset_info_t *
|
||||
_cairo_xlib_scaled_glyph_get_glyphset_info (cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
return scaled_glyph->surface_private;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xlib_scaled_glyph_set_glyphset_info (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_xlib_font_glyphset_info_t *glyphset_info)
|
||||
{
|
||||
scaled_glyph->surface_private = glyphset_info;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
|
@ -2525,7 +2580,7 @@ _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
|||
struct _cairo_xlib_render_free_glyphs *arg = malloc (sizeof (*arg));
|
||||
if (arg != NULL) {
|
||||
cairo_status_t status;
|
||||
arg->glyphset = font_private->glyphset;
|
||||
arg->glyphset = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph)->glyphset;
|
||||
arg->glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
|
||||
status = _cairo_xlib_display_queue_work (display,
|
||||
(cairo_xlib_notify_func) _cairo_xlib_render_free_glyphs,
|
||||
|
@ -2551,6 +2606,32 @@ _native_byte_order_lsb (void)
|
|||
return *((char *) &x) == 1;
|
||||
}
|
||||
|
||||
static cairo_xlib_font_glyphset_info_t *
|
||||
_cairo_xlib_scaled_font_get_glyphset_info_for_format (cairo_scaled_font_t *scaled_font,
|
||||
cairo_format_t format)
|
||||
{
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
cairo_xlib_font_glyphset_info_t *glyphset_info;
|
||||
int glyphset_index;
|
||||
|
||||
switch (format) {
|
||||
default:
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
case CAIRO_FORMAT_ARGB32: glyphset_index = GLYPHSET_INDEX_ARGB32; break;
|
||||
case CAIRO_FORMAT_A8: glyphset_index = GLYPHSET_INDEX_A8; break;
|
||||
case CAIRO_FORMAT_A1: glyphset_index = GLYPHSET_INDEX_A1; break;
|
||||
}
|
||||
|
||||
glyphset_info = &font_private->glyphset_info[glyphset_index];
|
||||
|
||||
if (glyphset_info->glyphset == None) {
|
||||
glyphset_info->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(font_private->dpy, glyphset_info->format);
|
||||
glyphset_info->glyphset = XRenderCreateGlyphSet (font_private->dpy, glyphset_info->xrender_format);
|
||||
}
|
||||
|
||||
return glyphset_info;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_add_glyph (Display *dpy,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
|
@ -2564,6 +2645,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
|||
cairo_scaled_glyph_t *scaled_glyph = *pscaled_glyph;
|
||||
cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
|
||||
cairo_bool_t already_had_glyph_surface;
|
||||
cairo_xlib_font_glyphset_info_t *glyphset_info;
|
||||
|
||||
if (!glyph_surface) {
|
||||
|
||||
|
@ -2583,13 +2665,15 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
|||
}
|
||||
|
||||
if (scaled_font->surface_private == NULL) {
|
||||
status = _cairo_xlib_surface_font_init (dpy, scaled_font,
|
||||
glyph_surface->format);
|
||||
status = _cairo_xlib_surface_font_init (dpy, scaled_font);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
font_private = scaled_font->surface_private;
|
||||
|
||||
glyphset_info = _cairo_xlib_scaled_font_get_glyphset_info_for_format (scaled_font,
|
||||
glyph_surface->format);
|
||||
|
||||
/* If the glyph surface has zero height or width, we create
|
||||
* a clear 1x1 surface, to avoid various X server bugs.
|
||||
*/
|
||||
|
@ -2597,7 +2681,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
|||
cairo_t *cr;
|
||||
cairo_surface_t *tmp_surface;
|
||||
|
||||
tmp_surface = cairo_image_surface_create (font_private->format, 1, 1);
|
||||
tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1);
|
||||
cr = cairo_create (tmp_surface);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
||||
cairo_paint (cr);
|
||||
|
@ -2619,11 +2703,11 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
|||
* create a temporary surface for the glyph image with the font's
|
||||
* format.
|
||||
*/
|
||||
if (glyph_surface->format != font_private->format) {
|
||||
if (glyph_surface->format != glyphset_info->format) {
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *tmp_surface;
|
||||
|
||||
tmp_surface = cairo_image_surface_create (font_private->format,
|
||||
tmp_surface = cairo_image_surface_create (glyphset_info->format,
|
||||
glyph_surface->width,
|
||||
glyph_surface->height);
|
||||
tmp_surface->device_transform = glyph_surface->base.device_transform;
|
||||
|
@ -2719,11 +2803,13 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
|
|||
|
||||
glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
|
||||
|
||||
XRenderAddGlyphs (dpy, font_private->glyphset,
|
||||
XRenderAddGlyphs (dpy, glyphset_info->glyphset,
|
||||
&glyph_index, &(glyph_info), 1,
|
||||
(char *) data,
|
||||
glyph_surface->stride * glyph_surface->height);
|
||||
|
||||
_cairo_xlib_scaled_glyph_set_glyphset_info (scaled_glyph, glyphset_info);
|
||||
|
||||
if (data != glyph_surface->data)
|
||||
free (data);
|
||||
|
||||
|
@ -2773,19 +2859,23 @@ typedef struct {
|
|||
} p;
|
||||
} cairo_xlib_glyph_t;
|
||||
|
||||
/* compile-time assert that cairo_xlib_glyph_t is the same size as cairo_glyph_t */
|
||||
typedef int cairo_xlib_glyph_t_size_assertion [sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t) ? 1 : -1];
|
||||
|
||||
#define GLYPH_INDEX_SKIP ((unsigned long) -1)
|
||||
#define STACK_ELTS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (XGlyphElt8)))
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
||||
cairo_xlib_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
int width,
|
||||
int num_elts,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
cairo_xlib_surface_t *src,
|
||||
cairo_surface_attributes_t *attributes)
|
||||
cairo_surface_attributes_t *attributes,
|
||||
/* info for this chunk */
|
||||
int num_elts,
|
||||
int width,
|
||||
cairo_xlib_font_glyphset_info_t *glyphset_info)
|
||||
{
|
||||
/* Which XRenderCompositeText function to use */
|
||||
cairo_xrender_composite_text_func_t composite_text_func;
|
||||
|
@ -2793,7 +2883,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
|||
|
||||
/* Element buffer stuff */
|
||||
XGlyphElt8 *elts;
|
||||
XGlyphElt8 stack_elts[STACK_ELTS_LEN];
|
||||
XGlyphElt8 stack_elts[CAIRO_STACK_ARRAY_LENGTH (XGlyphElt8)];
|
||||
|
||||
/* Reuse the input glyph array for output char generation */
|
||||
char *char8 = (char *) glyphs;
|
||||
|
@ -2805,8 +2895,6 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
|||
int n; /* Num output glyphs in current element */
|
||||
int j; /* Num output glyphs so far */
|
||||
|
||||
cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
|
||||
|
||||
switch (width) {
|
||||
case 1:
|
||||
/* don't cast the 8-variant, to catch possible mismatches */
|
||||
|
@ -2824,7 +2912,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
|||
}
|
||||
|
||||
/* Allocate element array */
|
||||
if (num_elts <= STACK_ELTS_LEN) {
|
||||
if (num_elts <= ARRAY_LENGTH (stack_elts)) {
|
||||
elts = stack_elts;
|
||||
} else {
|
||||
elts = _cairo_malloc_ab (num_elts, sizeof (XGlyphElt8));
|
||||
|
@ -2851,7 +2939,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
|||
n = 0;
|
||||
}
|
||||
elts[nelt].chars = char8 + size * j;
|
||||
elts[nelt].glyphset = font_private->glyphset;
|
||||
elts[nelt].glyphset = glyphset_info->glyphset;
|
||||
elts[nelt].xOff = glyphs[i].p.i.x;
|
||||
elts[nelt].yOff = glyphs[i].p.i.y;
|
||||
}
|
||||
|
@ -2877,7 +2965,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
|||
_render_operator (op),
|
||||
src->src_picture,
|
||||
dst->dst_picture,
|
||||
font_private->xrender_format,
|
||||
glyphset_info->xrender_format,
|
||||
attributes->x_offset + elts[0].xOff,
|
||||
attributes->y_offset + elts[0].yOff,
|
||||
elts[0].xOff, elts[0].yOff,
|
||||
|
@ -2889,8 +2977,6 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#undef STACK_ELTS_LEN
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
||||
cairo_xlib_glyph_t *glyphs,
|
||||
|
@ -2904,6 +2990,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_fixed_t x = 0, y = 0;
|
||||
cairo_xlib_font_glyphset_info_t *glyphset_info = NULL, *this_glyphset_info;
|
||||
|
||||
unsigned long max_index = 0;
|
||||
int width = 1;
|
||||
|
@ -2954,6 +3041,19 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Send unsent glyphs to the server */
|
||||
if (_cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph) == NULL) {
|
||||
status = _cairo_xlib_surface_add_glyph (dst->dpy,
|
||||
scaled_font,
|
||||
&scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
this_glyphset_info = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph);
|
||||
if (!glyphset_info)
|
||||
glyphset_info = this_glyphset_info;
|
||||
|
||||
old_width = width;
|
||||
|
||||
/* Update max glyph index */
|
||||
|
@ -2969,11 +3069,20 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
|||
|
||||
/* If we will pass the max request size by adding this glyph,
|
||||
* flush current glyphs. Note that we account for a
|
||||
* possible element being added below. */
|
||||
if (request_size + width > max_request_size - sz_xGlyphElt) {
|
||||
* possible element being added below.
|
||||
*
|
||||
* Also flush if changing glyphsets, as Xrender limits one mask
|
||||
* format per request, so we can either break up, or use a
|
||||
* wide-enough mask format. We do the former. One reason to
|
||||
* prefer the latter is the fact that Xserver ADDs all glyphs
|
||||
* to the mask first, and then composes that to final surface,
|
||||
* though it's not a big deal.
|
||||
*/
|
||||
if (request_size + width > max_request_size - sz_xGlyphElt ||
|
||||
(this_glyphset_info != glyphset_info)) {
|
||||
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
|
||||
old_width, num_elts,
|
||||
scaled_font, op, src, attributes);
|
||||
scaled_font, op, src, attributes,
|
||||
num_elts, old_width, glyphset_info);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
return status;
|
||||
|
||||
|
@ -2986,7 +3095,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
|||
num_elts = 0;
|
||||
num_out_glyphs = 0;
|
||||
x = y = 0;
|
||||
|
||||
glyphset_info = this_glyphset_info;
|
||||
}
|
||||
|
||||
/* Convert absolute glyph position to relative-to-current-point
|
||||
|
@ -3001,16 +3110,6 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
|||
request_size += sz_xGlyphElt;
|
||||
}
|
||||
|
||||
/* Send unsent glyphs to the server */
|
||||
if (scaled_glyph->surface_private == NULL) {
|
||||
status = _cairo_xlib_surface_add_glyph (dst->dpy,
|
||||
scaled_font,
|
||||
&scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
scaled_glyph->surface_private = (void *) 1;
|
||||
}
|
||||
|
||||
/* adjust current-position */
|
||||
x = this_x + scaled_glyph->x_advance;
|
||||
y = this_y + scaled_glyph->y_advance;
|
||||
|
@ -3021,8 +3120,8 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
|
|||
|
||||
if (num_elts)
|
||||
status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, num_glyphs,
|
||||
width, num_elts,
|
||||
scaled_font, op, src, attributes);
|
||||
scaled_font, op, src, attributes,
|
||||
num_elts, width, glyphset_info);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -33,12 +33,9 @@
|
|||
#ifndef CAIRO_XLIB_XRENDER_PRIVATE_H
|
||||
#define CAIRO_XLIB_XRENDER_PRIVATE_H
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
|
||||
#include "cairo-xlib-xrender.h"
|
||||
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
|
||||
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <X11/extensions/renderproto.h>
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#include <cairo.h>
|
||||
|
||||
#if CAIRO_HAS_XLIB_SURFACE
|
||||
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
@ -56,8 +56,8 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
|
|||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#else /* CAIRO_HAS_XLIB_SURFACE */
|
||||
# error Cairo was not compiled with support for the xlib backend
|
||||
#endif /* CAIRO_HAS_XLIB_SURFACE */
|
||||
#else /* CAIRO_HAS_XLIB_XRENDER_SURFACE */
|
||||
# error Cairo was not compiled with support for the xlib XRender backend
|
||||
#endif /* CAIRO_HAS_XLIB_XRENDER_SURFACE */
|
||||
|
||||
#endif /* CAIRO_XLIB_XRENDER_H */
|
||||
|
|
|
@ -67,7 +67,7 @@ static const cairo_t _cairo_nil = {
|
|||
* a bit of a pain, but it should be easy to always catch as long as
|
||||
* one adds a new test case to test a trigger of the new status value.
|
||||
*/
|
||||
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_INDEX
|
||||
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_TEMP_FILE_ERROR
|
||||
|
||||
/**
|
||||
* _cairo_error:
|
||||
|
@ -3019,6 +3019,9 @@ cairo_text_path (cairo_t *cr, const char *utf8)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
if (utf8 == NULL)
|
||||
return;
|
||||
|
||||
cairo_get_current_point (cr, &x, &y);
|
||||
|
||||
status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
|
||||
|
@ -3076,6 +3079,9 @@ cairo_glyph_path (cairo_t *cr, const cairo_glyph_t *glyphs, int num_glyphs)
|
|||
if (cr->status)
|
||||
return;
|
||||
|
||||
if (num_glyphs == 0)
|
||||
return;
|
||||
|
||||
status = _cairo_gstate_glyph_path (cr->gstate,
|
||||
glyphs, num_glyphs,
|
||||
cr->path);
|
||||
|
@ -3326,17 +3332,19 @@ cairo_get_target (cairo_t *cr)
|
|||
* cairo_get_group_target:
|
||||
* @cr: a cairo context
|
||||
*
|
||||
* Gets the target surface for the current group as started by the
|
||||
* most recent call to cairo_push_group() or
|
||||
* cairo_push_group_with_content().
|
||||
* Gets the current destination surface for the context. This is either
|
||||
* the original target surface as passed to cairo_create() or the target
|
||||
* surface for the current group as started by the most recent call to
|
||||
* cairo_push_group() or cairo_push_group_with_content().
|
||||
*
|
||||
* This function will return NULL if called "outside" of any group
|
||||
* rendering blocks, (that is, after the last balancing call to
|
||||
* cairo_pop_group() or cairo_pop_group_to_source()).
|
||||
* This function will always return a valid pointer, but the result
|
||||
* can be a "nil" surface if @cr is already in an error state,
|
||||
* (ie. cairo_status() <literal>!=</literal> %CAIRO_STATUS_SUCCESS).
|
||||
* A nil surface is indicated by cairo_surface_status()
|
||||
* <literal>!=</literal> %CAIRO_STATUS_SUCCESS.
|
||||
*
|
||||
* Return value: the target group surface, or NULL if none. This
|
||||
* object is owned by cairo. To keep a reference to it, you must call
|
||||
* cairo_surface_reference().
|
||||
* Return value: the target surface. This object is owned by cairo. To
|
||||
* keep a reference to it, you must call cairo_surface_reference().
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
|
@ -3551,6 +3559,8 @@ cairo_status_to_string (cairo_status_t status)
|
|||
return "invalid index passed to getter";
|
||||
case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
|
||||
return "clip region not representable in desired format";
|
||||
case CAIRO_STATUS_TEMP_FILE_ERROR:
|
||||
return "error creating or writing to a temporary file";
|
||||
}
|
||||
|
||||
return "<unknown error status>";
|
||||
|
|
|
@ -201,6 +201,7 @@ typedef struct _cairo_user_data_key {
|
|||
* @CAIRO_STATUS_INVALID_DSC_COMMENT: invalid value for a DSC comment (Since 1.2)
|
||||
* @CAIRO_STATUS_INVALID_INDEX: invalid index passed to getter (Since 1.4)
|
||||
* @CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: clip region not representable in desired format (Since 1.4)
|
||||
* @CAIRO_STATUS_TEMP_FILE_ERROR: error creating or writing to a temporary file (Since 1.6)
|
||||
*
|
||||
* #cairo_status_t is used to indicate errors that can occur when
|
||||
* using Cairo. In some cases it is returned directly by functions.
|
||||
|
@ -233,7 +234,9 @@ typedef enum _cairo_status {
|
|||
CAIRO_STATUS_INVALID_DASH,
|
||||
CAIRO_STATUS_INVALID_DSC_COMMENT,
|
||||
CAIRO_STATUS_INVALID_INDEX,
|
||||
CAIRO_STATUS_CLIP_NOT_REPRESENTABLE
|
||||
CAIRO_STATUS_CLIP_NOT_REPRESENTABLE,
|
||||
CAIRO_STATUS_TEMP_FILE_ERROR
|
||||
/* after adding a new error: update CAIRO_STATUS_LAST_STATUS in cairo.c */
|
||||
} cairo_status_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -81,6 +81,12 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
#ifdef _WIN32
|
||||
cairo_private FILE *
|
||||
_cairo_win32_tmpfile (void);
|
||||
#define tmpfile() _cairo_win32_tmpfile()
|
||||
#endif
|
||||
|
||||
#undef MIN
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
|
@ -99,13 +105,6 @@ CAIRO_BEGIN_DECLS
|
|||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
#undef assert
|
||||
#define assert(expr) \
|
||||
do { if (!(expr)) fprintf(stderr, "Assertion failed at %s:%d: %s\n", \
|
||||
__FILE__, __LINE__, #expr); } while (0)
|
||||
#endif
|
||||
|
||||
#undef ARRAY_LENGTH
|
||||
#define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
|
||||
|
||||
|
@ -116,6 +115,8 @@ CAIRO_BEGIN_DECLS
|
|||
#define CAIRO_STACK_BUFFER_SIZE (512 * sizeof (int))
|
||||
#endif
|
||||
|
||||
#define CAIRO_STACK_ARRAY_LENGTH(T) (CAIRO_STACK_BUFFER_SIZE / sizeof(T))
|
||||
|
||||
#define ASSERT_NOT_REACHED \
|
||||
do { \
|
||||
static const int NOT_REACHED = 0; \
|
||||
|
@ -177,152 +178,8 @@ be32_to_cpu(uint32_t v)
|
|||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-cache-private.h"
|
||||
#include "cairo-fixed-private.h"
|
||||
#include "cairo-reference-count-private.h"
|
||||
|
||||
typedef struct _cairo_region cairo_region_t;
|
||||
|
||||
typedef struct _cairo_point {
|
||||
cairo_fixed_t x;
|
||||
cairo_fixed_t y;
|
||||
} cairo_point_t;
|
||||
|
||||
typedef struct _cairo_slope
|
||||
{
|
||||
cairo_fixed_t dx;
|
||||
cairo_fixed_t dy;
|
||||
} cairo_slope_t, cairo_distance_t;
|
||||
|
||||
typedef struct _cairo_point_double {
|
||||
double x;
|
||||
double y;
|
||||
} cairo_point_double_t;
|
||||
|
||||
typedef struct _cairo_distance_double {
|
||||
double dx;
|
||||
double dy;
|
||||
} cairo_distance_double_t;
|
||||
|
||||
typedef struct _cairo_line {
|
||||
cairo_point_t p1;
|
||||
cairo_point_t p2;
|
||||
} cairo_line_t, cairo_box_t;
|
||||
|
||||
typedef struct _cairo_trapezoid {
|
||||
cairo_fixed_t top, bottom;
|
||||
cairo_line_t left, right;
|
||||
} cairo_trapezoid_t;
|
||||
|
||||
typedef struct _cairo_rectangle_int16 {
|
||||
int16_t x, y;
|
||||
uint16_t width, height;
|
||||
} cairo_rectangle_int16_t, cairo_glyph_size_t;
|
||||
|
||||
typedef struct _cairo_rectangle_int32 {
|
||||
int32_t x, y;
|
||||
uint32_t width, height;
|
||||
} cairo_rectangle_int32_t;
|
||||
|
||||
typedef struct _cairo_point_int16 {
|
||||
int16_t x, y;
|
||||
} cairo_point_int16_t;
|
||||
|
||||
typedef struct _cairo_point_int32 {
|
||||
int16_t x, y;
|
||||
} cairo_point_int32_t;
|
||||
|
||||
typedef struct _cairo_box_int16 {
|
||||
cairo_point_int16_t p1;
|
||||
cairo_point_int16_t p2;
|
||||
} cairo_box_int16_t;
|
||||
|
||||
typedef struct _cairo_box_int32 {
|
||||
cairo_point_int32_t p1;
|
||||
cairo_point_int32_t p2;
|
||||
} cairo_box_int32_t;
|
||||
|
||||
#if CAIRO_FIXED_BITS == 32 && CAIRO_FIXED_FRAC_BITS >= 16
|
||||
typedef cairo_rectangle_int16_t cairo_rectangle_int_t;
|
||||
typedef cairo_point_int16_t cairo_point_int_t;
|
||||
typedef cairo_box_int16_t cairo_box_int_t;
|
||||
#define CAIRO_RECT_INT_MIN INT16_MIN
|
||||
#define CAIRO_RECT_INT_MAX INT16_MAX
|
||||
#elif CAIRO_FIXED_BITS == 32
|
||||
typedef cairo_rectangle_int32_t cairo_rectangle_int_t;
|
||||
typedef cairo_point_int32_t cairo_point_int_t;
|
||||
typedef cairo_box_int32_t cairo_box_int_t;
|
||||
#define CAIRO_RECT_INT_MIN INT32_MIN
|
||||
#define CAIRO_RECT_INT_MAX INT32_MAX
|
||||
#else
|
||||
#error Not sure how to pick a cairo_rectangle_int_t for your CAIRO_FIXED_BITS!
|
||||
#endif
|
||||
|
||||
typedef enum _cairo_direction {
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
CAIRO_DIRECTION_REVERSE
|
||||
} cairo_direction_t;
|
||||
|
||||
typedef struct _cairo_path_fixed cairo_path_fixed_t;
|
||||
typedef enum _cairo_clip_mode {
|
||||
CAIRO_CLIP_MODE_PATH,
|
||||
CAIRO_CLIP_MODE_REGION,
|
||||
CAIRO_CLIP_MODE_MASK
|
||||
} cairo_clip_mode_t;
|
||||
typedef struct _cairo_clip_path cairo_clip_path_t;
|
||||
|
||||
typedef struct _cairo_edge {
|
||||
cairo_line_t edge;
|
||||
int clockWise;
|
||||
|
||||
cairo_fixed_t current_x;
|
||||
} cairo_edge_t;
|
||||
|
||||
typedef struct _cairo_polygon {
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_point_t first_point;
|
||||
cairo_point_t current_point;
|
||||
cairo_bool_t has_current_point;
|
||||
|
||||
int num_edges;
|
||||
int edges_size;
|
||||
cairo_edge_t *edges;
|
||||
cairo_edge_t edges_embedded[8];
|
||||
} cairo_polygon_t;
|
||||
|
||||
typedef struct _cairo_spline_knots {
|
||||
cairo_point_t a, b, c, d;
|
||||
} cairo_spline_knots_t;
|
||||
typedef struct _cairo_spline {
|
||||
cairo_spline_knots_t knots;
|
||||
|
||||
cairo_slope_t initial_slope;
|
||||
cairo_slope_t final_slope;
|
||||
|
||||
int num_points;
|
||||
int points_size;
|
||||
cairo_point_t *points;
|
||||
cairo_point_t points_embedded[8];
|
||||
} cairo_spline_t;
|
||||
|
||||
typedef struct _cairo_pen_vertex {
|
||||
cairo_point_t point;
|
||||
|
||||
cairo_slope_t slope_ccw;
|
||||
cairo_slope_t slope_cw;
|
||||
} cairo_pen_vertex_t;
|
||||
|
||||
typedef struct _cairo_pen {
|
||||
double radius;
|
||||
double tolerance;
|
||||
|
||||
cairo_pen_vertex_t *vertices;
|
||||
int num_vertices;
|
||||
} cairo_pen_t;
|
||||
|
||||
typedef struct _cairo_color cairo_color_t;
|
||||
typedef struct _cairo_image_surface cairo_image_surface_t;
|
||||
|
||||
cairo_private void
|
||||
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_t *rectangle);
|
||||
|
||||
|
@ -528,7 +385,7 @@ struct _cairo_scaled_font_backend {
|
|||
unsigned char *buffer,
|
||||
unsigned long *length);
|
||||
|
||||
void
|
||||
cairo_warn cairo_int_status_t
|
||||
(*map_glyphs_to_unicode)(void *scaled_font,
|
||||
cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
|
@ -570,16 +427,6 @@ extern const cairo_private struct _cairo_scaled_font_backend cairo_atsui_scaled_
|
|||
|
||||
#endif
|
||||
|
||||
typedef struct _cairo_stroke_style {
|
||||
double line_width;
|
||||
cairo_line_cap_t line_cap;
|
||||
cairo_line_join_t line_join;
|
||||
double miter_limit;
|
||||
double *dash;
|
||||
unsigned int num_dashes;
|
||||
double dash_offset;
|
||||
} cairo_stroke_style_t;
|
||||
|
||||
struct _cairo_surface_backend {
|
||||
cairo_surface_type_t type;
|
||||
|
||||
|
@ -840,14 +687,6 @@ struct _cairo_surface_backend {
|
|||
cairo_antialias_t stroke_antialias);
|
||||
};
|
||||
|
||||
typedef struct _cairo_format_masks {
|
||||
int bpp;
|
||||
unsigned long alpha_mask;
|
||||
unsigned long red_mask;
|
||||
unsigned long green_mask;
|
||||
unsigned long blue_mask;
|
||||
} cairo_format_masks_t;
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
|
||||
struct _cairo_image_surface {
|
||||
|
@ -887,12 +726,6 @@ struct _cairo_color {
|
|||
unsigned short alpha_short;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CAIRO_STOCK_WHITE,
|
||||
CAIRO_STOCK_BLACK,
|
||||
CAIRO_STOCK_TRANSPARENT
|
||||
} cairo_stock_t;
|
||||
|
||||
#define CAIRO_EXTEND_SURFACE_DEFAULT CAIRO_EXTEND_NONE
|
||||
#define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD
|
||||
#define CAIRO_FILTER_DEFAULT CAIRO_FILTER_BEST
|
||||
|
@ -1014,6 +847,11 @@ typedef struct _cairo_traps {
|
|||
#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_FT_FONT_FAMILY_DEFAULT
|
||||
#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &cairo_ft_scaled_font_backend
|
||||
|
||||
#else
|
||||
|
||||
/* Paranoia: this should have been caught by configure. */
|
||||
#error No font backends are available.
|
||||
|
||||
#endif
|
||||
|
||||
#define CAIRO_GSTATE_OPERATOR_DEFAULT CAIRO_OPERATOR_OVER
|
||||
|
@ -1520,7 +1358,7 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t *path,
|
|||
cairo_path_fixed_close_path_func_t *close_path,
|
||||
void *closure);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_private void
|
||||
_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2);
|
||||
|
@ -1957,6 +1795,9 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface);
|
|||
CAIRO_CONTENT_COLOR_ALPHA))\
|
||||
== 0))
|
||||
|
||||
cairo_private cairo_format_t
|
||||
_cairo_format_width (cairo_format_t format);
|
||||
|
||||
cairo_private cairo_format_t
|
||||
_cairo_format_from_content (cairo_content_t content);
|
||||
|
||||
|
@ -2221,6 +2062,10 @@ _cairo_slope_counter_clockwise (cairo_slope_t *a, cairo_slope_t *b);
|
|||
|
||||
/* cairo_pattern.c */
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_pattern_create_copy (cairo_pattern_t **pattern,
|
||||
const cairo_pattern_t *other);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
||||
const cairo_pattern_t *other);
|
||||
|
@ -2316,11 +2161,16 @@ _cairo_utf8_to_ucs4 (const unsigned char *str,
|
|||
uint32_t **result,
|
||||
int *items_written);
|
||||
|
||||
#if CAIRO_HAS_WIN32_FONT+0 || CAIRO_HAS_ATSUI_FONT+0
|
||||
# define CAIRO_HAS_UTF8_TO_UTF16 1
|
||||
#endif
|
||||
#if CAIRO_HAS_UTF8_TO_UTF16
|
||||
cairo_private cairo_status_t
|
||||
_cairo_utf8_to_utf16 (const unsigned char *str,
|
||||
int len,
|
||||
uint16_t **result,
|
||||
int *items_written);
|
||||
#endif
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_error (cairo_status_t status);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
CAIRO_HAS_HIDDEN_SYMBOLS
|
|
@ -124,11 +124,10 @@ SourcePictureClassify (source_image_t *pict,
|
|||
int offset1 = stride < 0 ? \
|
||||
offset0 + ((-stride) >> 1) * ((pict->height) >> 1) : \
|
||||
offset0 + (offset0 >> 2)
|
||||
/* Note no trailing semicolon on the above macro; if it's there, then
|
||||
* the typical usage YV12_SETUP(pict); will have an extra trailing ;
|
||||
* which will be interpreted as an empty statement by some compilers
|
||||
* (MSVC) -- which will then error out at any further variable
|
||||
* declarations.
|
||||
/* Note n trailing semicolon on the above macro; if it's there, then
|
||||
* the typical usage of YV12_SETUP(pict); will have an extra trailing ;
|
||||
* that some compilers will interpret as a statement -- and then any further
|
||||
* variable declarations will cause an error.
|
||||
*/
|
||||
|
||||
#define YV12_Y(line) \
|
||||
|
|
|
@ -1387,6 +1387,249 @@ pixman_image_composite_rect (pixman_op_t op,
|
|||
free (scanline_buffer);
|
||||
}
|
||||
|
||||
/* These "formats" both have depth 0, so they
|
||||
* will never clash with any real ones
|
||||
*/
|
||||
#define PIXMAN_null PIXMAN_FORMAT(0,0,0,0,0,0)
|
||||
#define PIXMAN_solid PIXMAN_FORMAT(0,1,0,0,0,0)
|
||||
|
||||
#define NEED_COMPONENT_ALPHA (1 << 0)
|
||||
#define NEED_PIXBUF (1 << 1)
|
||||
#define NEED_SOLID_MASK (1 << 2)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pixman_op_t op;
|
||||
pixman_format_code_t src_format;
|
||||
pixman_format_code_t mask_format;
|
||||
pixman_format_code_t dest_format;
|
||||
CompositeFunc func;
|
||||
uint32_t flags;
|
||||
} FastPathInfo;
|
||||
|
||||
#ifdef USE_MMX
|
||||
static const FastPathInfo mmx_fast_paths[] =
|
||||
{
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r5g6b5, fbCompositeSolidMask_nx8x0565mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b5g6r5, fbCompositeSolidMask_nx8x0565mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8888x8888Cmmx, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8888x8888Cmmx, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_r5g6b5, fbCompositeSolidMask_nx8888x0565Cmmx, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8888x8888Cmmx, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8888x8888Cmmx, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_b5g6r5, fbCompositeSolidMask_nx8888x0565Cmmx, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8r8g8b8, PIXMAN_a8r8g8b8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8b8g8r8, PIXMAN_a8r8g8b8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8r8g8b8, PIXMAN_x8r8g8b8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8b8g8r8, PIXMAN_x8r8g8b8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8r8g8b8, PIXMAN_r5g6b5, fbCompositeSrc_8888RevNPx0565mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8b8g8r8, PIXMAN_r5g6b5, fbCompositeSrc_8888RevNPx0565mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8r8g8b8, PIXMAN_a8b8g8r8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8b8g8r8, PIXMAN_a8b8g8r8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8r8g8b8, PIXMAN_x8b8g8r8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8b8g8r8, PIXMAN_x8b8g8r8, fbCompositeSrc_8888RevNPx8888mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8r8g8b8, PIXMAN_b5g6r5, fbCompositeSrc_8888RevNPx0565mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8b8g8r8, PIXMAN_b5g6r5, fbCompositeSrc_8888RevNPx0565mmx, NEED_PIXBUF },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSrc_x888xnx8888mmx, NEED_SOLID_MASK },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSrc_x888xnx8888mmx, NEED_SOLID_MASK },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSrc_x888xnx8888mmx, NEED_SOLID_MASK },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSrc_x888xnx8888mmx, NEED_SOLID_MASK },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSrc_8888x8x8888mmx, NEED_SOLID_MASK },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSrc_8888x8x8888mmx, NEED_SOLID_MASK },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSrc_8888x8x8888mmx, NEED_SOLID_MASK },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSrc_8888x8x8888mmx, NEED_SOLID_MASK },
|
||||
#if 0
|
||||
/* FIXME: This code is commented out since it's apparently not actually faster than the generic code. */
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeOver_x888x8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeOver_x888x8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeOver_x888x8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeOver_x888x8x8888mmx, 0 },
|
||||
#endif
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSolid_nx8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSolid_nx8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSolid_nx0565mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeCopyAreammx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeCopyAreammx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrc_8888x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrc_8888x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSrc_8888x0565mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrc_8888x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrc_8888x8888mmx, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, fbCompositeSrc_8888x0565mmx, 0 },
|
||||
|
||||
{ PIXMAN_OP_ADD, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrcAdd_8888x8888mmx, 0 },
|
||||
{ PIXMAN_OP_ADD, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrcAdd_8888x8888mmx, 0 },
|
||||
{ PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fbCompositeSrcAdd_8000x8000mmx, 0 },
|
||||
{ PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fbCompositeSrcAdd_8888x8x8mmx, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSolidMaskSrc_nx8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSolidMaskSrc_nx8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSolidMaskSrc_nx8x8888mmx, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSolidMaskSrc_nx8x8888mmx, 0 },
|
||||
|
||||
{ PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeCopyAreammx, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeCopyAreammx, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeCopyAreammx, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeCopyAreammx, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_r5g6b5, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeCopyAreammx, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_b5g6r5, PIXMAN_null, PIXMAN_b5g6r5, fbCompositeCopyAreammx, 0 },
|
||||
{ PIXMAN_OP_IN, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fbCompositeIn_8x8mmx, 0 },
|
||||
{ PIXMAN_OP_IN, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fbCompositeIn_nx8x8mmx, 0 },
|
||||
{ PIXMAN_OP_NONE },
|
||||
};
|
||||
#endif
|
||||
|
||||
static const FastPathInfo c_fast_paths[] =
|
||||
{
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r5g6b5, fbCompositeSolidMask_nx8x0565, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b5g6r5, fbCompositeSolidMask_nx8x0565, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_r8g8b8, fbCompositeSolidMask_nx8x0888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_b8g8r8, fbCompositeSolidMask_nx8x0888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8r8g8b8, PIXMAN_r5g6b5, fbCompositeSolidMask_nx8888x0565C, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a8b8g8r8, PIXMAN_b5g6r5, fbCompositeSolidMask_nx8888x0565C, NEED_COMPONENT_ALPHA },
|
||||
#if 0
|
||||
/* FIXME: This code is commented out since it's apparently not actually faster than the generic code */
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_x8r8g8b8, fbCompositeOver_x888x8x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeOver_x888x8x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_x8b8g8r8, fbCompositeOver_x888x8x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_x8b8r8g8, PIXMAN_a8, PIXMAN_a8r8g8b8, fbCompositeOver_x888x8x8888, 0 },
|
||||
#endif
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrc_8888x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrc_8888x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSrc_8888x0565, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrc_8888x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrc_8888x8888, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_b5g6r5, fbCompositeSrc_8888x0565, 0 },
|
||||
#if 0
|
||||
/* FIXME */
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_r5g6b5, fbCompositeSolidMask_nx1xn, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_b5g6r5, fbCompositeSolidMask_nx1xn, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_r8g8b8, fbCompositeSolidMask_nx1xn, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_b8g8r8, fbCompositeSolidMask_nx1xn, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx1xn, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx1xn, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx1xn, 0 },
|
||||
{ PIXMAN_OP_OVER, PIXMAN_solid, PIXMAN_a1, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx1xn, 0 },
|
||||
#endif
|
||||
{ PIXMAN_OP_ADD, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrcAdd_8888x8888, 0 },
|
||||
{ PIXMAN_OP_ADD, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrcAdd_8888x8888, 0 },
|
||||
{ PIXMAN_OP_ADD, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fbCompositeSrcAdd_8000x8000, 0 },
|
||||
#if 0
|
||||
/* FIXME */
|
||||
{ PIXMAN_OP_ADD, PIXMAN_a1, PIXMAN_null, PIXMAN_a1, fbCompositeSrcAdd_1000x1000, 0 },
|
||||
#endif
|
||||
{ PIXMAN_OP_ADD, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fbCompositeSrcAdd_8888x8x8, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSolidFill, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSolidFill, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSolidFill, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSolidFill, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_a8, fbCompositeSolidFill, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_solid, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSolidFill, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrc_8888xx888, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrc_8888xx888, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrc_8888xx888, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrc_8888xx888, 0 },
|
||||
#if 0
|
||||
/* FIXME */
|
||||
{ PIXMAN_OP_SRC, PIXMAN_a8r8g8b8, PIXMAN_null, PIXMAN_a8r8g8b8, fbCompositeSrcSrc_nxn, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_a8b8g8r8, PIXMAN_null, PIXMAN_a8b8g8r8, fbCompositeSrcSrc_nxn, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_x8r8g8b8, PIXMAN_null, PIXMAN_x8r8g8b8, fbCompositeSrcSrc_nxn, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_x8b8g8r8, PIXMAN_null, PIXMAN_x8b8g8r8, fbCompositeSrcSrc_nxn, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_r5g6b5, PIXMAN_null, PIXMAN_r5g6b5, fbCompositeSrcSrc_nxn, 0 },
|
||||
{ PIXMAN_OP_SRC, PIXMAN_b5g6r5, PIXMAN_null, PIXMAN_b5g6r5, fbCompositeSrcSrc_nxn, 0 },
|
||||
#endif
|
||||
{ PIXMAN_OP_IN, PIXMAN_a8, PIXMAN_null, PIXMAN_a8, fbCompositeSrcIn_8x8, 0 },
|
||||
{ PIXMAN_OP_IN, PIXMAN_solid, PIXMAN_a8, PIXMAN_a8, fbCompositeSolidMaskIn_nx8x8, 0 },
|
||||
{ PIXMAN_OP_NONE },
|
||||
};
|
||||
|
||||
static pixman_bool_t
|
||||
mask_is_solid (pixman_image_t *mask)
|
||||
{
|
||||
if (mask->type == SOLID)
|
||||
return TRUE;
|
||||
|
||||
if (mask->type == BITS &&
|
||||
mask->common.repeat == PIXMAN_REPEAT_NORMAL &&
|
||||
mask->bits.width == 1 &&
|
||||
mask->bits.height == 1)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const FastPathInfo *
|
||||
get_fast_path (const FastPathInfo *fast_paths,
|
||||
pixman_op_t op,
|
||||
pixman_image_t *pSrc,
|
||||
pixman_image_t *pMask,
|
||||
pixman_image_t *pDst,
|
||||
pixman_bool_t is_pixbuf)
|
||||
{
|
||||
const FastPathInfo *info;
|
||||
|
||||
for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++)
|
||||
{
|
||||
pixman_bool_t valid_src = FALSE;
|
||||
pixman_bool_t valid_mask = FALSE;
|
||||
|
||||
if (info->op != op)
|
||||
continue;
|
||||
|
||||
if ((info->src_format == PIXMAN_solid && can_get_solid (pSrc)) ||
|
||||
(pSrc->type == BITS && info->src_format == pSrc->bits.format))
|
||||
{
|
||||
valid_src = TRUE;
|
||||
}
|
||||
|
||||
if (!valid_src)
|
||||
continue;
|
||||
|
||||
if ((info->mask_format == PIXMAN_null && !pMask) ||
|
||||
(pMask && pMask->type == BITS && info->mask_format == pMask->bits.format))
|
||||
{
|
||||
valid_mask = TRUE;
|
||||
|
||||
if (info->flags & NEED_SOLID_MASK)
|
||||
{
|
||||
if (!pMask || !mask_is_solid (pMask))
|
||||
valid_mask = FALSE;
|
||||
}
|
||||
|
||||
if (info->flags & NEED_COMPONENT_ALPHA)
|
||||
{
|
||||
if (!pMask || !pMask->common.component_alpha)
|
||||
valid_mask = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid_mask)
|
||||
continue;
|
||||
|
||||
if (info->dest_format != pDst->bits.format)
|
||||
continue;
|
||||
|
||||
if ((info->flags & NEED_PIXBUF) && !is_pixbuf)
|
||||
continue;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pixman_image_composite (pixman_op_t op,
|
||||
|
@ -1449,573 +1692,42 @@ pixman_image_composite (pixman_op_t op,
|
|||
&& !pSrc->common.read_func && !pSrc->common.write_func
|
||||
&& !(pMask && pMask->common.read_func) && !(pMask && pMask->common.write_func)
|
||||
&& !pDst->common.read_func && !pDst->common.write_func)
|
||||
switch (op) {
|
||||
case PIXMAN_OP_OVER:
|
||||
if (pMask)
|
||||
{
|
||||
if (can_get_solid(pSrc) &&
|
||||
!maskRepeat)
|
||||
{
|
||||
if (pSrc->type == SOLID || PIXMAN_FORMAT_COLOR(pSrc->bits.format)) {
|
||||
switch (pMask->bits.format) {
|
||||
case PIXMAN_a8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_r5g6b5:
|
||||
case PIXMAN_b5g6r5:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSolidMask_nx8x0565mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSolidMask_nx8x0565;
|
||||
break;
|
||||
case PIXMAN_r8g8b8:
|
||||
case PIXMAN_b8g8r8:
|
||||
func = fbCompositeSolidMask_nx8x0888;
|
||||
break;
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
case PIXMAN_a8b8g8r8:
|
||||
case PIXMAN_x8b8g8r8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSolidMask_nx8x8888mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSolidMask_nx8x8888;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PIXMAN_a8r8g8b8:
|
||||
if (pMask->common.component_alpha) {
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSolidMask_nx8888x8888Cmmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSolidMask_nx8888x8888C;
|
||||
break;
|
||||
case PIXMAN_r5g6b5:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSolidMask_nx8888x0565Cmmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSolidMask_nx8888x0565C;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIXMAN_a8b8g8r8:
|
||||
if (pMask->common.component_alpha) {
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8b8g8r8:
|
||||
case PIXMAN_x8b8g8r8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSolidMask_nx8888x8888Cmmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSolidMask_nx8888x8888C;
|
||||
break;
|
||||
case PIXMAN_b5g6r5:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSolidMask_nx8888x0565Cmmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSolidMask_nx8888x0565C;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIXMAN_a1:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_r5g6b5:
|
||||
case PIXMAN_b5g6r5:
|
||||
case PIXMAN_r8g8b8:
|
||||
case PIXMAN_b8g8r8:
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
case PIXMAN_a8b8g8r8:
|
||||
case PIXMAN_x8b8g8r8:
|
||||
{
|
||||
uint32_t src;
|
||||
{
|
||||
const FastPathInfo *info;
|
||||
pixman_bool_t pixbuf;
|
||||
|
||||
#if 0
|
||||
/* FIXME */
|
||||
fbComposeGetSolid(pSrc, src, pDst->bits.format);
|
||||
if ((src & 0xff000000) == 0xff000000)
|
||||
func = fbCompositeSolidMask_nx1xn;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (func)
|
||||
srcRepeat = FALSE;
|
||||
}
|
||||
else if (!srcRepeat) /* has mask and non-repeating source */
|
||||
{
|
||||
if (pSrc->bits.bits == pMask->bits.bits &&
|
||||
xSrc == xMask &&
|
||||
ySrc == yMask &&
|
||||
!pMask->common.component_alpha && !maskRepeat)
|
||||
{
|
||||
/* source == mask: non-premultiplied data */
|
||||
switch (pSrc->bits.format) {
|
||||
case PIXMAN_x8b8g8r8:
|
||||
switch (pMask->bits.format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_a8b8g8r8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888RevNPx8888mmx;
|
||||
#endif
|
||||
break;
|
||||
case PIXMAN_r5g6b5:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888RevNPx0565mmx;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PIXMAN_x8r8g8b8:
|
||||
switch (pMask->bits.format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_a8b8g8r8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8b8g8r8:
|
||||
case PIXMAN_x8b8g8r8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888RevNPx8888mmx;
|
||||
#endif
|
||||
break;
|
||||
case PIXMAN_r5g6b5:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888RevNPx0565mmx;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (maskRepeat &&
|
||||
pMask->bits.width == 1 &&
|
||||
pMask->bits.height == 1)
|
||||
{
|
||||
switch (pSrc->bits.format) {
|
||||
#ifdef USE_MMX
|
||||
case PIXMAN_x8r8g8b8:
|
||||
if ((pDst->bits.format == PIXMAN_a8r8g8b8 ||
|
||||
pDst->bits.format == PIXMAN_x8r8g8b8) &&
|
||||
pMask->bits.format == PIXMAN_a8 && pixman_have_mmx())
|
||||
func = fbCompositeSrc_x888xnx8888mmx;
|
||||
break;
|
||||
case PIXMAN_x8b8g8r8:
|
||||
if ((pDst->bits.format == PIXMAN_a8b8g8r8 ||
|
||||
pDst->bits.format == PIXMAN_x8b8g8r8) &&
|
||||
pMask->bits.format == PIXMAN_a8 && pixman_have_mmx())
|
||||
func = fbCompositeSrc_x888xnx8888mmx;
|
||||
break;
|
||||
case PIXMAN_a8r8g8b8:
|
||||
if ((pDst->bits.format == PIXMAN_a8r8g8b8 ||
|
||||
pDst->bits.format == PIXMAN_x8r8g8b8) &&
|
||||
pMask->bits.format == PIXMAN_a8 && pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888x8x8888mmx;
|
||||
break;
|
||||
case PIXMAN_a8b8g8r8:
|
||||
if ((pDst->bits.format == PIXMAN_a8b8g8r8 ||
|
||||
pDst->bits.format == PIXMAN_x8b8g8r8) &&
|
||||
pMask->bits.format == PIXMAN_a8 && pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888x8x8888mmx;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pixbuf =
|
||||
pSrc && pSrc->type == BITS &&
|
||||
pMask && pMask->type == BITS &&
|
||||
pSrc->bits.bits == pMask->bits.bits &&
|
||||
xSrc == xMask &&
|
||||
ySrc == yMask &&
|
||||
!pMask->common.component_alpha &&
|
||||
!maskRepeat;
|
||||
|
||||
if (func)
|
||||
maskRepeat = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
/* FIXME: This code is commented out since it's apparently not
|
||||
* actually faster than the generic code.
|
||||
*/
|
||||
if (pMask->bits.format == PIXMAN_a8)
|
||||
{
|
||||
if ((pSrc->bits.format == PIXMAN_x8r8g8b8 &&
|
||||
(pDst->bits.format == PIXMAN_x8r8g8b8 ||
|
||||
pDst->bits.format == PIXMAN_a8r8g8b8)) ||
|
||||
(pSrc->bits.format == PIXMAN_x8b8g8r8 &&
|
||||
(pDst->bits.format == PIXMAN_x8b8g8r8 ||
|
||||
pDst->bits.format == PIXMAN_a8b8g8r8)))
|
||||
{
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeOver_x888x8x8888mmx;
|
||||
else
|
||||
info = NULL;
|
||||
if (pixman_have_mmx())
|
||||
info = get_fast_path (mmx_fast_paths, op, pSrc, pMask, pDst, pixbuf);
|
||||
if (!info)
|
||||
#endif
|
||||
func = fbCompositeOver_x888x8x8888;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* no mask */
|
||||
info = get_fast_path (c_fast_paths, op, pSrc, pMask, pDst, pixbuf);
|
||||
|
||||
if (info)
|
||||
{
|
||||
if (can_get_solid(pSrc))
|
||||
{
|
||||
/* no mask and repeating source */
|
||||
if (pSrc->type == SOLID || pSrc->bits.format == PIXMAN_a8r8g8b8)
|
||||
{
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
{
|
||||
srcRepeat = FALSE;
|
||||
func = fbCompositeSolid_nx8888mmx;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case PIXMAN_r5g6b5:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
{
|
||||
srcRepeat = FALSE;
|
||||
func = fbCompositeSolid_nx0565mmx;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (! srcRepeat)
|
||||
{
|
||||
/*
|
||||
* Formats without alpha bits are just Copy with Over
|
||||
*/
|
||||
if (pSrc->bits.format == pDst->bits.format && !PIXMAN_FORMAT_A(pSrc->bits.format))
|
||||
{
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx() &&
|
||||
(pSrc->bits.format == PIXMAN_x8r8g8b8 || pSrc->bits.format == PIXMAN_x8b8g8r8))
|
||||
func = fbCompositeCopyAreammx;
|
||||
else
|
||||
#endif
|
||||
#if 0
|
||||
/* FIXME */
|
||||
func = fbCompositeSrcSrc_nxn
|
||||
#endif
|
||||
;
|
||||
}
|
||||
else switch (pSrc->bits.format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888x8888mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSrc_8888x8888;
|
||||
break;
|
||||
case PIXMAN_r8g8b8:
|
||||
func = fbCompositeSrc_8888x0888;
|
||||
break;
|
||||
case PIXMAN_r5g6b5:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888x0565mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSrc_8888x0565;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PIXMAN_x8r8g8b8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_x8r8g8b8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeCopyAreammx;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case PIXMAN_x8b8g8r8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_x8b8g8r8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeCopyAreammx;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PIXMAN_a8b8g8r8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8b8g8r8:
|
||||
case PIXMAN_x8b8g8r8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888x8888mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSrc_8888x8888;
|
||||
break;
|
||||
case PIXMAN_b8g8r8:
|
||||
func = fbCompositeSrc_8888x0888;
|
||||
break;
|
||||
case PIXMAN_b5g6r5:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrc_8888x0565mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSrc_8888x0565;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIXMAN_OP_ADD:
|
||||
if (pMask == 0)
|
||||
{
|
||||
switch (pSrc->bits.format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8r8g8b8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrcAdd_8888x8888mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSrcAdd_8888x8888;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PIXMAN_a8b8g8r8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8b8g8r8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrcAdd_8888x8888mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSrcAdd_8888x8888;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PIXMAN_a8:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a8:
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrcAdd_8000x8000mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSrcAdd_8000x8000;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PIXMAN_a1:
|
||||
switch (pDst->bits.format) {
|
||||
case PIXMAN_a1:
|
||||
#if 0
|
||||
/* FIXME */
|
||||
func = fbCompositeSrcAdd_1000x1000;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (can_get_solid (pSrc) &&
|
||||
pMask->bits.format == PIXMAN_a8 &&
|
||||
pDst->bits.format == PIXMAN_a8)
|
||||
{
|
||||
func = info->func;
|
||||
|
||||
if (info->src_format == PIXMAN_solid)
|
||||
srcRepeat = FALSE;
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeSrcAdd_8888x8x8mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSrcAdd_8888x8x8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIXMAN_OP_SRC:
|
||||
if (pMask)
|
||||
{
|
||||
#ifdef USE_MMX
|
||||
if (can_get_solid (pSrc))
|
||||
{
|
||||
if (pMask->bits.format == PIXMAN_a8)
|
||||
{
|
||||
switch (pDst->bits.format)
|
||||
{
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
case PIXMAN_a8b8g8r8:
|
||||
case PIXMAN_x8b8g8r8:
|
||||
if (pixman_have_mmx())
|
||||
{
|
||||
srcRepeat = FALSE;
|
||||
func = fbCompositeSolidMaskSrc_nx8x8888mmx;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (can_get_solid (pSrc))
|
||||
{
|
||||
switch (pDst->bits.format)
|
||||
{
|
||||
case PIXMAN_a8r8g8b8:
|
||||
case PIXMAN_x8r8g8b8:
|
||||
case PIXMAN_a8b8g8r8:
|
||||
case PIXMAN_x8b8g8r8:
|
||||
case PIXMAN_a8:
|
||||
case PIXMAN_r5g6b5:
|
||||
func = fbCompositeSolidFill;
|
||||
srcRepeat = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pSrc->bits.format == pDst->bits.format)
|
||||
{
|
||||
#ifdef USE_MMX
|
||||
if (pSrc->bits.bits != pDst->bits.bits && pixman_have_mmx() &&
|
||||
(PIXMAN_FORMAT_BPP (pSrc->bits.format) == 16 ||
|
||||
PIXMAN_FORMAT_BPP (pSrc->bits.format) == 32))
|
||||
func = fbCompositeCopyAreammx;
|
||||
else
|
||||
#endif
|
||||
/* FIXME */
|
||||
#if 0
|
||||
func = fbCompositeSrcSrc_nxn
|
||||
#endif
|
||||
;
|
||||
}
|
||||
else if (((pSrc->bits.format == PIXMAN_a8r8g8b8 ||
|
||||
pSrc->bits.format == PIXMAN_x8r8g8b8) &&
|
||||
pDst->bits.format == PIXMAN_x8r8g8b8) ||
|
||||
((pSrc->bits.format == PIXMAN_a8b8g8r8 ||
|
||||
pSrc->bits.format == PIXMAN_x8b8g8r8) &&
|
||||
pDst->bits.format == PIXMAN_x8b8g8r8))
|
||||
{
|
||||
func = fbCompositeSrc_8888xx888;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIXMAN_OP_IN:
|
||||
if (pSrc->bits.format == PIXMAN_a8 &&
|
||||
pDst->bits.format == PIXMAN_a8 &&
|
||||
!pMask)
|
||||
{
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeIn_8x8mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSrcIn_8x8;
|
||||
}
|
||||
else if (srcRepeat && pMask && !pMask->common.component_alpha &&
|
||||
(pSrc->bits.format == PIXMAN_a8r8g8b8 ||
|
||||
pSrc->bits.format == PIXMAN_a8b8g8r8) &&
|
||||
(pMask->bits.format == PIXMAN_a8) &&
|
||||
pDst->bits.format == PIXMAN_a8)
|
||||
{
|
||||
#ifdef USE_MMX
|
||||
if (pixman_have_mmx())
|
||||
func = fbCompositeIn_nx8x8mmx;
|
||||
else
|
||||
#endif
|
||||
func = fbCompositeSolidMaskIn_nx8x8;
|
||||
srcRepeat = FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (info->mask_format == PIXMAN_solid ||
|
||||
info->flags & NEED_SOLID_MASK)
|
||||
{
|
||||
maskRepeat = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((srcRepeat &&
|
||||
pSrc->bits.width == 1 &&
|
||||
pSrc->bits.height == 1) ||
|
||||
|
@ -2034,7 +1746,8 @@ pixman_image_composite (pixman_op_t op,
|
|||
func = NULL;
|
||||
}
|
||||
|
||||
if (!func) {
|
||||
if (!func)
|
||||
{
|
||||
func = pixman_image_composite_rect;
|
||||
|
||||
/* CompositeGeneral optimizes 1x1 repeating images itself */
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#ifndef PIXMAN_PRIVATE_H
|
||||
#define PIXMAN_PRIVATE_H
|
||||
|
||||
#include "cairo-platform.h"
|
||||
|
||||
#include "pixman.h"
|
||||
#include <time.h>
|
||||
|
||||
|
|
|
@ -90,6 +90,13 @@ typedef unsigned __int64 uint64_t;
|
|||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* GCC visibility */
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define PIXMAN_EXPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define PIXMAN_EXPORT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Boolean
|
||||
*/
|
||||
|
@ -221,7 +228,9 @@ typedef enum
|
|||
PIXMAN_OP_CONJOINT_OUT_REVERSE = 0x28,
|
||||
PIXMAN_OP_CONJOINT_ATOP = 0x29,
|
||||
PIXMAN_OP_CONJOINT_ATOP_REVERSE = 0x2a,
|
||||
PIXMAN_OP_CONJOINT_XOR = 0x2b
|
||||
PIXMAN_OP_CONJOINT_XOR = 0x2b,
|
||||
|
||||
PIXMAN_OP_NONE
|
||||
} pixman_op_t;
|
||||
|
||||
/*
|
||||
|
@ -265,62 +274,85 @@ typedef enum
|
|||
/* This function exists only to make it possible to preserve the X ABI - it should
|
||||
* go away at first opportunity.
|
||||
*/
|
||||
PIXMAN_EXPORT
|
||||
void pixman_region_set_static_pointers (pixman_box16_t *empty_box,
|
||||
pixman_region16_data_t *empty_data,
|
||||
pixman_region16_data_t *broken_data);
|
||||
|
||||
/* creation/destruction */
|
||||
PIXMAN_EXPORT
|
||||
void pixman_region_init (pixman_region16_t *region);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_region_init_rect (pixman_region16_t *region,
|
||||
int x,
|
||||
int y,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_region_init_with_extents (pixman_region16_t *region,
|
||||
pixman_box16_t *extents);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_region_fini (pixman_region16_t *region);
|
||||
|
||||
/* manipulation */
|
||||
PIXMAN_EXPORT
|
||||
void pixman_region_translate (pixman_region16_t *region,
|
||||
int x,
|
||||
int y);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_copy (pixman_region16_t *dest,
|
||||
pixman_region16_t *source);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_intersect (pixman_region16_t *newReg,
|
||||
pixman_region16_t *reg1,
|
||||
pixman_region16_t *reg2);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_union (pixman_region16_t *newReg,
|
||||
pixman_region16_t *reg1,
|
||||
pixman_region16_t *reg2);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_union_rect (pixman_region16_t *dest,
|
||||
pixman_region16_t *source,
|
||||
int x,
|
||||
int y,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_subtract (pixman_region16_t *regD,
|
||||
pixman_region16_t *regM,
|
||||
pixman_region16_t *regS);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_inverse (pixman_region16_t *newReg,
|
||||
pixman_region16_t *reg1,
|
||||
pixman_box16_t *invRect);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_contains_point (pixman_region16_t *region,
|
||||
int x, int y, pixman_box16_t *box);
|
||||
PIXMAN_EXPORT
|
||||
pixman_region_overlap_t pixman_region_contains_rectangle (pixman_region16_t *pixman_region16_t,
|
||||
pixman_box16_t *prect);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_not_empty (pixman_region16_t *region);
|
||||
PIXMAN_EXPORT
|
||||
pixman_box16_t * pixman_region_extents (pixman_region16_t *region);
|
||||
PIXMAN_EXPORT
|
||||
int pixman_region_n_rects (pixman_region16_t *region);
|
||||
PIXMAN_EXPORT
|
||||
pixman_box16_t * pixman_region_rectangles (pixman_region16_t *region,
|
||||
int *n_rects);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_equal (pixman_region16_t *region1,
|
||||
pixman_region16_t *region2);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_selfcheck (pixman_region16_t *region);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_region_reset (pixman_region16_t *region, pixman_box16_t *box);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_region_init_rects (pixman_region16_t *region,
|
||||
pixman_box16_t *boxes, int count);
|
||||
|
||||
/* Copy / Fill */
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_blt (uint32_t *src_bits,
|
||||
uint32_t *dst_bits,
|
||||
int src_stride,
|
||||
|
@ -330,6 +362,7 @@ pixman_bool_t pixman_blt (uint32_t *src_bits,
|
|||
int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
int width, int height);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_fill (uint32_t *bits,
|
||||
int stride,
|
||||
int bpp,
|
||||
|
@ -458,25 +491,30 @@ typedef enum {
|
|||
|
||||
/* YUV formats */
|
||||
PIXMAN_yuy2 = PIXMAN_FORMAT(16,PIXMAN_TYPE_YUY2,0,0,0,0),
|
||||
PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0)
|
||||
PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0),
|
||||
} pixman_format_code_t;
|
||||
|
||||
/* Constructors */
|
||||
PIXMAN_EXPORT
|
||||
pixman_image_t *pixman_image_create_solid_fill (pixman_color_t *color);
|
||||
PIXMAN_EXPORT
|
||||
pixman_image_t *pixman_image_create_linear_gradient (pixman_point_fixed_t *p1,
|
||||
pixman_point_fixed_t *p2,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops);
|
||||
PIXMAN_EXPORT
|
||||
pixman_image_t *pixman_image_create_radial_gradient (pixman_point_fixed_t *inner,
|
||||
pixman_point_fixed_t *outer,
|
||||
pixman_fixed_t inner_radius,
|
||||
pixman_fixed_t outer_radius,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops);
|
||||
PIXMAN_EXPORT
|
||||
pixman_image_t *pixman_image_create_conical_gradient (pixman_point_fixed_t *center,
|
||||
pixman_fixed_t angle,
|
||||
const pixman_gradient_stop_t *stops,
|
||||
int n_stops);
|
||||
PIXMAN_EXPORT
|
||||
pixman_image_t *pixman_image_create_bits (pixman_format_code_t format,
|
||||
int width,
|
||||
int height,
|
||||
|
@ -484,44 +522,63 @@ pixman_image_t *pixman_image_create_bits (pixman_format_code_t
|
|||
int rowstride_bytes);
|
||||
|
||||
/* Destructor */
|
||||
PIXMAN_EXPORT
|
||||
pixman_image_t *pixman_image_ref (pixman_image_t *image);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_image_unref (pixman_image_t *image);
|
||||
|
||||
|
||||
/* Set properties */
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_image_set_clip_region (pixman_image_t *image,
|
||||
pixman_region16_t *region);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_image_set_has_client_clip (pixman_image_t *image,
|
||||
pixman_bool_t clien_clip);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_image_set_transform (pixman_image_t *image,
|
||||
const pixman_transform_t *transform);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_image_set_repeat (pixman_image_t *image,
|
||||
pixman_repeat_t repeat);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_image_set_filter (pixman_image_t *image,
|
||||
pixman_filter_t filter,
|
||||
const pixman_fixed_t *filter_params,
|
||||
int n_filter_params);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_image_set_filter_params (pixman_image_t *image,
|
||||
pixman_fixed_t *params,
|
||||
int n_params);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_image_set_source_clipping (pixman_image_t *image,
|
||||
pixman_bool_t source_clipping);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_image_set_alpha_map (pixman_image_t *image,
|
||||
pixman_image_t *alpha_map,
|
||||
int16_t x,
|
||||
int16_t y);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_image_set_component_alpha (pixman_image_t *image,
|
||||
pixman_bool_t component_alpha);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_image_set_accessors (pixman_image_t *image,
|
||||
pixman_read_memory_func_t read_func,
|
||||
pixman_write_memory_func_t write_func);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_image_set_indexed (pixman_image_t *image,
|
||||
const pixman_indexed_t *indexed);
|
||||
PIXMAN_EXPORT
|
||||
uint32_t *pixman_image_get_data (pixman_image_t *image);
|
||||
PIXMAN_EXPORT
|
||||
int pixman_image_get_width (pixman_image_t *image);
|
||||
PIXMAN_EXPORT
|
||||
int pixman_image_get_height (pixman_image_t *image);
|
||||
PIXMAN_EXPORT
|
||||
int pixman_image_get_stride (pixman_image_t *image);
|
||||
PIXMAN_EXPORT
|
||||
int pixman_image_get_depth (pixman_image_t *image);
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op,
|
||||
pixman_image_t *image,
|
||||
pixman_color_t *color,
|
||||
|
@ -529,6 +586,7 @@ pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op,
|
|||
const pixman_rectangle16_t *rects);
|
||||
|
||||
/* Composite */
|
||||
PIXMAN_EXPORT
|
||||
pixman_bool_t pixman_compute_composite_region (pixman_region16_t * pRegion,
|
||||
pixman_image_t * pSrc,
|
||||
pixman_image_t * pMask,
|
||||
|
@ -541,6 +599,7 @@ pixman_bool_t pixman_compute_composite_region (pixman_region16_t * pRegion,
|
|||
int16_t yDst,
|
||||
uint16_t width,
|
||||
uint16_t height);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_image_composite (pixman_op_t op,
|
||||
pixman_image_t *src,
|
||||
pixman_image_t *mask,
|
||||
|
@ -605,12 +664,16 @@ struct pixman_trap
|
|||
pixman_span_fix_t top, bot;
|
||||
};
|
||||
|
||||
PIXMAN_EXPORT
|
||||
pixman_fixed_t pixman_sample_ceil_y (pixman_fixed_t y,
|
||||
int bpp);
|
||||
PIXMAN_EXPORT
|
||||
pixman_fixed_t pixman_sample_floor_y (pixman_fixed_t y,
|
||||
int bpp);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_edge_step (pixman_edge_t *e,
|
||||
int n);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_edge_init (pixman_edge_t *e,
|
||||
int bpp,
|
||||
pixman_fixed_t y_start,
|
||||
|
@ -618,31 +681,35 @@ void pixman_edge_init (pixman_edge_t *e,
|
|||
pixman_fixed_t y_top,
|
||||
pixman_fixed_t x_bot,
|
||||
pixman_fixed_t y_bot);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_line_fixed_edge_init (pixman_edge_t *e,
|
||||
int bpp,
|
||||
pixman_fixed_t y,
|
||||
const pixman_line_fixed_t *line,
|
||||
int x_off,
|
||||
int y_off);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_rasterize_edges (pixman_image_t *image,
|
||||
pixman_edge_t *l,
|
||||
pixman_edge_t *r,
|
||||
pixman_fixed_t t,
|
||||
pixman_fixed_t b);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_add_traps (pixman_image_t *image,
|
||||
int16_t x_off,
|
||||
int16_t y_off,
|
||||
int ntrap,
|
||||
pixman_trap_t *traps);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_add_trapezoids (pixman_image_t *image,
|
||||
int16_t x_off,
|
||||
int y_off,
|
||||
int ntraps,
|
||||
const pixman_trapezoid_t *traps);
|
||||
PIXMAN_EXPORT
|
||||
void pixman_rasterize_trapezoid (pixman_image_t *image,
|
||||
const pixman_trapezoid_t *trap,
|
||||
int x_off,
|
||||
int y_off);
|
||||
|
||||
|
||||
#endif /* PIXMAN_H__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче