b=411224, r=vlad: 411224-cairo-upgrade-1.5.5

This commit is contained in:
vladimir%pobox.com 2008-01-18 21:46:27 +00:00
Родитель 7e9c4c2a2c
Коммит 37c1190c3f
65 изменённых файлов: 4585 добавлений и 3432 удалений

Просмотреть файл

@ -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__ */