зеркало из https://github.com/mozilla/pjs.git
b=383960: Upgrade cairo to 1.4.10: Cairo 1.4.10
This commit is contained in:
Родитель
4f1e29c742
Коммит
7f76b858fe
|
@ -6968,6 +6968,7 @@ if test "$MOZ_SVG" -o "$MOZ_ENABLE_CANVAS" -o "$MOZ_ENABLE_CAIRO_GFX" ; then
|
|||
# Define macros for cairo-features.h
|
||||
if test "$MOZ_X11"; then
|
||||
XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
|
||||
XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1"
|
||||
PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
|
||||
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
|
||||
FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
|
||||
|
@ -7014,6 +7015,7 @@ if test "$MOZ_SVG" -o "$MOZ_ENABLE_CANVAS" -o "$MOZ_ENABLE_CAIRO_GFX" ; then
|
|||
AC_SUBST(PDF_SURFACE_FEATURE)
|
||||
AC_SUBST(SVG_SURFACE_FEATURE)
|
||||
AC_SUBST(XLIB_SURFACE_FEATURE)
|
||||
AC_SUBST(XLIB_XRENDER_SURFACE_FEATURE)
|
||||
AC_SUBST(QUARTZ_SURFACE_FEATURE)
|
||||
AC_SUBST(NQUARTZ_SURFACE_FEATURE)
|
||||
AC_SUBST(XCB_SURFACE_FEATURE)
|
||||
|
|
|
@ -7,7 +7,7 @@ http://www.cairographics.org/.
|
|||
|
||||
VERSIONS:
|
||||
|
||||
cairo (1.4.2)
|
||||
cairo (1.4.10)
|
||||
glitz 0.5.2 (cvs - 2006-01-10)
|
||||
|
||||
***** NOTE FOR VISUAL C++ 6.0 *****
|
||||
|
@ -16,8 +16,6 @@ VC6 is not supported. Please upgrade to VC8.
|
|||
|
||||
==== Patches ====
|
||||
|
||||
All patches in the cairo tree are surrounded by "MOZILLA_CAIRO_NOT_DEFINED" (which should NOT be defined).
|
||||
|
||||
Some specific things:
|
||||
|
||||
max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues
|
||||
|
|
|
@ -70,7 +70,7 @@ CSRCS = \
|
|||
cairo-debug.c \
|
||||
cairo-deflate-stream.c \
|
||||
cairo-fixed.c \
|
||||
cairo-font.c \
|
||||
cairo-font-face.c \
|
||||
cairo-font-options.c \
|
||||
cairo-freelist.c \
|
||||
cairo-gstate.c \
|
||||
|
@ -80,6 +80,7 @@ CSRCS = \
|
|||
cairo-lzw.c \
|
||||
cairo-matrix.c \
|
||||
cairo-meta-surface.c \
|
||||
cairo-mutex.c \
|
||||
cairo-operator.c \
|
||||
cairo-output-stream.c \
|
||||
cairo-paginated-surface.c \
|
||||
|
@ -154,7 +155,8 @@ endif
|
|||
|
||||
ifdef MOZ_X11
|
||||
CSRCS += cairo-xlib-surface.c \
|
||||
cairo-xlib-screen.c
|
||||
cairo-xlib-screen.c \
|
||||
cairo-xlib-display.c
|
||||
EXPORTS += cairo-xlib.h cairo-xlib-xrender.h
|
||||
endif
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* $Id: cairo-analysis-surface-private.h,v 1.6 2007/06/11 00:01:29 vladimir%pobox.com Exp $
|
||||
*
|
||||
/*
|
||||
* Copyright © 2005 Keith Packard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
#include "cairo-paginated-surface-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
|
||||
typedef struct {
|
||||
cairo_surface_t base;
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-arc-private.h"
|
||||
|
||||
/* Spline deviation from the circle in radius would be given by:
|
||||
|
@ -85,7 +87,7 @@ _arc_max_angle_for_tolerance_normalized (double tolerance)
|
|||
{ M_PI / 10.0, 1.73863223499021216974e-08 },
|
||||
{ M_PI / 11.0, 9.81410988043554039085e-09 },
|
||||
};
|
||||
int table_size = (sizeof (table) / sizeof (table[0]));
|
||||
int table_size = ARRAY_LENGTH (table);
|
||||
|
||||
for (i = 0; i < table_size; i++)
|
||||
if (table[i].error < tolerance)
|
||||
|
|
|
@ -34,11 +34,10 @@
|
|||
* Calum Robinson <calumr@mac.com>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "cairo-atsui.h"
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo.h"
|
||||
#include "cairo-atsui.h"
|
||||
#include "cairo-quartz-private.h"
|
||||
|
||||
/*
|
||||
|
@ -117,8 +116,7 @@ _cairo_atsui_font_face_scaled_font_create (void *abstract_face,
|
|||
ATSUStyle style;
|
||||
|
||||
err = ATSUCreateStyle (&style);
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(styleTags) / sizeof(styleTags[0]),
|
||||
err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
|
||||
styleTags, styleSizes, styleValues);
|
||||
|
||||
return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
|
||||
|
@ -131,6 +129,19 @@ static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
|
|||
_cairo_atsui_font_face_scaled_font_create
|
||||
};
|
||||
|
||||
/**
|
||||
* cairo_atsui_font_face_create_for_atsu_font_id
|
||||
* @font_id: an ATSUFontID for the font.
|
||||
*
|
||||
* Creates a new font for the ATSUI font backend based on an
|
||||
* #ATSUFontID. This font can then be used with
|
||||
* cairo_set_font_face() or cairo_scaled_font_create().
|
||||
*
|
||||
* Return value: a newly created #cairo_font_face_t. Free with
|
||||
* cairo_font_face_destroy() when you are done using it.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
cairo_font_face_t *
|
||||
cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
|
||||
{
|
||||
|
@ -149,14 +160,6 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
|
|||
return &font_face->base;
|
||||
}
|
||||
|
||||
static CGAffineTransform
|
||||
CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale)
|
||||
{
|
||||
return CGAffineTransformMake(scale->xx, scale->yx,
|
||||
scale->xy, scale->yy,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
static ATSUStyle
|
||||
CreateSizedCopyOfStyle(ATSUStyle inStyle,
|
||||
const Fixed *theSize,
|
||||
|
@ -232,8 +235,13 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
|
|||
if (font == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
_cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
|
||||
&cairo_atsui_scaled_font_backend);
|
||||
status = _cairo_scaled_font_init (&font->base,
|
||||
font_face, font_matrix, ctm, options,
|
||||
&cairo_atsui_scaled_font_backend);
|
||||
if (status) {
|
||||
free (font);
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_matrix_compute_scale_factors (&font->base.scale,
|
||||
&xscale, &yscale, 1);
|
||||
|
@ -374,8 +382,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
|||
ByteCount styleSizes[] =
|
||||
{ sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
|
||||
|
||||
err = ATSUSetAttributes(style,
|
||||
sizeof(styleTags) / sizeof(styleTags[0]),
|
||||
err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
|
||||
styleTags, styleSizes, styleValues);
|
||||
}
|
||||
|
||||
|
@ -397,50 +404,6 @@ _cairo_atsui_font_fini(void *abstract_font)
|
|||
ATSUDisposeStyle(font->unscaled_style);
|
||||
}
|
||||
|
||||
static
|
||||
OSStatus _move_to_for_metrics (const Float32Point *point, void *callback_data)
|
||||
{
|
||||
CGMutablePathRef path = callback_data;
|
||||
|
||||
CGPathMoveToPoint (path, &CGAffineTransformIdentity,
|
||||
point->x, point->y);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static
|
||||
OSStatus _line_to_for_metrics(const Float32Point *point, void *callback_data)
|
||||
{
|
||||
CGMutablePathRef path = callback_data;
|
||||
|
||||
CGPathAddLineToPoint (path, &CGAffineTransformIdentity,
|
||||
point->x, point->y);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static
|
||||
OSStatus _curve_to_for_metrics (const Float32Point *point1,
|
||||
const Float32Point *point2,
|
||||
const Float32Point *point3,
|
||||
void *callback_data)
|
||||
{
|
||||
CGMutablePathRef path = callback_data;
|
||||
|
||||
CGPathAddCurveToPoint (path, &CGAffineTransformIdentity,
|
||||
point1->x, point1->y,
|
||||
point2->x, point2->y,
|
||||
point3->x, point3->y);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static
|
||||
OSStatus _close_path_for_metrics(void *callback_data)
|
||||
{
|
||||
CGMutablePathRef path = callback_data;
|
||||
|
||||
CGPathCloseSubpath (path);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static GlyphID
|
||||
_cairo_atsui_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
|
||||
unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
|
||||
|
@ -454,16 +417,10 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
|
|||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
|
||||
OSStatus err, callback_err;
|
||||
OSStatus err;
|
||||
ATSGlyphScreenMetrics metricsH;
|
||||
static ATSCubicMoveToUPP moveProc = NULL;
|
||||
static ATSCubicLineToUPP lineProc = NULL;
|
||||
static ATSCubicCurveToUPP curveProc = NULL;
|
||||
static ATSCubicClosePathUPP closePathProc = NULL;
|
||||
CGMutablePathRef path;
|
||||
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
|
||||
double xscale, yscale;
|
||||
CGRect rect;
|
||||
|
||||
if (theGlyph == kATSDeletedGlyphcode) {
|
||||
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
||||
|
@ -489,41 +446,15 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
|
|||
|
||||
extents.x_advance = metricsH.deviceAdvance.x * xscale;
|
||||
extents.y_advance = 0;
|
||||
|
||||
if (moveProc == NULL) {
|
||||
moveProc = NewATSCubicMoveToUPP (_move_to_for_metrics);
|
||||
lineProc = NewATSCubicLineToUPP (_line_to_for_metrics);
|
||||
curveProc = NewATSCubicCurveToUPP (_curve_to_for_metrics);
|
||||
closePathProc = NewATSCubicClosePathUPP (_close_path_for_metrics);
|
||||
}
|
||||
|
||||
path = CGPathCreateMutable ();
|
||||
|
||||
/* The callback error contains any error our functions returned.
|
||||
* Its only meaningful if err != noErr, and we don't currently
|
||||
* use it for anything.
|
||||
*/
|
||||
err = ATSUGlyphGetCubicPaths (scaled_font->style, theGlyph,
|
||||
moveProc, lineProc, curveProc, closePathProc,
|
||||
(void *)path, &callback_err);
|
||||
|
||||
if (err != noErr) {
|
||||
CGPathRelease (path);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
rect = CGPathGetBoundingBox (path);
|
||||
|
||||
extents.x_bearing = rect.origin.x * xscale;
|
||||
extents.y_bearing = rect.origin.y * yscale;
|
||||
extents.width = rect.size.width * xscale;
|
||||
extents.height = rect.size.height * yscale;
|
||||
|
||||
extents.x_bearing = metricsH.topLeft.x * xscale;
|
||||
extents.y_bearing = -metricsH.topLeft.y * yscale;
|
||||
extents.width = metricsH.width * xscale;
|
||||
extents.height = metricsH.height * yscale;
|
||||
|
||||
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
&extents);
|
||||
CGPathRelease (path);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -667,6 +598,7 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
|
|||
CGContextRef drawingContext;
|
||||
cairo_image_surface_t *surface;
|
||||
cairo_format_t format;
|
||||
cairo_status_t status;
|
||||
|
||||
ATSFontRef atsFont;
|
||||
CGFontRef cgFont;
|
||||
|
@ -683,8 +615,10 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
|
|||
|
||||
if (theGlyph == kATSDeletedGlyphcode) {
|
||||
surface = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
|
||||
if (!surface)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
status = cairo_surface_status ((cairo_surface_t *)surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_scaled_glyph_set_surface (scaled_glyph,
|
||||
&base,
|
||||
surface);
|
||||
|
@ -692,19 +626,25 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
|
|||
}
|
||||
|
||||
/* Compute a box to contain the glyph mask. The vertical
|
||||
* sizes come from the font extents; extra pixels are
|
||||
* sizes come from the font extents; extra pixels are
|
||||
* added to account for fractional sizes.
|
||||
*/
|
||||
height = extents.ascent + extents.descent + 2.0;
|
||||
bottom = -extents.descent - 1.0;
|
||||
|
||||
_cairo_matrix_compute_scale_factors (&base.scale,
|
||||
&xscale, &yscale, 1);
|
||||
bbox = CGRectApplyAffineTransform (CGRectMake (1.0, bottom, 1.0, height), CGAffineTransformMakeScale(xscale, yscale));
|
||||
bottom = CGRectGetMinY (bbox);
|
||||
height = bbox.size.height;
|
||||
|
||||
/* Horizontal sizes come from the glyph typographic metrics.
|
||||
* It is possible that this might result in clipped text
|
||||
* in fonts where the typographic bounds don't cover the ink.
|
||||
* The width is recalculated, since metricsH.width is rounded.
|
||||
*/
|
||||
err = ATSUGlyphGetScreenMetrics (scaled_font->style,
|
||||
1, &theGlyph, 0, false,
|
||||
1, &theGlyph, 0, false,
|
||||
false, &metricsH);
|
||||
left = metricsH.sideBearing.x - 1.0;
|
||||
width = metricsH.deviceAdvance.x
|
||||
|
@ -743,8 +683,9 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
|
|||
|
||||
/* create the glyph mask surface */
|
||||
surface = (cairo_image_surface_t *)cairo_image_surface_create (format, bbox.size.width, bbox.size.height);
|
||||
if (!surface)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
status = cairo_surface_status ((cairo_surface_t *)surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Create a CGBitmapContext for the dest surface for drawing into */
|
||||
{
|
||||
|
|
|
@ -115,7 +115,7 @@ _cairo_base85_stream_create (cairo_output_stream_t *output)
|
|||
|
||||
stream = malloc (sizeof (cairo_base85_stream_t));
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
|
||||
_cairo_output_stream_init (&stream->base,
|
||||
_cairo_base85_stream_write,
|
||||
|
|
|
@ -137,6 +137,7 @@ typedef struct _cairo_bo_sweep_line {
|
|||
int32_t current_y;
|
||||
} cairo_bo_sweep_line_t;
|
||||
|
||||
|
||||
static inline int
|
||||
_cairo_bo_point32_compare (cairo_bo_point32_t const *a,
|
||||
cairo_bo_point32_t const *b)
|
||||
|
@ -692,13 +693,16 @@ _cairo_bo_event_init (cairo_bo_event_t *event,
|
|||
event->point = point;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
|
||||
cairo_bo_event_t *event)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
/* Don't insert if there's already an equivalent intersection event in the queue. */
|
||||
_cairo_skip_list_insert (&queue->intersection_queue, event,
|
||||
event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION);
|
||||
if (_cairo_skip_list_insert (&queue->intersection_queue, event,
|
||||
event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) == NULL)
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -750,16 +754,14 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
|
|||
* or stop events, so this allocation is safe. XXX: make the
|
||||
* event type a union so it doesn't always contain the skip
|
||||
* elt? */
|
||||
events = malloc (num_events * sizeof(cairo_bo_event_t));
|
||||
sorted_event_ptrs = malloc (num_events * sizeof(cairo_bo_event_t*));
|
||||
if (!events || !sorted_event_ptrs) {
|
||||
if (events) free(events);
|
||||
if (sorted_event_ptrs) free(sorted_event_ptrs);
|
||||
events = malloc (num_events * (sizeof (cairo_bo_event_t) + sizeof(cairo_bo_event_t*)));
|
||||
if (events == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
sorted_event_ptrs = (cairo_bo_event_t **) (events + num_events);
|
||||
event_queue->startstop_events = events;
|
||||
event_queue->sorted_startstop_event_ptrs = sorted_event_ptrs;
|
||||
event_queue->num_startstop_events = (unsigned)(num_events);
|
||||
event_queue->num_startstop_events = num_events;
|
||||
event_queue->next_startstop_event_index = 0;
|
||||
|
||||
for (i = 0; i < num_edges; i++) {
|
||||
|
@ -792,11 +794,9 @@ _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
|
|||
_cairo_skip_list_fini (&event_queue->intersection_queue);
|
||||
if (event_queue->startstop_events)
|
||||
free (event_queue->startstop_events);
|
||||
if (event_queue->sorted_startstop_event_ptrs)
|
||||
free (event_queue->sorted_startstop_event_ptrs);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t *event_queue,
|
||||
cairo_bo_edge_t *left,
|
||||
cairo_bo_edge_t *right)
|
||||
|
@ -806,7 +806,7 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
|
|||
cairo_bo_event_t event;
|
||||
|
||||
if (left == NULL || right == NULL)
|
||||
return;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* The names "left" and "right" here are correct descriptions of
|
||||
* the order of the two edges within the active edge list. So if a
|
||||
|
@ -814,13 +814,13 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
|
|||
* that the intersection of these two segments has oalready
|
||||
* occurred before the current sweep line position. */
|
||||
if (_slope_compare (left, right) < 0)
|
||||
return;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_bo_edge_intersect (left, right, &intersection);
|
||||
if (status == CAIRO_BO_STATUS_PARALLEL ||
|
||||
status == CAIRO_BO_STATUS_NO_INTERSECTION)
|
||||
{
|
||||
return;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_bo_event_init (&event,
|
||||
|
@ -828,7 +828,7 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
|
|||
left, right,
|
||||
intersection);
|
||||
|
||||
_cairo_bo_event_queue_insert (event_queue, &event);
|
||||
return _cairo_bo_event_queue_insert (event_queue, &event);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -848,7 +848,7 @@ _cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
|
|||
_cairo_skip_list_fini (&sweep_line->active_edges);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
|
||||
cairo_bo_edge_t *edge)
|
||||
{
|
||||
|
@ -858,6 +858,8 @@ _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
|
|||
|
||||
sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge,
|
||||
1 /* unique inserts*/);
|
||||
if (sweep_line_elt == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
next_elt = sweep_line_elt->elt.next[0];
|
||||
if (next_elt)
|
||||
|
@ -876,6 +878,8 @@ _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
|
|||
*next_of_prev = edge;
|
||||
|
||||
edge->sweep_line_elt = sweep_line_elt;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1057,7 +1061,6 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
|
|||
cairo_bo_traps_t *bo_traps)
|
||||
{
|
||||
cairo_fixed_t fixed_top, fixed_bot;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_bo_trap_t *trap = left->deferred_trap;
|
||||
cairo_bo_edge_t *right;
|
||||
|
||||
|
@ -1099,11 +1102,11 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
|
|||
left_bot.x != right_bot.x ||
|
||||
left_bot.y != right_bot.y)
|
||||
{
|
||||
status = _cairo_traps_add_trap_from_points (bo_traps->traps,
|
||||
fixed_top,
|
||||
fixed_bot,
|
||||
left_top, left_bot,
|
||||
right_top, right_bot);
|
||||
_cairo_traps_add_trap_from_points (bo_traps->traps,
|
||||
fixed_top,
|
||||
fixed_bot,
|
||||
left_top, left_bot,
|
||||
right_top, right_bot);
|
||||
|
||||
#if DEBUG_PRINT_STATE
|
||||
printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) "
|
||||
|
@ -1117,7 +1120,8 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
|
|||
|
||||
_cairo_freelist_free (&bo_traps->freelist, trap);
|
||||
left->deferred_trap = NULL;
|
||||
return status;
|
||||
|
||||
return _cairo_traps_status (bo_traps->traps);
|
||||
}
|
||||
|
||||
/* Start a new trapezoid at the given top y coordinate, whose edges
|
||||
|
@ -1254,7 +1258,7 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
|||
cairo_fixed_t ymax,
|
||||
int *num_intersections)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_status_t status;
|
||||
int intersection_count = 0;
|
||||
cairo_bo_event_queue_t event_queue;
|
||||
cairo_bo_sweep_line_t sweep_line;
|
||||
|
@ -1264,7 +1268,10 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
|||
cairo_bo_edge_t *left, *right;
|
||||
cairo_bo_edge_t *edge1, *edge2;
|
||||
|
||||
_cairo_bo_event_queue_init (&event_queue, edges, num_edges);
|
||||
status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_bo_sweep_line_init (&sweep_line);
|
||||
_cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
|
||||
|
||||
|
@ -1296,7 +1303,9 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
|||
case CAIRO_BO_EVENT_TYPE_START:
|
||||
edge = event->e1;
|
||||
|
||||
_cairo_bo_sweep_line_insert (&sweep_line, edge);
|
||||
status = _cairo_bo_sweep_line_insert (&sweep_line, edge);
|
||||
if (status)
|
||||
goto unwind;
|
||||
/* Cache the insert position for use in pass 2.
|
||||
event->e2 = Sortlist::prev (sweep_line, edge);
|
||||
*/
|
||||
|
@ -1304,9 +1313,13 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
|||
left = edge->prev;
|
||||
right = edge->next;
|
||||
|
||||
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge);
|
||||
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge);
|
||||
if (status)
|
||||
goto unwind;
|
||||
|
||||
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
|
||||
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
|
||||
if (status)
|
||||
goto unwind;
|
||||
|
||||
#if DEBUG_PRINT_STATE
|
||||
print_state ("After processing start", &event_queue, &sweep_line);
|
||||
|
@ -1326,7 +1339,9 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
|||
if (status)
|
||||
goto unwind;
|
||||
|
||||
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
|
||||
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
|
||||
if (status)
|
||||
goto unwind;
|
||||
|
||||
#if DEBUG_PRINT_STATE
|
||||
print_state ("After processing stop", &event_queue, &sweep_line);
|
||||
|
@ -1354,11 +1369,15 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
|
|||
|
||||
/* after the swap e2 is left of e1 */
|
||||
|
||||
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
|
||||
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
|
||||
left, edge2);
|
||||
if (status)
|
||||
goto unwind;
|
||||
|
||||
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
|
||||
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
|
||||
edge1, right);
|
||||
if (status)
|
||||
goto unwind;
|
||||
|
||||
#if DEBUG_PRINT_STATE
|
||||
print_state ("After processing intersection", &event_queue, &sweep_line);
|
||||
|
@ -1402,6 +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 *edges;
|
||||
cairo_fixed_t xmin = 0x7FFFFFFF;
|
||||
cairo_fixed_t ymin = 0x7FFFFFFF;
|
||||
|
@ -1413,9 +1433,13 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
|
|||
if (0 == polygon->num_edges)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
edges = malloc (polygon->num_edges * sizeof (cairo_bo_edge_t));
|
||||
if (edges == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
|
||||
edges = stack_edges;
|
||||
} else {
|
||||
edges = malloc (polygon->num_edges * sizeof (cairo_bo_edge_t));
|
||||
if (edges == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Figure out the bounding box of the input coordinates and
|
||||
* validate that we're not given invalid polygon edges. */
|
||||
|
@ -1495,7 +1519,8 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
|
|||
xmin, ymin, xmax, ymax,
|
||||
&intersections);
|
||||
|
||||
free (edges);
|
||||
if (edges != stack_edges)
|
||||
free (edges);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -1771,7 +1796,7 @@ main (void)
|
|||
unsigned int i, num_random;
|
||||
test_t *test;
|
||||
|
||||
for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i++) {
|
||||
for (i = 0; i < ARRAY_LENGTH (tests); i++) {
|
||||
test = &tests[i];
|
||||
run_test (test->name, test->edges, test->num_edges);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#ifndef CAIRO_CACHE_PRIVATE_H
|
||||
#define CAIRO_CACHE_PRIVATE_H
|
||||
|
||||
typedef struct _cairo_cache cairo_cache_t;
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
/**
|
||||
* cairo_cache_entry_t:
|
||||
|
|
|
@ -38,17 +38,6 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
struct _cairo_cache {
|
||||
cairo_hash_table_t *hash_table;
|
||||
|
||||
cairo_destroy_func_t entry_destroy;
|
||||
|
||||
unsigned long max_size;
|
||||
unsigned long size;
|
||||
|
||||
int freeze_count;
|
||||
};
|
||||
|
||||
static void
|
||||
_cairo_cache_remove (cairo_cache_t *cache,
|
||||
cairo_cache_entry_t *entry);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -38,7 +38,7 @@
|
|||
|
||||
#include "cairo-path-fixed-private.h"
|
||||
|
||||
extern cairo_private const cairo_rectangle_list_t _cairo_rectangles_nil;
|
||||
extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
|
||||
|
||||
struct _cairo_clip_path {
|
||||
unsigned int ref_count;
|
||||
|
@ -72,7 +72,8 @@ struct _cairo_clip {
|
|||
/*
|
||||
* A clip region that can be placed in the surface
|
||||
*/
|
||||
pixman_region16_t *region;
|
||||
pixman_region16_t region;
|
||||
cairo_bool_t has_region;
|
||||
/*
|
||||
* If the surface supports path clipping, we store the list of
|
||||
* clipping paths that has been set here as a linked list.
|
||||
|
@ -83,18 +84,15 @@ struct _cairo_clip {
|
|||
cairo_private void
|
||||
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target);
|
||||
|
||||
cairo_private void
|
||||
_cairo_clip_fini (cairo_clip_t *clip);
|
||||
|
||||
cairo_private void
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
|
||||
|
||||
cairo_private void
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
|
||||
cairo_clip_t *other,
|
||||
cairo_surface_t *target);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_private void
|
||||
_cairo_clip_reset (cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
|
|
|
@ -61,28 +61,13 @@ _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
|
|||
|
||||
clip->serial = 0;
|
||||
|
||||
clip->region = NULL;
|
||||
pixman_region_init (&clip->region);
|
||||
clip->has_region = FALSE;
|
||||
|
||||
clip->path = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_clip_fini (cairo_clip_t *clip)
|
||||
{
|
||||
cairo_surface_destroy (clip->surface);
|
||||
clip->surface = NULL;
|
||||
|
||||
clip->serial = 0;
|
||||
|
||||
if (clip->region)
|
||||
pixman_region_destroy (clip->region);
|
||||
clip->region = NULL;
|
||||
|
||||
_cairo_clip_path_destroy (clip->path);
|
||||
clip->path = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
cairo_status_t
|
||||
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
|
||||
{
|
||||
clip->mode = other->mode;
|
||||
|
@ -92,17 +77,26 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
|
|||
|
||||
clip->serial = other->serial;
|
||||
|
||||
if (other->region == NULL) {
|
||||
clip->region = other->region;
|
||||
pixman_region_init (&clip->region);
|
||||
|
||||
if (other->has_region) {
|
||||
if (pixman_region_copy (&clip->region, &other->region) !=
|
||||
PIXMAN_REGION_STATUS_SUCCESS) {
|
||||
pixman_region_fini (&clip->region);
|
||||
cairo_surface_destroy (clip->surface);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
clip->has_region = TRUE;
|
||||
} else {
|
||||
clip->region = pixman_region_create ();
|
||||
pixman_region_copy (clip->region, other->region);
|
||||
clip->has_region = FALSE;
|
||||
}
|
||||
|
||||
clip->path = _cairo_clip_path_reference (other->path);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_clip_reset (cairo_clip_t *clip)
|
||||
{
|
||||
/* destroy any existing clip-region artifacts */
|
||||
|
@ -111,14 +105,18 @@ _cairo_clip_reset (cairo_clip_t *clip)
|
|||
|
||||
clip->serial = 0;
|
||||
|
||||
if (clip->region)
|
||||
pixman_region_destroy (clip->region);
|
||||
clip->region = NULL;
|
||||
if (clip->has_region) {
|
||||
/* pixman_region_fini just releases the resources used but
|
||||
* doesn't bother with leaving the region in a valid state.
|
||||
* So pixman_region_init has to be called afterwards. */
|
||||
pixman_region_fini (&clip->region);
|
||||
pixman_region_init (&clip->region);
|
||||
|
||||
clip->has_region = FALSE;
|
||||
}
|
||||
|
||||
_cairo_clip_path_destroy (clip->path);
|
||||
clip->path = NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -170,27 +168,26 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
|
|||
return status;
|
||||
}
|
||||
|
||||
if (clip->region) {
|
||||
pixman_region16_t *intersection;
|
||||
if (clip->has_region) {
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
pixman_region_status_t pixman_status;
|
||||
pixman_region16_t intersection;
|
||||
|
||||
intersection = _cairo_region_create_from_rectangle (rectangle);
|
||||
if (intersection == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
pixman_region_init_rect (&intersection,
|
||||
rectangle->x, rectangle->y,
|
||||
rectangle->width, rectangle->height);
|
||||
|
||||
pixman_status = pixman_region_intersect (intersection,
|
||||
clip->region,
|
||||
intersection);
|
||||
if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS)
|
||||
_cairo_region_extents_rectangle (intersection, rectangle);
|
||||
else
|
||||
if (PIXMAN_REGION_STATUS_SUCCESS !=
|
||||
pixman_region_intersect (&intersection, &clip->region,
|
||||
&intersection)) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
} else {
|
||||
_cairo_region_extents_rectangle (&intersection, rectangle);
|
||||
}
|
||||
|
||||
pixman_region_destroy (intersection);
|
||||
pixman_region_fini (&intersection);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (clip->surface)
|
||||
|
@ -203,6 +200,8 @@ cairo_status_t
|
|||
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
|
||||
pixman_region16_t *region)
|
||||
{
|
||||
pixman_region_status_t pixman_status;
|
||||
|
||||
if (!clip)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -210,28 +209,28 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
|
|||
/* Intersect clip path into region. */
|
||||
}
|
||||
|
||||
if (clip->region)
|
||||
pixman_region_intersect (region, clip->region, region);
|
||||
if (clip->has_region) {
|
||||
pixman_status = pixman_region_intersect (region, &clip->region, region);
|
||||
if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (clip->surface) {
|
||||
pixman_region16_t *clip_rect;
|
||||
pixman_region_status_t pixman_status;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
pixman_region16_t clip_rect;
|
||||
|
||||
clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
|
||||
if (clip_rect == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
pixman_region_init_rect (&clip_rect,
|
||||
clip->surface_rect.x, clip->surface_rect.y,
|
||||
clip->surface_rect.width, clip->surface_rect.height);
|
||||
|
||||
pixman_status = pixman_region_intersect (region,
|
||||
clip_rect,
|
||||
region);
|
||||
if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
|
||||
if (PIXMAN_REGION_STATUS_SUCCESS !=
|
||||
pixman_region_intersect (region, &clip_rect, region))
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
pixman_region_destroy (clip_rect);
|
||||
pixman_region_fini (&clip_rect);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -329,42 +328,47 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
|
|||
free (clip_path);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
static cairo_int_status_t
|
||||
_cairo_clip_intersect_region (cairo_clip_t *clip,
|
||||
cairo_traps_t *traps,
|
||||
cairo_surface_t *target)
|
||||
{
|
||||
pixman_region16_t *region;
|
||||
cairo_status_t status;
|
||||
pixman_region16_t region;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (clip->mode != CAIRO_CLIP_MODE_REGION)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_traps_extract_region (traps, ®ion);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (region == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
if (clip->region == NULL) {
|
||||
clip->region = region;
|
||||
} else {
|
||||
pixman_region16_t *intersection = pixman_region_create();
|
||||
|
||||
if (pixman_region_intersect (intersection,
|
||||
clip->region, region)
|
||||
== PIXMAN_REGION_STATUS_SUCCESS) {
|
||||
pixman_region_destroy (clip->region);
|
||||
clip->region = intersection;
|
||||
} else {
|
||||
if (!clip->has_region) {
|
||||
if (pixman_region_copy (&clip->region, ®ion) ==
|
||||
PIXMAN_REGION_STATUS_SUCCESS)
|
||||
clip->has_region = TRUE;
|
||||
else
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
pixman_region_destroy (region);
|
||||
} else {
|
||||
pixman_region16_t intersection;
|
||||
pixman_region_init (&intersection);
|
||||
|
||||
if (PIXMAN_REGION_STATUS_SUCCESS !=
|
||||
pixman_region_intersect (&intersection,
|
||||
&clip->region,
|
||||
®ion) ||
|
||||
PIXMAN_REGION_STATUS_SUCCESS !=
|
||||
pixman_region_copy (&clip->region, &intersection))
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
pixman_region_fini (&intersection);
|
||||
}
|
||||
|
||||
clip->serial = _cairo_surface_allocate_clip_serial (target);
|
||||
pixman_region_fini (®ion);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -402,14 +406,16 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
|
|||
CAIRO_CONTENT_ALPHA,
|
||||
surface_rect.width,
|
||||
surface_rect.height,
|
||||
CAIRO_COLOR_WHITE);
|
||||
CAIRO_COLOR_WHITE,
|
||||
NULL);
|
||||
if (surface->status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
/* Render the new clipping path into the new mask surface. */
|
||||
|
||||
_cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y);
|
||||
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
|
||||
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
|
||||
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
|
||||
&pattern.base,
|
||||
|
@ -509,8 +515,8 @@ _cairo_clip_translate (cairo_clip_t *clip,
|
|||
cairo_fixed_t tx,
|
||||
cairo_fixed_t ty)
|
||||
{
|
||||
if (clip->region) {
|
||||
pixman_region_translate (clip->region,
|
||||
if (clip->has_region) {
|
||||
pixman_region_translate (&clip->region,
|
||||
_cairo_fixed_integer_part (tx),
|
||||
_cairo_fixed_integer_part (ty));
|
||||
}
|
||||
|
@ -549,7 +555,7 @@ _cairo_clip_path_reapply_clip_path (cairo_clip_t *clip,
|
|||
clip_path->antialias);
|
||||
}
|
||||
|
||||
void
|
||||
cairo_status_t
|
||||
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
|
||||
cairo_clip_t *other,
|
||||
cairo_surface_t *target)
|
||||
|
@ -560,18 +566,22 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
|
|||
/* We should reapply the original clip path in this case, and let
|
||||
* whatever the right handling is happen */
|
||||
} else {
|
||||
if (other->region) {
|
||||
clip->region = pixman_region_create ();
|
||||
pixman_region_copy (clip->region, other->region);
|
||||
if (other->has_region) {
|
||||
if (pixman_region_copy (&clip->region, &other->region) !=
|
||||
PIXMAN_REGION_STATUS_SUCCESS)
|
||||
goto BAIL;
|
||||
clip->has_region = TRUE;
|
||||
}
|
||||
|
||||
if (other->surface) {
|
||||
_cairo_surface_clone_similar (target, other->surface,
|
||||
if (_cairo_surface_clone_similar (target, other->surface,
|
||||
other->surface_rect.x,
|
||||
other->surface_rect.y,
|
||||
other->surface_rect.width,
|
||||
other->surface_rect.height,
|
||||
&clip->surface);
|
||||
&clip->surface) !=
|
||||
CAIRO_STATUS_SUCCESS)
|
||||
goto BAIL;
|
||||
clip->surface_rect = other->surface_rect;
|
||||
}
|
||||
|
||||
|
@ -579,6 +589,16 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
|
|||
_cairo_clip_path_reapply_clip_path (clip, other->path);
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
BAIL:
|
||||
if (clip->has_region)
|
||||
pixman_region_fini (&clip->region);
|
||||
if (clip->surface)
|
||||
cairo_surface_destroy (clip->surface);
|
||||
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
const cairo_rectangle_list_t _cairo_rectangles_nil =
|
||||
|
@ -613,16 +633,16 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
|
|||
if (clip->path || clip->surface)
|
||||
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
|
||||
|
||||
n_boxes = clip->region ? pixman_region_num_rects (clip->region) : 1;
|
||||
n_boxes = clip->has_region ? pixman_region_num_rects (&clip->region) : 1;
|
||||
rectangles = malloc (sizeof (cairo_rectangle_t)*n_boxes);
|
||||
if (rectangles == NULL)
|
||||
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
|
||||
|
||||
if (clip->region) {
|
||||
if (clip->has_region) {
|
||||
pixman_box16_t *boxes;
|
||||
int i;
|
||||
|
||||
boxes = pixman_region_rects (clip->region);
|
||||
boxes = pixman_region_rects (&clip->region);
|
||||
for (i = 0; i < n_boxes; ++i) {
|
||||
if (!_cairo_clip_rect_to_user(gstate, boxes[i].x1, boxes[i].y1,
|
||||
boxes[i].x2 - boxes[i].x1,
|
||||
|
@ -635,10 +655,14 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
|
|||
}
|
||||
} else {
|
||||
cairo_rectangle_int16_t extents;
|
||||
_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents);
|
||||
if (!_cairo_clip_rect_to_user(gstate, extents.x, extents.y,
|
||||
extents.width, extents.height,
|
||||
rectangles)) {
|
||||
if (_cairo_surface_get_extents (_cairo_gstate_get_target (gstate),
|
||||
&extents) != CAIRO_STATUS_SUCCESS) {
|
||||
free (rectangles);
|
||||
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
|
||||
}
|
||||
if (! _cairo_clip_rect_to_user(gstate, extents.x, extents.y,
|
||||
extents.width, extents.height,
|
||||
rectangles)) {
|
||||
free (rectangles);
|
||||
return (cairo_rectangle_list_t*)
|
||||
&_cairo_rectangles_not_representable;
|
||||
|
|
|
@ -160,3 +160,13 @@ _cairo_color_get_rgba_premultiplied (cairo_color_t *color,
|
|||
*blue = color->blue * color->alpha;
|
||||
*alpha = color->alpha;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_color_equal (const cairo_color_t *color_a,
|
||||
const cairo_color_t *color_b)
|
||||
{
|
||||
return color_a->red_short == color_b->red_short &&
|
||||
color_a->green_short == color_b->green_short &&
|
||||
color_a->blue_short == color_b->blue_short &&
|
||||
color_a->alpha_short == color_b->alpha_short;
|
||||
}
|
||||
|
|
|
@ -59,13 +59,11 @@
|
|||
void
|
||||
cairo_debug_reset_static_data (void)
|
||||
{
|
||||
#if CAIRO_HAS_XLIB_SURFACE
|
||||
_cairo_xlib_screen_reset_static_data ();
|
||||
#endif
|
||||
|
||||
_cairo_font_reset_static_data ();
|
||||
|
||||
#if CAIRO_HAS_FT_FONT
|
||||
_cairo_ft_font_reset_static_data ();
|
||||
#endif
|
||||
|
||||
_cairo_pattern_reset_static_data ();
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output)
|
|||
|
||||
stream = malloc (sizeof (cairo_deflate_stream_t));
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
|
||||
_cairo_output_stream_init (&stream->base,
|
||||
_cairo_deflate_stream_write,
|
||||
|
@ -130,8 +130,10 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output)
|
|||
stream->zlib_stream.zfree = Z_NULL;
|
||||
stream->zlib_stream.opaque = Z_NULL;
|
||||
|
||||
if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK) {
|
||||
free (stream);
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
}
|
||||
|
||||
stream->zlib_stream.next_in = stream->input_buf;
|
||||
stream->zlib_stream.avail_in = 0;
|
||||
|
|
|
@ -35,10 +35,9 @@
|
|||
* Claudio Ciccani <klan@users.sf.net>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-directfb.h"
|
||||
|
||||
#include <directfb.h>
|
||||
|
||||
|
@ -47,9 +46,6 @@
|
|||
#include <direct/memcpy.h>
|
||||
#include <direct/util.h>
|
||||
|
||||
#include "cairo-directfb.h"
|
||||
#include "cairoint.h"
|
||||
|
||||
|
||||
/*
|
||||
* Rectangle causes problems (see bugs 361377, 359553, 359243 in Gnome BTS).
|
||||
|
@ -337,7 +333,7 @@ _directfb_acquire_surface (cairo_directfb_surface_t *surface,
|
|||
cairo_format_t cairo_format;
|
||||
cairo_format = surface->format;
|
||||
|
||||
if (surface->format == -1) {
|
||||
if (surface->format == (cairo_format_t) -1) {
|
||||
if( intrest_rec ) {
|
||||
source_rect.x = intrest_rec->x;
|
||||
source_rect.y = intrest_rec->y;
|
||||
|
@ -1515,6 +1511,17 @@ _cairo_directfb_surface_show_glyphs ( void *abstract_dst,
|
|||
#endif /* DFB_SHOW_GLYPHS */
|
||||
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_directfb_surface_is_similar (void *surface_a,
|
||||
void *surface_b,
|
||||
cairo_content_t content)
|
||||
{
|
||||
cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
|
||||
cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
|
||||
|
||||
return a->dfb == b->dfb;
|
||||
}
|
||||
|
||||
static cairo_surface_backend_t cairo_directfb_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/
|
||||
_cairo_directfb_surface_create_similar,/*create_similar*/
|
||||
|
@ -1564,7 +1571,9 @@ static cairo_surface_backend_t cairo_directfb_surface_backend = {
|
|||
#else
|
||||
NULL, /* show_glyphs */
|
||||
#endif
|
||||
NULL /* snapshot */
|
||||
NULL, /* snapshot */
|
||||
_cairo_directfb_surface_is_similar,
|
||||
NULL /* reset */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
#ifdef CAIRO_HAS_DIRECTFB_SURFACE
|
||||
|
||||
#include <directfb.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
|
|
|
@ -53,9 +53,9 @@
|
|||
|
||||
#define CAIRO_VERSION_MAJOR 1
|
||||
#define CAIRO_VERSION_MINOR 4
|
||||
#define CAIRO_VERSION_MICRO 2
|
||||
#define CAIRO_VERSION_MICRO 10
|
||||
|
||||
#define CAIRO_VERSION_STRING "1.4.2"
|
||||
#define CAIRO_VERSION_STRING "1.4.10"
|
||||
|
||||
@PS_SURFACE_FEATURE@
|
||||
|
||||
|
@ -65,6 +65,8 @@
|
|||
|
||||
@XLIB_SURFACE_FEATURE@
|
||||
|
||||
@XLIB_XRENDER_SURFACE_FEATURE@
|
||||
|
||||
@QUARTZ_SURFACE_FEATURE@
|
||||
|
||||
@XCB_SURFACE_FEATURE@
|
||||
|
|
|
@ -59,6 +59,8 @@ void
|
|||
_cairo_font_face_init (cairo_font_face_t *font_face,
|
||||
const cairo_font_face_backend_t *backend)
|
||||
{
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
font_face->status = CAIRO_STATUS_SUCCESS;
|
||||
font_face->ref_count = 1;
|
||||
font_face->backend = backend;
|
||||
|
@ -66,10 +68,6 @@ _cairo_font_face_init (cairo_font_face_t *font_face,
|
|||
_cairo_user_data_array_init (&font_face->user_data);
|
||||
}
|
||||
|
||||
/* This mutex protects both cairo_toy_font_hash_table as well as
|
||||
reference count manipulations for all cairo_font_face_t. */
|
||||
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex);
|
||||
|
||||
/**
|
||||
* cairo_font_face_reference:
|
||||
* @font_face: a #cairo_font_face_t, (may be %NULL in which case this
|
||||
|
@ -457,6 +455,11 @@ _cairo_toy_font_face_scaled_font_create (void *abstract_font_face
|
|||
{
|
||||
cairo_toy_font_face_t *font_face = abstract_font_face;
|
||||
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
|
||||
cairo_status_t status;
|
||||
|
||||
status = cairo_font_options_status ((cairo_font_options_t *) options);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return backend->create_toy (font_face,
|
||||
font_matrix, ctm, options, scaled_font);
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
static const cairo_font_options_t cairo_font_options_nil = {
|
||||
static const cairo_font_options_t _cairo_font_options_nil = {
|
||||
CAIRO_ANTIALIAS_DEFAULT,
|
||||
CAIRO_SUBPIXEL_ORDER_DEFAULT,
|
||||
CAIRO_HINT_STYLE_DEFAULT,
|
||||
|
@ -52,7 +52,7 @@ static const cairo_font_options_t cairo_font_options_nil = {
|
|||
void
|
||||
_cairo_font_options_init_default (cairo_font_options_t *options)
|
||||
{
|
||||
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
|
||||
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
|
||||
return;
|
||||
|
||||
options->antialias = CAIRO_ANTIALIAS_DEFAULT;
|
||||
|
@ -89,7 +89,7 @@ cairo_font_options_create (void)
|
|||
cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
|
||||
|
||||
if (!options)
|
||||
return (cairo_font_options_t *)&cairo_font_options_nil;
|
||||
return (cairo_font_options_t *)&_cairo_font_options_nil;
|
||||
|
||||
_cairo_font_options_init_default (options);
|
||||
|
||||
|
@ -113,10 +113,14 @@ slim_hidden_def (cairo_font_options_create);
|
|||
cairo_font_options_t *
|
||||
cairo_font_options_copy (const cairo_font_options_t *original)
|
||||
{
|
||||
cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
|
||||
cairo_font_options_t *options;
|
||||
|
||||
if (original == &_cairo_font_options_nil)
|
||||
return (cairo_font_options_t *)&_cairo_font_options_nil;
|
||||
|
||||
options = malloc (sizeof (cairo_font_options_t));
|
||||
if (!options)
|
||||
return (cairo_font_options_t *)&cairo_font_options_nil;
|
||||
return (cairo_font_options_t *)&_cairo_font_options_nil;
|
||||
|
||||
_cairo_font_options_init_copy (options, original);
|
||||
|
||||
|
@ -133,7 +137,7 @@ cairo_font_options_copy (const cairo_font_options_t *original)
|
|||
void
|
||||
cairo_font_options_destroy (cairo_font_options_t *options)
|
||||
{
|
||||
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
|
||||
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
|
||||
return;
|
||||
|
||||
free (options);
|
||||
|
@ -152,11 +156,12 @@ slim_hidden_def (cairo_font_options_destroy);
|
|||
cairo_status_t
|
||||
cairo_font_options_status (cairo_font_options_t *options)
|
||||
{
|
||||
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
|
||||
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
else
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
slim_hidden_def (cairo_font_options_status);
|
||||
|
||||
/**
|
||||
* cairo_font_options_merge:
|
||||
|
@ -172,7 +177,7 @@ void
|
|||
cairo_font_options_merge (cairo_font_options_t *options,
|
||||
const cairo_font_options_t *other)
|
||||
{
|
||||
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
|
||||
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
|
||||
return;
|
||||
|
||||
if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
|
||||
|
@ -240,7 +245,7 @@ void
|
|||
cairo_font_options_set_antialias (cairo_font_options_t *options,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
|
||||
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
|
||||
return;
|
||||
|
||||
options->antialias = antialias;
|
||||
|
@ -276,7 +281,7 @@ void
|
|||
cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
|
||||
cairo_subpixel_order_t subpixel_order)
|
||||
{
|
||||
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
|
||||
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
|
||||
return;
|
||||
|
||||
options->subpixel_order = subpixel_order;
|
||||
|
@ -312,7 +317,7 @@ void
|
|||
cairo_font_options_set_hint_style (cairo_font_options_t *options,
|
||||
cairo_hint_style_t hint_style)
|
||||
{
|
||||
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
|
||||
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
|
||||
return;
|
||||
|
||||
options->hint_style = hint_style;
|
||||
|
@ -348,7 +353,7 @@ void
|
|||
cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
|
||||
cairo_hint_metrics_t hint_metrics)
|
||||
{
|
||||
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
|
||||
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
|
||||
return;
|
||||
|
||||
options->hint_metrics = hint_metrics;
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#include <stddef.h>
|
||||
|
||||
/* Opaque implementation types. */
|
||||
struct _cairo_freelist;
|
||||
struct _cairo_freelist_node;
|
||||
typedef struct _cairo_freelist cairo_freelist_t;
|
||||
typedef struct _cairo_freelist_node cairo_freelist_node_t;
|
||||
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-freelist-private.h"
|
||||
|
||||
void
|
||||
|
|
|
@ -37,10 +37,12 @@
|
|||
* Carl Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-ft-private.h"
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
|
||||
|
@ -62,12 +64,6 @@
|
|||
*/
|
||||
#define MAX_OPEN_FACES 10
|
||||
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
/* This is the maximum font size we allow to be passed to FT_Set_Char_Size
|
||||
*/
|
||||
#define MAX_FONT_SIZE 1000
|
||||
#endif /* !MOZILLA_CAIRO_NOT_DEFINED */
|
||||
|
||||
/*
|
||||
* The simple 2x2 matrix is converted into separate scale and shape
|
||||
* factors so that hinting works right
|
||||
|
@ -156,8 +152,6 @@ typedef struct _cairo_ft_unscaled_font_map {
|
|||
|
||||
static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
|
||||
|
||||
CAIRO_MUTEX_DECLARE(_cairo_ft_unscaled_font_map_mutex);
|
||||
|
||||
static void
|
||||
_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
|
||||
cairo_ft_unscaled_font_t *unscaled)
|
||||
|
@ -261,6 +255,7 @@ _cairo_ft_unscaled_font_map_lock (void)
|
|||
|
||||
if (cairo_ft_unscaled_font_map == NULL) {
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -333,14 +328,16 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
|
|||
unscaled->face = NULL;
|
||||
|
||||
filename_copy = strdup (filename);
|
||||
if (filename_copy == NULL)
|
||||
if (filename_copy == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);
|
||||
}
|
||||
|
||||
unscaled->have_scale = FALSE;
|
||||
CAIRO_MUTEX_INIT (&unscaled->mutex);
|
||||
CAIRO_MUTEX_INIT (unscaled->mutex);
|
||||
unscaled->lock_count = 0;
|
||||
|
||||
unscaled->faces = NULL;
|
||||
|
@ -375,7 +372,7 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
|
|||
unscaled->filename = NULL;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_FINI (&unscaled->mutex);
|
||||
CAIRO_MUTEX_FINI (unscaled->mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -419,8 +416,8 @@ _cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
|
|||
if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
|
||||
(cairo_hash_entry_t **) &unscaled))
|
||||
{
|
||||
_cairo_ft_unscaled_font_map_unlock ();
|
||||
_cairo_unscaled_font_reference (&unscaled->base);
|
||||
_cairo_ft_unscaled_font_map_unlock ();
|
||||
return unscaled;
|
||||
}
|
||||
|
||||
|
@ -556,6 +553,7 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
|
|||
&face) != FT_Err_Ok)
|
||||
{
|
||||
CAIRO_MUTEX_UNLOCK (unscaled->mutex);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -614,7 +612,7 @@ _compute_transform (cairo_ft_font_transform_t *sf,
|
|||
/* Temporarily scales an unscaled font to the give scale. We catch
|
||||
* scaling to the same size, since changing a FT_Face is expensive.
|
||||
*/
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
|
||||
cairo_matrix_t *scale)
|
||||
{
|
||||
|
@ -629,7 +627,7 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
|
|||
scale->yx == unscaled->current_scale.yx &&
|
||||
scale->xy == unscaled->current_scale.xy &&
|
||||
scale->yy == unscaled->current_scale.yy)
|
||||
return;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
unscaled->have_scale = TRUE;
|
||||
unscaled->current_scale = *scale;
|
||||
|
@ -658,27 +656,14 @@ _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) {
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
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,
|
||||
sf.x_scale * 64.0,
|
||||
sf.y_scale * 64.0,
|
||||
0, 0);
|
||||
#else
|
||||
error = FT_Set_Char_Size (unscaled->face,
|
||||
x_scale * 64.0,
|
||||
y_scale * 64.0,
|
||||
0, 0);
|
||||
#endif /* MOZCAIRO */
|
||||
assert (error == 0);
|
||||
if (error) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
} else {
|
||||
double min_distance = DBL_MAX;
|
||||
int i;
|
||||
|
@ -707,8 +692,13 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
|
|||
error = FT_Set_Pixel_Sizes (unscaled->face,
|
||||
unscaled->face->available_sizes[best_i].width,
|
||||
unscaled->face->available_sizes[best_i].height);
|
||||
assert (error == 0);
|
||||
if (error) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Empirically-derived subpixel filtering values thanks to Keith
|
||||
|
@ -753,8 +743,10 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
|||
assert (stride == bitmap->pitch);
|
||||
} else {
|
||||
data = malloc (stride * height);
|
||||
if (!data)
|
||||
if (!data) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (stride == bitmap->pitch) {
|
||||
memcpy (data, bitmap->buffer, stride * height);
|
||||
|
@ -801,8 +793,10 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
|||
data = bitmap->buffer;
|
||||
} else {
|
||||
data = malloc (stride * height);
|
||||
if (!data)
|
||||
if (!data) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
memcpy (data, bitmap->buffer, stride * height);
|
||||
}
|
||||
format = CAIRO_FORMAT_A8;
|
||||
|
@ -841,6 +835,12 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
|||
stride = bitmap->pitch;
|
||||
stride_rgba = (width_rgba * 4 + 3) & ~3;
|
||||
data_rgba = calloc (1, stride_rgba * height);
|
||||
if (data_rgba == NULL) {
|
||||
if (own_buffer)
|
||||
free (bitmap->buffer);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
os = 1;
|
||||
switch (font_options->subpixel_order) {
|
||||
|
@ -905,6 +905,9 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
|
|||
case FT_PIXEL_MODE_GRAY4:
|
||||
/* These could be triggered by very rare types of TrueType fonts */
|
||||
default:
|
||||
if (own_buffer)
|
||||
free (bitmap->buffer);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -1035,6 +1038,7 @@ _render_glyph_outline (FT_Face face,
|
|||
bitmap.buffer = calloc (1, stride * bitmap.rows);
|
||||
|
||||
if (bitmap.buffer == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -1042,6 +1046,7 @@ _render_glyph_outline (FT_Face face,
|
|||
|
||||
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
|
||||
free (bitmap.buffer);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -1079,8 +1084,10 @@ _render_glyph_bitmap (FT_Face face,
|
|||
* we avoid the FT_LOAD_NO_RECURSE flag.
|
||||
*/
|
||||
error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
|
||||
if (error)
|
||||
if (error) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
|
||||
if (status)
|
||||
|
@ -1178,24 +1185,33 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
|
|||
|
||||
/* Initialize it to empty
|
||||
*/
|
||||
_cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
0, 0,
|
||||
width, height);
|
||||
status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
0, 0,
|
||||
width, height);
|
||||
if (status) {
|
||||
cairo_surface_destroy (image);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Draw the original bitmap transformed into the new bitmap
|
||||
*/
|
||||
_cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
|
||||
cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
|
||||
|
||||
_cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||
&pattern.base, NULL, image,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
width,
|
||||
height);
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||
&pattern.base, NULL, image,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
width,
|
||||
height);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
|
||||
if (status) {
|
||||
cairo_surface_destroy (image);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Now update the cache entry for the new bitmap, recomputing
|
||||
* the origin based on the final transform.
|
||||
*/
|
||||
|
@ -1445,6 +1461,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
|
|||
FT_Face face;
|
||||
FT_Size_Metrics *metrics;
|
||||
cairo_font_extents_t fs_metrics;
|
||||
cairo_status_t status;
|
||||
|
||||
face = _cairo_ft_unscaled_font_lock_face (unscaled);
|
||||
if (!face)
|
||||
|
@ -1453,6 +1470,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
|
|||
scaled_font = malloc (sizeof(cairo_ft_scaled_font_t));
|
||||
if (scaled_font == NULL) {
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1465,13 +1483,26 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
|
|||
_cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
|
||||
_cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
|
||||
|
||||
_cairo_scaled_font_init (&scaled_font->base,
|
||||
font_face,
|
||||
font_matrix, ctm, options,
|
||||
&cairo_ft_scaled_font_backend);
|
||||
status = _cairo_scaled_font_init (&scaled_font->base,
|
||||
font_face,
|
||||
font_matrix, ctm, options,
|
||||
&cairo_ft_scaled_font_backend);
|
||||
if (status) {
|
||||
free (scaled_font);
|
||||
_cairo_unscaled_font_destroy (&unscaled->base);
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = _cairo_ft_unscaled_font_set_scale (unscaled,
|
||||
&scaled_font->base.scale);
|
||||
if (status) {
|
||||
free (scaled_font);
|
||||
_cairo_unscaled_font_destroy (&unscaled->base);
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_cairo_ft_unscaled_font_set_scale (unscaled,
|
||||
&scaled_font->base.scale);
|
||||
|
||||
metrics = &face->size->metrics;
|
||||
|
||||
|
@ -1549,8 +1580,10 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
|
|||
unsigned char *family = (unsigned char*) toy_face->family;
|
||||
|
||||
pattern = FcPatternCreate ();
|
||||
if (!pattern)
|
||||
if (!pattern) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
switch (toy_face->weight)
|
||||
{
|
||||
|
@ -1620,6 +1653,7 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
|
|||
*font = new_font;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
} else {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
@ -1644,8 +1678,10 @@ _move_to (FT_Vector *to, void *closure)
|
|||
x = _cairo_fixed_from_26_6 (to->x);
|
||||
y = _cairo_fixed_from_26_6 (to->y);
|
||||
|
||||
_cairo_path_fixed_close_path (path);
|
||||
_cairo_path_fixed_move_to (path, x, y);
|
||||
if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
|
||||
return 1;
|
||||
if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1659,7 +1695,8 @@ _line_to (FT_Vector *to, void *closure)
|
|||
x = _cairo_fixed_from_26_6 (to->x);
|
||||
y = _cairo_fixed_from_26_6 (to->y);
|
||||
|
||||
_cairo_path_fixed_line_to (path, x, y);
|
||||
if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1675,7 +1712,9 @@ _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
|
|||
cairo_fixed_t x3, y3;
|
||||
cairo_point_t conic;
|
||||
|
||||
_cairo_path_fixed_get_current_point (path, &x0, &y0);
|
||||
if (_cairo_path_fixed_get_current_point (path, &x0, &y0) !=
|
||||
CAIRO_STATUS_SUCCESS)
|
||||
return 1;
|
||||
|
||||
conic.x = _cairo_fixed_from_26_6 (control->x);
|
||||
conic.y = _cairo_fixed_from_26_6 (control->y);
|
||||
|
@ -1689,10 +1728,11 @@ _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
|
|||
x2 = x3 + 2.0/3.0 * (conic.x - x3);
|
||||
y2 = y3 + 2.0/3.0 * (conic.y - y3);
|
||||
|
||||
_cairo_path_fixed_curve_to (path,
|
||||
x1, y1,
|
||||
x2, y2,
|
||||
x3, y3);
|
||||
if (_cairo_path_fixed_curve_to (path,
|
||||
x1, y1,
|
||||
x2, y2,
|
||||
x3, y3) != CAIRO_STATUS_SUCCESS)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1715,10 +1755,11 @@ _cubic_to (FT_Vector *control1, FT_Vector *control2,
|
|||
x2 = _cairo_fixed_from_26_6 (to->x);
|
||||
y2 = _cairo_fixed_from_26_6 (to->y);
|
||||
|
||||
_cairo_path_fixed_curve_to (path,
|
||||
x0, y0,
|
||||
x1, y1,
|
||||
x2, y2);
|
||||
if (_cairo_path_fixed_curve_to (path,
|
||||
x0, y0,
|
||||
x1, y1,
|
||||
x2, y2) != CAIRO_STATUS_SUCCESS)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1743,6 +1784,7 @@ _decompose_glyph_outline (FT_Face face,
|
|||
|
||||
FT_GlyphSlot glyph;
|
||||
cairo_path_fixed_t *path;
|
||||
cairo_status_t status;
|
||||
|
||||
path = _cairo_path_fixed_create ();
|
||||
if (!path)
|
||||
|
@ -1752,9 +1794,17 @@ _decompose_glyph_outline (FT_Face face,
|
|||
|
||||
/* Font glyphs have an inverted Y axis compared to cairo. */
|
||||
FT_Outline_Transform (&glyph->outline, &invert_y);
|
||||
FT_Outline_Decompose (&glyph->outline, &outline_funcs, path);
|
||||
if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
|
||||
_cairo_path_fixed_destroy (path);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
_cairo_path_fixed_close_path (path);
|
||||
status = _cairo_path_fixed_close_path (path);
|
||||
if (status) {
|
||||
_cairo_path_fixed_destroy (path);
|
||||
return status;
|
||||
}
|
||||
|
||||
*pathp = path;
|
||||
|
||||
|
@ -1798,14 +1848,16 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
FT_Glyph_Metrics *metrics;
|
||||
double x_factor, y_factor;
|
||||
cairo_bool_t vertical_layout = FALSE;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_status_t status;
|
||||
|
||||
face = _cairo_ft_unscaled_font_lock_face (unscaled);
|
||||
if (!face)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
_cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
|
||||
&scaled_font->base.scale);
|
||||
status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
|
||||
&scaled_font->base.scale);
|
||||
if (status)
|
||||
goto FAIL;
|
||||
|
||||
/* Ignore global advance unconditionally */
|
||||
load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
|
||||
|
@ -1951,9 +2003,12 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
} else {
|
||||
status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
|
||||
&surface);
|
||||
if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape)
|
||||
if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape) {
|
||||
status = _transform_glyph_bitmap (&unscaled->current_shape,
|
||||
&surface);
|
||||
if (status)
|
||||
cairo_surface_destroy (&surface->base);
|
||||
}
|
||||
}
|
||||
if (status)
|
||||
goto FAIL;
|
||||
|
@ -1977,6 +2032,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
|
||||
if (error) {
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
|
||||
|
@ -2186,10 +2242,12 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
|
|||
&font_face->base,
|
||||
font_matrix, ctm,
|
||||
options, ft_options);
|
||||
if (*scaled_font)
|
||||
if (*scaled_font) {
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
else
|
||||
} else {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
|
||||
|
@ -2202,23 +2260,32 @@ static cairo_font_face_t *
|
|||
_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
|
||||
cairo_ft_options_t *ft_options)
|
||||
{
|
||||
cairo_ft_font_face_t *font_face;
|
||||
cairo_ft_font_face_t *font_face, **prev_font_face;
|
||||
|
||||
/* Looked for an existing matching font face */
|
||||
for (font_face = unscaled->faces;
|
||||
for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
|
||||
font_face;
|
||||
font_face = font_face->next)
|
||||
prev_font_face = &font_face->next, font_face = font_face->next)
|
||||
{
|
||||
if (font_face->ft_options.load_flags == ft_options->load_flags &&
|
||||
font_face->ft_options.extra_flags == ft_options->extra_flags &&
|
||||
cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
|
||||
return cairo_font_face_reference (&font_face->base);
|
||||
{
|
||||
if (! font_face->base.status)
|
||||
return cairo_font_face_reference (&font_face->base);
|
||||
|
||||
/* The font_face has been left in an error state, abandon it. */
|
||||
*prev_font_face = font_face->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No match found, create a new one */
|
||||
font_face = malloc (sizeof (cairo_ft_font_face_t));
|
||||
if (!font_face)
|
||||
if (!font_face) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
font_face->unscaled = unscaled;
|
||||
_cairo_unscaled_font_reference (&unscaled->base);
|
||||
|
@ -2376,10 +2443,8 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
|
|||
|
||||
if (font_face)
|
||||
return font_face;
|
||||
else {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
else
|
||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2429,12 +2494,10 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
|
|||
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
|
||||
_cairo_unscaled_font_destroy (&unscaled->base);
|
||||
|
||||
if (font_face) {
|
||||
if (font_face)
|
||||
return font_face;
|
||||
} else {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
else
|
||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2472,6 +2535,7 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
|
|||
{
|
||||
cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
|
||||
FT_Face face;
|
||||
cairo_status_t status;
|
||||
|
||||
if (scaled_font->base.status)
|
||||
return NULL;
|
||||
|
@ -2482,8 +2546,13 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
_cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
|
||||
&scaled_font->base.scale);
|
||||
status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
|
||||
&scaled_font->base.scale);
|
||||
if (status) {
|
||||
_cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
|
||||
_cairo_scaled_font_set_error (&scaled_font->base, status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* NOTE: We deliberately release the unscaled font's mutex here,
|
||||
* so that we are not holding a lock across two separate calls to
|
||||
|
|
|
@ -33,7 +33,8 @@ typedef struct _cairo_glitz_surface {
|
|||
|
||||
glitz_surface_t *surface;
|
||||
glitz_format_t *format;
|
||||
pixman_region16_t *clip;
|
||||
cairo_bool_t has_clip;
|
||||
pixman_region16_t clip;
|
||||
} cairo_glitz_surface_t;
|
||||
|
||||
static const cairo_surface_backend_t *
|
||||
|
@ -44,10 +45,9 @@ _cairo_glitz_surface_finish (void *abstract_surface)
|
|||
{
|
||||
cairo_glitz_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->clip)
|
||||
{
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
|
||||
pixman_region_destroy (surface->clip);
|
||||
if (surface->has_clip) {
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
|
||||
pixman_region_fini (&surface->clip);
|
||||
}
|
||||
|
||||
glitz_surface_destroy (surface->surface);
|
||||
|
@ -208,7 +208,7 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
|
|||
}
|
||||
|
||||
/* clear out the glitz clip; the clip affects glitz_get_pixels */
|
||||
if (surface->clip)
|
||||
if (surface->has_clip)
|
||||
glitz_surface_set_clip_region (surface->surface,
|
||||
0, 0, NULL, 0);
|
||||
|
||||
|
@ -221,12 +221,12 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
|
|||
glitz_buffer_destroy (buffer);
|
||||
|
||||
/* restore the clip, if any */
|
||||
if (surface->clip) {
|
||||
if (surface->has_clip) {
|
||||
glitz_box_t *box;
|
||||
int n;
|
||||
|
||||
box = (glitz_box_t *) pixman_region_rects (surface->clip);
|
||||
n = pixman_region_num_rects (surface->clip);
|
||||
box = (glitz_box_t *) pixman_region_rects (&surface->clip);
|
||||
n = pixman_region_num_rects (&surface->clip);
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
|
||||
}
|
||||
|
||||
|
@ -668,7 +668,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
}
|
||||
|
||||
glitz_set_pixels (src->surface, 0, 0, gradient->n_stops, 1,
|
||||
&format, buffer);
|
||||
(glitz_pixel_format_t *)&format, buffer);
|
||||
|
||||
glitz_buffer_destroy (buffer);
|
||||
|
||||
|
@ -822,11 +822,16 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
|
|||
combined = src_solid->color;
|
||||
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
|
||||
|
||||
_cairo_pattern_init_solid (&tmp.solid, &combined);
|
||||
_cairo_pattern_init_solid (&tmp.solid, &combined,
|
||||
CAIRO_COLOR_IS_OPAQUE (&combined) ?
|
||||
CAIRO_CONTENT_COLOR :
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
mask = NULL;
|
||||
} else {
|
||||
_cairo_pattern_init_copy (&tmp.base, src);
|
||||
status = _cairo_pattern_init_copy (&tmp.base, src);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
|
||||
|
@ -841,7 +846,9 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
|
|||
|
||||
if (mask)
|
||||
{
|
||||
_cairo_pattern_init_copy (&tmp.base, mask);
|
||||
status = _cairo_pattern_init_copy (&tmp.base, mask);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
|
||||
mask_x, mask_y,
|
||||
|
@ -1002,7 +1009,8 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
|
|||
_cairo_surface_create_similar_solid (&dst->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
1, 1,
|
||||
(cairo_color_t *) color);
|
||||
(cairo_color_t *) color,
|
||||
NULL);
|
||||
if (src->base.status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
|
@ -1071,7 +1079,9 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
|
||||
{
|
||||
_cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
|
||||
status = _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base,
|
||||
dst,
|
||||
|
@ -1283,26 +1293,32 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface,
|
|||
glitz_box_t *box;
|
||||
int n;
|
||||
|
||||
if (!surface->clip)
|
||||
{
|
||||
surface->clip = pixman_region_create ();
|
||||
if (!surface->clip)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
pixman_region_copy (surface->clip, region);
|
||||
if (!surface->has_clip) {
|
||||
pixman_region_init (&surface->clip);
|
||||
surface->has_clip = TRUE;
|
||||
}
|
||||
|
||||
if (pixman_region_copy (&surface->clip, region) !=
|
||||
PIXMAN_REGION_STATUS_SUCCESS)
|
||||
{
|
||||
pixman_region_fini (&surface->clip);
|
||||
surface->has_clip = FALSE;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
box = (glitz_box_t *) pixman_region_rects (&surface->clip);
|
||||
n = pixman_region_num_rects (&surface->clip);
|
||||
|
||||
box = (glitz_box_t *) pixman_region_rects (surface->clip);
|
||||
n = pixman_region_num_rects (surface->clip);
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
|
||||
|
||||
if (surface->clip)
|
||||
pixman_region_destroy (surface->clip);
|
||||
|
||||
surface->clip = NULL;
|
||||
if (surface->has_clip) {
|
||||
pixman_region_fini (&surface->clip);
|
||||
surface->has_clip = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -2172,6 +2188,33 @@ _cairo_glitz_surface_flush (void *abstract_surface)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_glitz_surface_is_similar (void *surface_a,
|
||||
void *surface_b,
|
||||
cairo_content_t content)
|
||||
{
|
||||
cairo_glitz_surface_t *a = (cairo_glitz_surface_t *) surface_a;
|
||||
cairo_glitz_surface_t *b = (cairo_glitz_surface_t *) surface_b;
|
||||
|
||||
glitz_drawable_t *drawable_a = glitz_surface_get_drawable (a->surface);
|
||||
glitz_drawable_t *drawable_b = glitz_surface_get_drawable (b->surface);
|
||||
|
||||
return drawable_a == drawable_b;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_surface_reset (void *abstract_surface)
|
||||
{
|
||||
cairo_glitz_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_glitz_surface_set_clip_region (surface, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_GLITZ,
|
||||
_cairo_glitz_surface_create_similar,
|
||||
|
@ -2194,7 +2237,18 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
|
|||
_cairo_glitz_surface_flush,
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
_cairo_glitz_surface_scaled_font_fini,
|
||||
_cairo_glitz_surface_scaled_glyph_fini
|
||||
_cairo_glitz_surface_scaled_glyph_fini,
|
||||
|
||||
NULL, /* paint */
|
||||
NULL, /* mask */
|
||||
NULL, /* stroke */
|
||||
NULL, /* fill */
|
||||
NULL, /* show_glyphs */
|
||||
|
||||
NULL, /* snapshot */
|
||||
_cairo_glitz_surface_is_similar,
|
||||
|
||||
_cairo_glitz_surface_reset
|
||||
};
|
||||
|
||||
static const cairo_surface_backend_t *
|
||||
|
@ -2240,9 +2294,9 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
|
|||
|
||||
glitz_surface_reference (surface);
|
||||
|
||||
crsurface->surface = surface;
|
||||
crsurface->format = format;
|
||||
crsurface->clip = NULL;
|
||||
crsurface->surface = surface;
|
||||
crsurface->format = format;
|
||||
crsurface->has_clip = FALSE;
|
||||
|
||||
return (cairo_surface_t *) crsurface;
|
||||
}
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-clip-private.h"
|
||||
|
@ -64,6 +62,8 @@ cairo_status_t
|
|||
_cairo_gstate_init (cairo_gstate_t *gstate,
|
||||
cairo_surface_t *target)
|
||||
{
|
||||
gstate->next = NULL;
|
||||
|
||||
gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
|
||||
|
||||
gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
|
||||
|
@ -91,13 +91,12 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
|
|||
_cairo_gstate_identity_matrix (gstate);
|
||||
gstate->source_ctm_inverse = gstate->ctm_inverse;
|
||||
|
||||
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
|
||||
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
if (gstate->source->status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
gstate->next = NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return target ? target->status : CAIRO_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,7 +130,9 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
|
|||
|
||||
_cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
|
||||
|
||||
_cairo_clip_init_copy (&gstate->clip, &other->clip);
|
||||
status = _cairo_clip_init_copy (&gstate->clip, &other->clip);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
gstate->target = cairo_surface_reference (other->target);
|
||||
/* parent_target is always set to NULL; it's only ever set by redirect_target */
|
||||
|
@ -160,7 +161,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
|
|||
cairo_scaled_font_destroy (gstate->scaled_font);
|
||||
gstate->scaled_font = NULL;
|
||||
|
||||
_cairo_clip_fini (&gstate->clip);
|
||||
_cairo_clip_reset (&gstate->clip);
|
||||
|
||||
cairo_surface_destroy (gstate->target);
|
||||
gstate->target = NULL;
|
||||
|
@ -175,7 +176,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
|
|||
gstate->source = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
_cairo_gstate_destroy (cairo_gstate_t *gstate)
|
||||
{
|
||||
if (gstate == NULL)
|
||||
|
@ -197,7 +198,7 @@ _cairo_gstate_destroy (cairo_gstate_t *gstate)
|
|||
* Return value: a new cairo_gstate_t or NULL if there is insufficient
|
||||
* memory.
|
||||
**/
|
||||
cairo_gstate_t*
|
||||
static cairo_gstate_t*
|
||||
_cairo_gstate_clone (cairo_gstate_t *other)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
@ -218,6 +219,55 @@ _cairo_gstate_clone (cairo_gstate_t *other)
|
|||
return gstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_gstate_save:
|
||||
* @gstate: input/output gstate pointer
|
||||
*
|
||||
* Makes a copy of the current state of @gstate and saves it
|
||||
* to @gstate->next, then put the address of the newly allcated
|
||||
* copy into @gstate. _cairo_gstate_restore() reverses this.
|
||||
**/
|
||||
cairo_status_t
|
||||
_cairo_gstate_save (cairo_gstate_t **gstate)
|
||||
{
|
||||
cairo_gstate_t *top;
|
||||
|
||||
top = _cairo_gstate_clone (*gstate);
|
||||
|
||||
if (top == NULL) {
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
top->next = *gstate;
|
||||
*gstate = top;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_gstate_restore:
|
||||
* @gstate: input/output gstate pointer
|
||||
*
|
||||
* Reverses the effects of one _cairo_gstate_save() call.
|
||||
**/
|
||||
cairo_status_t
|
||||
_cairo_gstate_restore (cairo_gstate_t **gstate)
|
||||
{
|
||||
cairo_gstate_t *top;
|
||||
|
||||
top = *gstate;
|
||||
|
||||
if (top->next == NULL) {
|
||||
return CAIRO_STATUS_INVALID_RESTORE;
|
||||
}
|
||||
|
||||
*gstate = top->next;
|
||||
|
||||
_cairo_gstate_destroy (top);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate,
|
||||
cairo_clip_path_t *cpath)
|
||||
|
@ -252,9 +302,11 @@ _cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate,
|
|||
* original #cairo_t target, the clip will be INVALID after this call,
|
||||
* and the caller should either recreate or reset the clip.
|
||||
**/
|
||||
void
|
||||
cairo_status_t
|
||||
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
/* If this gstate is already redirected, this is an error; we need a
|
||||
* new gstate to be able to redirect */
|
||||
assert (gstate->parent_target == NULL);
|
||||
|
@ -269,14 +321,18 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
|
|||
* since its ref is now owned by gstate->parent_target */
|
||||
gstate->target = cairo_surface_reference (child);
|
||||
|
||||
_cairo_clip_fini (&gstate->clip);
|
||||
_cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
|
||||
_cairo_clip_reset (&gstate->clip);
|
||||
status = _cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* The clip is in surface backend coordinates for the previous target;
|
||||
* translate it into the child's backend coordinates. */
|
||||
_cairo_clip_translate (&gstate->clip,
|
||||
_cairo_fixed_from_double (child->device_transform.x0 - gstate->parent_target->device_transform.x0),
|
||||
_cairo_fixed_from_double (child->device_transform.y0 - gstate->parent_target->device_transform.y0));
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -356,7 +412,7 @@ _cairo_gstate_set_source (cairo_gstate_t *gstate,
|
|||
if (source->status)
|
||||
return source->status;
|
||||
|
||||
cairo_pattern_reference (source);
|
||||
source = cairo_pattern_reference (source);
|
||||
cairo_pattern_destroy (gstate->source);
|
||||
gstate->source = source;
|
||||
gstate->source_ctm_inverse = gstate->ctm_inverse;
|
||||
|
@ -507,6 +563,24 @@ _cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dash
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gstate_get_dash (cairo_gstate_t *gstate,
|
||||
double *dashes,
|
||||
int *num_dashes,
|
||||
double *offset)
|
||||
{
|
||||
if (dashes)
|
||||
memcpy (dashes,
|
||||
gstate->stroke_style.dash,
|
||||
sizeof (double) * gstate->stroke_style.num_dashes);
|
||||
|
||||
if (num_dashes)
|
||||
*num_dashes = gstate->stroke_style.num_dashes;
|
||||
|
||||
if (offset)
|
||||
*offset = gstate->stroke_style.dash_offset;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit)
|
||||
{
|
||||
|
@ -583,13 +657,16 @@ _cairo_gstate_transform (cairo_gstate_t *gstate,
|
|||
const cairo_matrix_t *matrix)
|
||||
{
|
||||
cairo_matrix_t tmp;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
||||
tmp = *matrix;
|
||||
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
|
||||
|
||||
cairo_matrix_invert (&tmp);
|
||||
status = cairo_matrix_invert (&tmp);
|
||||
if (status)
|
||||
return status;
|
||||
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -613,49 +690,39 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
|
||||
{
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
||||
cairo_matrix_init_identity (&gstate->ctm);
|
||||
cairo_matrix_init_identity (&gstate->ctm_inverse);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
cairo_matrix_transform_point (&gstate->ctm, x, y);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_gstate_user_to_device_distance (cairo_gstate_t *gstate,
|
||||
double *dx, double *dy)
|
||||
{
|
||||
cairo_matrix_transform_distance (&gstate->ctm, dx, dy);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y)
|
||||
{
|
||||
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate,
|
||||
double *dx, double *dy)
|
||||
{
|
||||
cairo_matrix_transform_distance (&gstate->ctm_inverse, dx, dy);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -697,7 +764,7 @@ _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
|
|||
}
|
||||
*/
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
|
||||
cairo_pattern_t *pattern,
|
||||
cairo_pattern_t *original,
|
||||
|
@ -705,8 +772,12 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
|
|||
{
|
||||
cairo_surface_pattern_t *surface_pattern;
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_pattern_init_copy (pattern, original);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_pattern_init_copy (pattern, original);
|
||||
_cairo_pattern_transform (pattern, ctm_inverse);
|
||||
|
||||
if (cairo_pattern_get_type (original) == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
|
@ -716,25 +787,26 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
|
|||
_cairo_pattern_transform (pattern, &surface->device_transform);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_gstate_copy_transformed_source (cairo_gstate_t *gstate,
|
||||
cairo_pattern_t *pattern)
|
||||
{
|
||||
_cairo_gstate_copy_transformed_pattern (gstate, pattern,
|
||||
gstate->source,
|
||||
&gstate->source_ctm_inverse);
|
||||
return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
|
||||
gstate->source,
|
||||
&gstate->source_ctm_inverse);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate,
|
||||
cairo_pattern_t *pattern,
|
||||
cairo_pattern_t *mask)
|
||||
{
|
||||
_cairo_gstate_copy_transformed_pattern (gstate, pattern,
|
||||
mask,
|
||||
&gstate->ctm_inverse);
|
||||
return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
|
||||
mask,
|
||||
&gstate->ctm_inverse);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -750,7 +822,9 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
|
||||
status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_surface_paint (gstate->target,
|
||||
gstate->op,
|
||||
|
@ -857,16 +931,22 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
_cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
|
||||
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
|
||||
if (status)
|
||||
goto CLEANUP_SOURCE;
|
||||
|
||||
status = _cairo_surface_mask (gstate->target,
|
||||
gstate->op,
|
||||
&source_pattern.base,
|
||||
&mask_pattern.base);
|
||||
|
||||
_cairo_pattern_fini (&source_pattern.base);
|
||||
_cairo_pattern_fini (&mask_pattern.base);
|
||||
CLEANUP_SOURCE:
|
||||
_cairo_pattern_fini (&source_pattern.base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -887,7 +967,10 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
status = _cairo_gstate_copy_transformed_source (gstate,
|
||||
&source_pattern.base);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_surface_stroke (gstate->target,
|
||||
gstate->op,
|
||||
|
@ -954,7 +1037,9 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
|
||||
status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_surface_fill (gstate->target,
|
||||
gstate->op,
|
||||
|
@ -1001,29 +1086,13 @@ BAIL:
|
|||
cairo_status_t
|
||||
_cairo_gstate_copy_page (cairo_gstate_t *gstate)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_surface_copy_page (gstate->target);
|
||||
|
||||
/* It's fine if some surfaces just don't support this. */
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return status;
|
||||
return _cairo_surface_copy_page (gstate->target);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_show_page (cairo_gstate_t *gstate)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_surface_show_page (gstate->target);
|
||||
|
||||
/* It's fine if some surfaces just don't support this. */
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return status;
|
||||
return _cairo_surface_show_page (gstate->target);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1125,7 +1194,9 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
|
|||
cairo_status_t
|
||||
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
|
||||
{
|
||||
return _cairo_clip_reset (&gstate->clip);
|
||||
_cairo_clip_reset (&gstate->clip);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -1190,12 +1261,15 @@ _cairo_gstate_select_font_face (cairo_gstate_t *gstate,
|
|||
cairo_font_weight_t weight)
|
||||
{
|
||||
cairo_font_face_t *font_face;
|
||||
cairo_status_t status;
|
||||
|
||||
font_face = _cairo_toy_font_face_create (family, slant, weight);
|
||||
if (font_face->status)
|
||||
return font_face->status;
|
||||
|
||||
_cairo_gstate_set_font_face (gstate, font_face);
|
||||
status = _cairo_gstate_set_font_face (gstate, font_face);
|
||||
if (status)
|
||||
return status;
|
||||
cairo_font_face_destroy (font_face);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -1230,15 +1304,13 @@ _cairo_gstate_get_font_matrix (cairo_gstate_t *gstate,
|
|||
*matrix = gstate->font_matrix;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_gstate_set_font_options (cairo_gstate_t *gstate,
|
||||
const cairo_font_options_t *options)
|
||||
{
|
||||
_cairo_gstate_unset_scaled_font (gstate);
|
||||
|
||||
gstate->font_options = *options;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1357,17 +1429,19 @@ _cairo_gstate_get_scaled_font (cairo_gstate_t *gstate,
|
|||
static cairo_status_t
|
||||
_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
|
||||
{
|
||||
if (!gstate->font_face) {
|
||||
cairo_font_face_t *font_face;
|
||||
cairo_font_face_t *font_face;
|
||||
|
||||
font_face = _cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
|
||||
CAIRO_FONT_SLANT_DEFAULT,
|
||||
CAIRO_FONT_WEIGHT_DEFAULT);
|
||||
if (font_face->status)
|
||||
return font_face->status;
|
||||
else
|
||||
gstate->font_face = font_face;
|
||||
}
|
||||
if (gstate->font_face != NULL)
|
||||
return gstate->font_face->status;
|
||||
|
||||
|
||||
font_face = _cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
|
||||
CAIRO_FONT_SLANT_DEFAULT,
|
||||
CAIRO_FONT_WEIGHT_DEFAULT);
|
||||
if (font_face->status)
|
||||
return font_face->status;
|
||||
|
||||
gstate->font_face = font_face;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1377,9 +1451,10 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate)
|
|||
{
|
||||
cairo_status_t status;
|
||||
cairo_font_options_t options;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
|
||||
if (gstate->scaled_font)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (gstate->scaled_font != NULL)
|
||||
return gstate->scaled_font->status;
|
||||
|
||||
status = _cairo_gstate_ensure_font_face (gstate);
|
||||
if (status)
|
||||
|
@ -1388,13 +1463,16 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate)
|
|||
cairo_surface_get_font_options (gstate->target, &options);
|
||||
cairo_font_options_merge (&options, &gstate->font_options);
|
||||
|
||||
gstate->scaled_font = cairo_scaled_font_create (gstate->font_face,
|
||||
&gstate->font_matrix,
|
||||
&gstate->ctm,
|
||||
&options);
|
||||
scaled_font = cairo_scaled_font_create (gstate->font_face,
|
||||
&gstate->font_matrix,
|
||||
&gstate->ctm,
|
||||
&options);
|
||||
|
||||
if (!gstate->scaled_font)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
status = cairo_scaled_font_status (scaled_font);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
gstate->scaled_font = scaled_font;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1409,7 +1487,7 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
|
|||
|
||||
cairo_scaled_font_extents (gstate->scaled_font, extents);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return cairo_scaled_font_status (gstate->scaled_font);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -1426,13 +1504,8 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
|
||||
utf8, glyphs, num_glyphs);
|
||||
|
||||
if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs))
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
|
||||
utf8, glyphs, num_glyphs);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -1468,7 +1541,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
|
|||
glyphs, num_glyphs,
|
||||
extents);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return cairo_scaled_font_status (gstate->scaled_font);
|
||||
}
|
||||
|
||||
#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t)))
|
||||
|
@ -1505,7 +1578,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
|
||||
transformed_glyphs);
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
if (status)
|
||||
goto CLEANUP_GLYPHS;
|
||||
|
||||
status = _cairo_surface_show_glyphs (gstate->target,
|
||||
gstate->op,
|
||||
|
@ -1516,6 +1591,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
|
|||
|
||||
_cairo_pattern_fini (&source_pattern.base);
|
||||
|
||||
CLEANUP_GLYPHS:
|
||||
if (transformed_glyphs != stack_transformed_glyphs)
|
||||
free (transformed_glyphs);
|
||||
|
||||
|
|
|
@ -39,51 +39,13 @@
|
|||
#ifndef CAIRO_HASH_PRIVATE_H
|
||||
#define CAIRO_HASH_PRIVATE_H
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
/* XXX: I'd like this file to be self-contained in terms of
|
||||
* includeability, but that's not really possible with the current
|
||||
* monolithic cairoint.h. So, for now, just include cairoint.h instead
|
||||
* if you want to include this file. */
|
||||
|
||||
typedef struct _cairo_hash_table cairo_hash_table_t;
|
||||
|
||||
/**
|
||||
* cairo_hash_entry_t:
|
||||
*
|
||||
* A #cairo_hash_entry_t contains both a key and a value for
|
||||
* cairo_hash_table_t. User-derived types for cairo_hash_entry_t must
|
||||
* be type-compatible with this structure (eg. they must have an
|
||||
* unsigned long as the first parameter. The easiest way to get this
|
||||
* is to use:
|
||||
*
|
||||
* typedef _my_entry {
|
||||
* cairo_hash_entry_t base;
|
||||
* ... Remainder of key and value fields here ..
|
||||
* } my_entry_t;
|
||||
*
|
||||
* which then allows a pointer to my_entry_t to be passed to any of
|
||||
* the cairo_hash_table functions as follows without requiring a cast:
|
||||
*
|
||||
* _cairo_hash_table_insert (hash_table, &my_entry->base);
|
||||
*
|
||||
* IMPORTANT: The caller is reponsible for initializing
|
||||
* my_entry->base.hash with a hash code derived from the key. The
|
||||
* essential property of the hash code is that keys_equal must never
|
||||
* return TRUE for two keys that have different hashes. The best hash
|
||||
* code will reduce the frequency of two keys with the same code for
|
||||
* which keys_equal returns FALSE.
|
||||
*
|
||||
* Which parts of the entry make up the "key" and which part make up
|
||||
* the value are entirely up to the caller, (as determined by the
|
||||
* computation going into base.hash as well as the keys_equal
|
||||
* function). A few of the cairo_hash_table functions accept an entry
|
||||
* which will be used exclusively as a "key", (indicated by a
|
||||
* parameter name of key). In these cases, the value-related fields of
|
||||
* the entry need not be initialized if so desired.
|
||||
**/
|
||||
typedef struct _cairo_hash_entry {
|
||||
unsigned long hash;
|
||||
} cairo_hash_entry_t;
|
||||
|
||||
typedef cairo_bool_t
|
||||
(*cairo_hash_keys_equal_func_t) (const void *key_a, const void *key_b);
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ static const cairo_hash_table_arrangement_t hash_table_arrangements [] = {
|
|||
{ 268435456, 590559793, 590559791 }
|
||||
};
|
||||
|
||||
#define NUM_HASH_TABLE_ARRANGEMENTS ((int)(sizeof(hash_table_arrangements)/sizeof(hash_table_arrangements[0])))
|
||||
#define NUM_HASH_TABLE_ARRANGEMENTS ARRAY_LENGTH (hash_table_arrangements)
|
||||
|
||||
struct _cairo_hash_table {
|
||||
cairo_hash_keys_equal_func_t keys_equal;
|
||||
|
@ -481,8 +481,12 @@ _cairo_hash_table_insert (cairo_hash_table_t *hash_table,
|
|||
hash_table->live_entries++;
|
||||
|
||||
status = _cairo_hash_table_resize (hash_table);
|
||||
if (status)
|
||||
if (status) {
|
||||
/* abort the insert... */
|
||||
*entry = DEAD_ENTRY;
|
||||
hash_table->live_entries--;
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -561,6 +565,9 @@ _cairo_hash_table_foreach (cairo_hash_table_t *hash_table,
|
|||
* the table may need resizing. Just do this every time
|
||||
* as the check is inexpensive.
|
||||
*/
|
||||
if (--hash_table->iterating == 0)
|
||||
if (--hash_table->iterating == 0) {
|
||||
/* Should we fail to shrink the hash table, it is left unaltered,
|
||||
* and we don't need to propagate the error status. */
|
||||
_cairo_hash_table_resize (hash_table);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
|
||||
static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
|
||||
{
|
||||
&cairo_image_surface_backend, /* backend */
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
|
@ -131,7 +131,7 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
|||
|
||||
/* Try to recover a cairo_format_t from a pixman_format
|
||||
* by looking at the bpp and masks values. */
|
||||
static cairo_format_t
|
||||
static cairo_internal_format_t
|
||||
_cairo_format_from_pixman_format (pixman_format_t *pixman_format)
|
||||
{
|
||||
unsigned int bpp, am, rm, gm, bm;
|
||||
|
@ -167,7 +167,7 @@ _cairo_format_from_pixman_format (pixman_format_t *pixman_format)
|
|||
rm == 0xf800 &&
|
||||
gm == 0x07e0 &&
|
||||
bm == 0x001f)
|
||||
return CAIRO_FORMAT_RGB16_565;
|
||||
return CAIRO_INTERNAL_FORMAT_RGB16_565;
|
||||
break;
|
||||
case 8:
|
||||
if (am == 0xff &&
|
||||
|
@ -212,28 +212,23 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
|
|||
int stride)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
pixman_format_t *pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
cairo_format_t cairo_format;
|
||||
pixman_format_t pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
cairo_format_t cairo_format;
|
||||
|
||||
pixman_format = pixman_format_create_masks (format->bpp,
|
||||
format->alpha_mask,
|
||||
format->red_mask,
|
||||
format->green_mask,
|
||||
format->blue_mask);
|
||||
pixman_format_init_masks (&pixman_format,
|
||||
format->bpp,
|
||||
format->alpha_mask,
|
||||
format->red_mask,
|
||||
format->green_mask,
|
||||
format->blue_mask);
|
||||
|
||||
if (pixman_format == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
cairo_format = _cairo_format_from_pixman_format (&pixman_format);
|
||||
|
||||
cairo_format = _cairo_format_from_pixman_format (pixman_format);
|
||||
|
||||
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
|
||||
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data,
|
||||
&pixman_format,
|
||||
width, height, format->bpp, stride);
|
||||
|
||||
pixman_format_destroy (pixman_format);
|
||||
|
||||
if (pixman_image == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
|
@ -241,28 +236,33 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
|
|||
|
||||
surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
|
||||
cairo_format);
|
||||
if (cairo_surface_status (surface)) {
|
||||
pixman_image_destroy (pixman_image);
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static pixman_format_t *
|
||||
_create_pixman_format (cairo_format_t format)
|
||||
static void
|
||||
_init_pixman_format (pixman_format_t *pixman_format, cairo_format_t format)
|
||||
{
|
||||
int ret;
|
||||
switch (format) {
|
||||
case CAIRO_FORMAT_A1:
|
||||
return pixman_format_create (PIXMAN_FORMAT_NAME_A1);
|
||||
ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_A1);
|
||||
break;
|
||||
case CAIRO_FORMAT_A8:
|
||||
return pixman_format_create (PIXMAN_FORMAT_NAME_A8);
|
||||
ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_A8);
|
||||
break;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
return pixman_format_create (PIXMAN_FORMAT_NAME_RGB24);
|
||||
ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_RGB24);
|
||||
break;
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
default:
|
||||
return pixman_format_create (PIXMAN_FORMAT_NAME_ARGB32);
|
||||
ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_ARGB32);
|
||||
break;
|
||||
}
|
||||
assert (ret);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -290,31 +290,27 @@ cairo_image_surface_create (cairo_format_t format,
|
|||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
pixman_format_t *pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
cairo_surface_t *surface;
|
||||
pixman_format_t pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
|
||||
if (! CAIRO_FORMAT_VALID (format)) {
|
||||
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
|
||||
return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
|
||||
}
|
||||
|
||||
pixman_format = _create_pixman_format (format);
|
||||
if (pixman_format == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
pixman_image = pixman_image_create (pixman_format, width, height);
|
||||
|
||||
pixman_format_destroy (pixman_format);
|
||||
_init_pixman_format (&pixman_format, format);
|
||||
|
||||
pixman_image = pixman_image_create (&pixman_format, width, height);
|
||||
if (pixman_image == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
|
||||
if (cairo_surface_status (surface)) {
|
||||
pixman_image_destroy (pixman_image);
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
@ -369,32 +365,29 @@ cairo_image_surface_create_for_data (unsigned char *data,
|
|||
int height,
|
||||
int stride)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
pixman_format_t *pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
cairo_surface_t *surface;
|
||||
pixman_format_t pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
|
||||
if (! CAIRO_FORMAT_VALID (format))
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
|
||||
pixman_format = _create_pixman_format (format);
|
||||
if (pixman_format == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
_init_pixman_format (&pixman_format, format);
|
||||
|
||||
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
|
||||
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data,
|
||||
&pixman_format,
|
||||
width, height,
|
||||
_cairo_format_bpp (format),
|
||||
stride);
|
||||
|
||||
pixman_format_destroy (pixman_format);
|
||||
|
||||
if (pixman_image == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
|
||||
if (cairo_surface_status (surface)) {
|
||||
pixman_image_destroy (pixman_image);
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
@ -567,7 +560,7 @@ _cairo_content_from_format (cairo_format_t format)
|
|||
case CAIRO_INTERNAL_FORMAT_ABGR32:
|
||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
case CAIRO_FORMAT_RGB16_565:
|
||||
case CAIRO_INTERNAL_FORMAT_RGB16_565:
|
||||
case CAIRO_INTERNAL_FORMAT_BGR24:
|
||||
return CAIRO_CONTENT_COLOR;
|
||||
case CAIRO_FORMAT_A8:
|
||||
|
@ -690,7 +683,8 @@ _cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
|
|||
|
||||
_cairo_matrix_to_pixman_matrix (matrix, &pixman_transform);
|
||||
|
||||
pixman_image_set_transform (surface->pixman_image, &pixman_transform);
|
||||
if (pixman_image_set_transform (surface->pixman_image, &pixman_transform))
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -907,8 +901,10 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
|
|||
pixman_color.alpha = color->alpha_short;
|
||||
|
||||
/* XXX: The pixman_rectangle_t cast is evil... it needs to go away somehow. */
|
||||
pixman_fill_rectangles (_pixman_operator(op), surface->pixman_image,
|
||||
&pixman_color, (pixman_rectangle_t *) rects, num_rects);
|
||||
if (pixman_fill_rectangles (_pixman_operator(op), surface->pixman_image,
|
||||
&pixman_color,
|
||||
(pixman_rectangle_t *) rects, num_rects))
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -932,10 +928,11 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
cairo_image_surface_t *src;
|
||||
cairo_int_status_t status;
|
||||
pixman_image_t *mask;
|
||||
pixman_format_t *format;
|
||||
pixman_format_t format;
|
||||
pixman_bits_t *mask_data;
|
||||
int mask_stride;
|
||||
int mask_bpp;
|
||||
int mask_stride;
|
||||
int mask_bpp;
|
||||
int ret;
|
||||
|
||||
/* Special case adding trapezoids onto a mask surface; we want to avoid
|
||||
* creating an intermediate temporary mask unecessarily.
|
||||
|
@ -974,7 +971,8 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
|
||||
switch (antialias) {
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
format = pixman_format_create (PIXMAN_FORMAT_NAME_A1);
|
||||
ret = pixman_format_init (&format, PIXMAN_FORMAT_NAME_A1);
|
||||
assert (ret);
|
||||
mask_stride = (width + 31)/8;
|
||||
mask_bpp = 1;
|
||||
break;
|
||||
|
@ -982,28 +980,23 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
default:
|
||||
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
|
||||
ret = pixman_format_init (&format, PIXMAN_FORMAT_NAME_A8);
|
||||
assert (ret);
|
||||
mask_stride = (width + 3) & ~3;
|
||||
mask_bpp = 8;
|
||||
break;
|
||||
}
|
||||
if (!format) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto CLEANUP_SOURCE;
|
||||
}
|
||||
|
||||
/* The image must be initially transparent */
|
||||
mask_data = calloc (1, mask_stride * height);
|
||||
if (!mask_data) {
|
||||
if (mask_data == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
pixman_format_destroy (format);
|
||||
goto CLEANUP_SOURCE;
|
||||
}
|
||||
|
||||
mask = pixman_image_create_for_data (mask_data, format, width, height,
|
||||
mask = pixman_image_create_for_data (mask_data, &format, width, height,
|
||||
mask_bpp, mask_stride);
|
||||
pixman_format_destroy (format);
|
||||
if (!mask) {
|
||||
if (mask == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto CLEANUP_IMAGE_DATA;
|
||||
}
|
||||
|
@ -1047,7 +1040,8 @@ _cairo_image_surface_set_clip_region (void *abstract_surface,
|
|||
{
|
||||
cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
|
||||
|
||||
pixman_image_set_clip_region (surface->pixman_image, region);
|
||||
if (pixman_image_set_clip_region (surface->pixman_image, region))
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
surface->has_clip = region != NULL;
|
||||
|
||||
|
@ -1068,6 +1062,28 @@ _cairo_image_surface_get_extents (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_image_surface_get_font_options (void *abstract_surface,
|
||||
cairo_font_options_t *options)
|
||||
{
|
||||
_cairo_font_options_init_default (options);
|
||||
|
||||
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_image_surface_reset (void *abstract_surface)
|
||||
{
|
||||
cairo_image_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_image_surface_set_clip_region (surface, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_surface_is_image:
|
||||
* @surface: a #cairo_surface_t
|
||||
|
@ -1099,7 +1115,22 @@ const cairo_surface_backend_t cairo_image_surface_backend = {
|
|||
_cairo_image_surface_set_clip_region,
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_image_surface_get_extents,
|
||||
NULL /* old_show_glyphs */
|
||||
NULL, /* old_show_glyphs */
|
||||
_cairo_image_surface_get_font_options,
|
||||
NULL, /* flush */
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
NULL, //* font_fini */
|
||||
NULL, //* glyph_fini */
|
||||
|
||||
NULL, /* paint */
|
||||
NULL, /* mask */
|
||||
NULL, /* stroke */
|
||||
NULL, /* fill */
|
||||
NULL, /* show_glyphs */
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
|
||||
_cairo_image_surface_reset
|
||||
};
|
||||
|
||||
/* A convenience function for when one needs to coerce an image
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
|
@ -198,7 +197,7 @@ slim_hidden_def(cairo_matrix_init_scale);
|
|||
* @sx: scale factor in the X direction
|
||||
* @sy: scale factor in the Y direction
|
||||
*
|
||||
* Applies scaling by @tx, @ty to the transformation in @matrix. The
|
||||
* Applies scaling by @sx, @sy to the transformation in @matrix. The
|
||||
* effect of the new transformation is to first scale the coordinates
|
||||
* by @sx and @sy, then apply the original transformation to the coordinates.
|
||||
**/
|
||||
|
@ -496,7 +495,7 @@ _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,
|
|||
}
|
||||
|
||||
/* Compute the amount that each basis vector is scaled by. */
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
|
||||
double *sx, double *sy, int x_major)
|
||||
{
|
||||
|
@ -536,8 +535,6 @@ _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
|
|||
*sy = major;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
|
|
|
@ -212,7 +212,11 @@ static cairo_status_t
|
|||
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
|
||||
const cairo_pattern_t *other)
|
||||
{
|
||||
_cairo_pattern_init_copy (pattern, other);
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_pattern_init_copy (pattern, other);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
|
@ -648,6 +652,9 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
|
|||
cairo_matrix_t *device_transform = &target->device_transform;
|
||||
cairo_path_fixed_t path_copy, *dev_path;
|
||||
|
||||
if (surface->status)
|
||||
return surface->status;
|
||||
|
||||
meta = (cairo_meta_surface_t *) surface;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -668,7 +675,9 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
|
|||
|
||||
dev_path = _cairo_command_get_path (command);
|
||||
if (dev_path && has_device_transform) {
|
||||
_cairo_path_fixed_init_copy (&path_copy, dev_path);
|
||||
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
|
||||
if (status)
|
||||
break;
|
||||
_cairo_path_fixed_device_transform (&path_copy, device_transform);
|
||||
dev_path = &path_copy;
|
||||
}
|
||||
|
@ -754,7 +763,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
|
|||
/* XXX Meta surface clipping is broken and requires some
|
||||
* cairo-gstate.c rewriting. Work around it for now. */
|
||||
if (dev_path == NULL)
|
||||
status = _cairo_clip_reset (&clip);
|
||||
_cairo_clip_reset (&clip);
|
||||
else
|
||||
status = _cairo_clip_clip (&clip, dev_path,
|
||||
command->intersect_clip_path.fill_rule,
|
||||
|
@ -773,7 +782,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
|
|||
break;
|
||||
}
|
||||
|
||||
_cairo_clip_fini (&clip);
|
||||
_cairo_clip_reset (&clip);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2007 Mathias Hasselmann
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mathias Hasselmann <mathias.hasselmann@gmx.de>
|
||||
*/
|
||||
|
||||
|
||||
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_pattern_cache_lock);
|
||||
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock);
|
||||
|
||||
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex);
|
||||
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex);
|
||||
|
||||
#if CAIRO_HAS_FT_FONT
|
||||
CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex);
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_XLIB_SURFACE
|
||||
CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex);
|
||||
#endif
|
||||
|
||||
|
||||
/* Undefine, to err on unintended inclusion */
|
||||
#undef CAIRO_MUTEX_DECLARE
|
|
@ -0,0 +1,175 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2005,2007 Red Hat, Inc.
|
||||
* Copyright © 2007 Mathias Hasselmann
|
||||
*
|
||||
* 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):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Mathias Hasselmann <mathias.hasselmann@gmx.de>
|
||||
* Behdad Esfahbod <behdad@behdad.org>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_MUTEX_PRIVATE_H
|
||||
#define CAIRO_MUTEX_PRIVATE_H
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <cairo-features.h>
|
||||
|
||||
#include "cairo-mutex-type-private.h"
|
||||
|
||||
/* Only the following three are mandatory at this point */
|
||||
#ifndef CAIRO_MUTEX_LOCK
|
||||
# error "CAIRO_MUTEX_LOCK not defined. Check cairo-mutex-type-private.h."
|
||||
#endif
|
||||
#ifndef CAIRO_MUTEX_UNLOCK
|
||||
# error "CAIRO_MUTEX_UNLOCK not defined. Check cairo-mutex-type-private.h."
|
||||
#endif
|
||||
#ifndef CAIRO_MUTEX_NIL_INITIALIZER
|
||||
# error "CAIRO_MUTEX_NIL_INITIALIZER not defined. Check cairo-mutex-type-private.h."
|
||||
#endif
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
|
||||
#define CAIRO_MUTEX_DECLARE(mutex) extern cairo_mutex_t mutex
|
||||
#include "cairo-mutex-list-private.h"
|
||||
#undef CAIRO_MUTEX_DECLARE
|
||||
|
||||
|
||||
/* make sure implementations don't fool us: we decide these ourself */
|
||||
#undef _CAIRO_MUTEX_USE_STATIC_INITIALIZER
|
||||
#undef _CAIRO_MUTEX_USE_STATIC_FINALIZER
|
||||
|
||||
|
||||
#ifdef CAIRO_MUTEX_INIT
|
||||
|
||||
/* If CAIRO_MUTEX_INIT is defined, we may need to initialize all
|
||||
* static mutex'es. */
|
||||
# ifndef CAIRO_MUTEX_INITIALIZE
|
||||
# define CAIRO_MUTEX_INITIALIZE() do { \
|
||||
if (!_cairo_mutex_initialized) \
|
||||
_cairo_mutex_initialize (); \
|
||||
} while(0)
|
||||
|
||||
cairo_private void _cairo_mutex_initialize (void);
|
||||
|
||||
/* and make sure we implement the above */
|
||||
# define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 1
|
||||
# endif /* CAIRO_MUTEX_INITIALIZE */
|
||||
|
||||
#else /* no CAIRO_MUTEX_INIT */
|
||||
|
||||
/* Otherwise we probably don't need to initialize static mutex'es, */
|
||||
# ifndef CAIRO_MUTEX_INITIALIZE
|
||||
# define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
|
||||
# endif /* CAIRO_MUTEX_INITIALIZE */
|
||||
|
||||
/* and dynamic ones can be initialized using the static initializer. */
|
||||
# define CAIRO_MUTEX_INIT(mutex) do { \
|
||||
cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_NIL_INITIALIZER; \
|
||||
memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* CAIRO_MUTEX_INIT */
|
||||
|
||||
|
||||
#ifdef CAIRO_MUTEX_FINI
|
||||
|
||||
/* If CAIRO_MUTEX_FINI is defined, we may need to finalize all
|
||||
* static mutex'es. */
|
||||
# ifndef CAIRO_MUTEX_FINALIZE
|
||||
# define CAIRO_MUTEX_FINALIZE() do { \
|
||||
if (_cairo_mutex_initialized) \
|
||||
_cairo_mutex_finalize (); \
|
||||
} while(0)
|
||||
|
||||
cairo_private void _cairo_mutex_finalize (void);
|
||||
|
||||
/* and make sure we implement the above */
|
||||
# define _CAIRO_MUTEX_USE_STATIC_FINALIZER 1
|
||||
# endif /* CAIRO_MUTEX_FINALIZE */
|
||||
|
||||
#else /* no CAIRO_MUTEX_FINI */
|
||||
|
||||
/* Otherwise we probably don't need to finalize static mutex'es, */
|
||||
# ifndef CAIRO_MUTEX_FINALIZE
|
||||
# define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
|
||||
# endif /* CAIRO_MUTEX_FINALIZE */
|
||||
|
||||
/* neither do the dynamic ones. */
|
||||
# define CAIRO_MUTEX_FINI(mutex) CAIRO_MUTEX_NOOP1(mutex)
|
||||
|
||||
#endif /* CAIRO_MUTEX_FINI */
|
||||
|
||||
|
||||
#ifndef _CAIRO_MUTEX_USE_STATIC_INITIALIZER
|
||||
#define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 0
|
||||
#endif
|
||||
#ifndef _CAIRO_MUTEX_USE_STATIC_FINALIZER
|
||||
#define _CAIRO_MUTEX_USE_STATIC_FINALIZER 0
|
||||
#endif
|
||||
|
||||
/* only if using static initializer and/or finalizer define the boolean */
|
||||
#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER
|
||||
cairo_private extern cairo_bool_t _cairo_mutex_initialized;
|
||||
#endif
|
||||
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
/* Make sure everything we want is defined */
|
||||
#ifndef CAIRO_MUTEX_INITIALIZE
|
||||
# error "CAIRO_MUTEX_INITIALIZE not defined"
|
||||
#endif
|
||||
#ifndef CAIRO_MUTEX_FINALIZE
|
||||
# error "CAIRO_MUTEX_FINALIZE not defined"
|
||||
#endif
|
||||
#ifndef CAIRO_MUTEX_LOCK
|
||||
# error "CAIRO_MUTEX_LOCK not defined"
|
||||
#endif
|
||||
#ifndef CAIRO_MUTEX_UNLOCK
|
||||
# error "CAIRO_MUTEX_UNLOCK not defined"
|
||||
#endif
|
||||
#ifndef CAIRO_MUTEX_INIT
|
||||
# error "CAIRO_MUTEX_INIT not defined"
|
||||
#endif
|
||||
#ifndef CAIRO_MUTEX_FINI
|
||||
# error "CAIRO_MUTEX_FINI not defined"
|
||||
#endif
|
||||
#ifndef CAIRO_MUTEX_NIL_INITIALIZER
|
||||
# error "CAIRO_MUTEX_NIL_INITIALIZER not defined"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,210 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2005,2007 Red Hat, Inc.
|
||||
* Copyright © 2007 Mathias Hasselmann
|
||||
*
|
||||
* 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):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Mathias Hasselmann <mathias.hasselmann@gmx.de>
|
||||
* Behdad Esfahbod <behdad@behdad.org>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H
|
||||
#define CAIRO_MUTEX_TYPE_PRIVATE_H
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <cairo-features.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
|
||||
/* A fully qualified no-operation statement */
|
||||
#define CAIRO_MUTEX_NOOP do {/*no-op*/} while (0)
|
||||
/* And one that evaluates it's argument once */
|
||||
#define CAIRO_MUTEX_NOOP1(expr) do { if (expr) ; } while (0)
|
||||
|
||||
|
||||
/* Cairo mutex implementation:
|
||||
*
|
||||
* Any new mutex implementation needs to do the following:
|
||||
*
|
||||
* - Condition on the right header or feature. Headers are
|
||||
* preferred as eg. you still can use win32 mutex implementation
|
||||
* on a win32 system even if you do not compile the win32
|
||||
* surface/backend.
|
||||
*
|
||||
* - typedef cairo_mutex_t to the proper mutex type on your target
|
||||
* system. Note that you may or may not need to use a pointer,
|
||||
* depending on what kinds of initialization your mutex
|
||||
* implementation supports. No trailing semicolon needed.
|
||||
* You should be able to compile the following snippet (don't try
|
||||
* running it):
|
||||
*
|
||||
* cairo_mutex_t _cairo_some_mutex;
|
||||
*
|
||||
* - #define CAIRO_MUTEX_LOCK(mutex) and CAIRO_MUTEX_UNLOCK(mutex) to
|
||||
* proper statement to lock/unlock the mutex object passed in.
|
||||
* You can (and should) assume that the mutex is already
|
||||
* initialized, and is-not-already-locked/is-locked,
|
||||
* respectively. Use the "do { ... } while (0)" idiom if necessary.
|
||||
* No trailing semicolons are needed (in any macro you define here).
|
||||
* You should be able to compile the following snippet:
|
||||
*
|
||||
* cairo_mutex_t _cairo_some_mutex;
|
||||
*
|
||||
* if (1)
|
||||
* CAIRO_MUTEX_LOCK (_cairo_some_mutex);
|
||||
* else
|
||||
* CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
|
||||
*
|
||||
* - #define CAIRO_MUTEX_NIL_INITIALIZER to something that can
|
||||
* initialize the cairo_mutex_t type you defined. Most of the
|
||||
* time one of 0, NULL, or {} works. At this point
|
||||
* you should be able to compile the following snippet:
|
||||
*
|
||||
* cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
|
||||
*
|
||||
* if (1)
|
||||
* CAIRO_MUTEX_LOCK (_cairo_some_mutex);
|
||||
* else
|
||||
* CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
|
||||
*
|
||||
* - If the above code is not enough to initialize a mutex on
|
||||
* your platform, #define CAIRO_MUTEX_INIT(mutex) to statement
|
||||
* to initialize the mutex (allocate resources, etc). Such that
|
||||
* you should be able to compile AND RUN the following snippet:
|
||||
*
|
||||
* cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
|
||||
*
|
||||
* CAIRO_MUTEX_INIT (_cairo_some_mutex);
|
||||
*
|
||||
* if (1)
|
||||
* CAIRO_MUTEX_LOCK (_cairo_some_mutex);
|
||||
* else
|
||||
* CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
|
||||
*
|
||||
* - If you define CAIRO_MUTEX_INIT(mutex), cairo will use it to
|
||||
* initialize all static mutex'es. If for any reason that should
|
||||
* not happen (eg. CAIRO_MUTEX_INIT is just a faster way than
|
||||
* what cairo does using CAIRO_MUTEX_NIL_INITIALIZER), then
|
||||
* #define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
|
||||
*
|
||||
* - If your system supports freeing a mutex object (deallocating
|
||||
* resources, etc), then #define CAIRO_MUTEX_FINI(mutex) to do
|
||||
* that.
|
||||
*
|
||||
* - If you define CAIRO_MUTEX_FINI(mutex), cairo will use it to
|
||||
* define a finalizer function to finalize all static mutex'es.
|
||||
* However, it's up to you to call CAIRO_MUTEX_FINALIZE() at
|
||||
* proper places, eg. when the system is unloading the cairo library.
|
||||
* So, if for any reason finalizing static mutex'es is not needed
|
||||
* (eg. you never call CAIRO_MUTEX_FINALIZE), then
|
||||
* #define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
|
||||
*
|
||||
* - That is all. If for any reason you think the above API is
|
||||
* not enough to implement cairo_mutex_t on your system, please
|
||||
* stop and write to the cairo mailing list about it. DO NOT
|
||||
* poke around cairo-mutex-private.h for possible solutions.
|
||||
*/
|
||||
|
||||
#if CAIRO_NO_MUTEX
|
||||
|
||||
/* A poor man's mutex */
|
||||
|
||||
typedef int cairo_mutex_t;
|
||||
|
||||
# define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
|
||||
# define CAIRO_MUTEX_LOCK(mutex) do { while (mutex) ; (mutex) = 1; } while (0)
|
||||
# define CAIRO_MUTEX_UNLOCK(mutex) (mutex) = 0
|
||||
# define CAIRO_MUTEX_NIL_INITIALIZER 0
|
||||
|
||||
#elif HAVE_PTHREAD_H /*******************************************************/
|
||||
|
||||
# include <pthread.h>
|
||||
|
||||
typedef pthread_mutex_t cairo_mutex_t;
|
||||
|
||||
# define CAIRO_MUTEX_LOCK(mutex) pthread_mutex_lock (&(mutex))
|
||||
# define CAIRO_MUTEX_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
|
||||
# define CAIRO_MUTEX_FINI(mutex) pthread_mutex_destroy (&(mutex))
|
||||
# define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
|
||||
# define CAIRO_MUTEX_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
|
||||
|
||||
#elif HAVE_WINDOWS_H /*******************************************************/
|
||||
|
||||
# include <windows.h>
|
||||
|
||||
typedef CRITICAL_SECTION cairo_mutex_t;
|
||||
|
||||
# define CAIRO_MUTEX_LOCK(mutex) EnterCriticalSection (&(mutex))
|
||||
# define CAIRO_MUTEX_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
|
||||
# define CAIRO_MUTEX_INIT(mutex) InitializeCriticalSection (&(mutex))
|
||||
# define CAIRO_MUTEX_FINI(mutex) DeleteCriticalSection (&(mutex))
|
||||
# define CAIRO_MUTEX_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 }
|
||||
|
||||
#elif defined __OS2__ /******************************************************/
|
||||
|
||||
# define INCL_BASE
|
||||
# define INCL_PM
|
||||
# include <os2.h>
|
||||
|
||||
typedef HMTX cairo_mutex_t;
|
||||
|
||||
# define CAIRO_MUTEX_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
|
||||
# define CAIRO_MUTEX_UNLOCK(mutex) DosReleaseMutexSem(mutex)
|
||||
# define CAIRO_MUTEX_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
|
||||
# define CAIRO_MUTEX_FINI(mutex) DosCloseMutexSem (mutex)
|
||||
# define CAIRO_MUTEX_NIL_INITIALIZER 0
|
||||
|
||||
#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/
|
||||
|
||||
typedef BLocker* cairo_mutex_t;
|
||||
|
||||
# define CAIRO_MUTEX_LOCK(mutex) (mutex)->Lock()
|
||||
# define CAIRO_MUTEX_UNLOCK(mutex) (mutex)->Unlock()
|
||||
# define CAIRO_MUTEX_INIT(mutex) (mutex) = new BLocker()
|
||||
# define CAIRO_MUTEX_FINI(mutex) delete (mutex)
|
||||
# define CAIRO_MUTEX_NIL_INITIALIZER NULL
|
||||
|
||||
#else /**********************************************************************/
|
||||
|
||||
# error "XXX: No mutex implementation found. Cairo will not work with multiple threads. Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support."
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif
|
|
@ -0,0 +1,80 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2007 Mathias Hasselmann
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mathias Hasselmann <mathias.hasselmann@gmx.de>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER
|
||||
#include "cairo-mutex-list-private.h"
|
||||
#undef CAIRO_MUTEX_DECLARE
|
||||
|
||||
#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER
|
||||
|
||||
# if _CAIRO_MUTEX_USE_STATIC_INITIALIZER
|
||||
# define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE FALSE
|
||||
# else
|
||||
# define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE TRUE
|
||||
# endif
|
||||
|
||||
cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE;
|
||||
|
||||
# undef _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE
|
||||
|
||||
#endif
|
||||
|
||||
#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER
|
||||
void _cairo_mutex_initialize (void)
|
||||
{
|
||||
if (_cairo_mutex_initialized)
|
||||
return;
|
||||
|
||||
_cairo_mutex_initialized = TRUE;
|
||||
|
||||
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex)
|
||||
#include "cairo-mutex-list-private.h"
|
||||
#undef CAIRO_MUTEX_DECLARE
|
||||
}
|
||||
#endif
|
||||
|
||||
#if _CAIRO_MUTEX_USE_STATIC_FINALIZER
|
||||
void _cairo_mutex_finalize (void)
|
||||
{
|
||||
if (!_cairo_mutex_initialized)
|
||||
return;
|
||||
|
||||
_cairo_mutex_initialized = FALSE;
|
||||
|
||||
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex)
|
||||
#include "cairo-mutex-list-private.h"
|
||||
#undef CAIRO_MUTEX_DECLARE
|
||||
}
|
||||
#endif
|
|
@ -35,8 +35,12 @@
|
|||
* Peter Weilbacher <mozilla@Weilbacher.org>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-os2-private.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include <float.h>
|
||||
#ifdef BUILD_CAIRO_DLL
|
||||
# define INCL_WIN
|
||||
|
@ -49,9 +53,6 @@
|
|||
# include <emx/startup.h>
|
||||
# endif
|
||||
#endif
|
||||
#include "cairoint.h"
|
||||
#include "cairo-os2-private.h"
|
||||
#include "fontconfig/fontconfig.h"
|
||||
|
||||
/*
|
||||
* Here comes the extra API for the OS/2 platform. Currently it consists
|
||||
|
@ -68,14 +69,6 @@
|
|||
/* Initialization counter: */
|
||||
static int cairo_os2_initialization_count = 0;
|
||||
|
||||
/* The mutex semaphores Cairo uses all around: */
|
||||
HMTX _cairo_scaled_font_map_mutex = 0;
|
||||
HMTX _global_image_glyph_cache_mutex = 0;
|
||||
HMTX _cairo_font_face_mutex = 0;
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
HMTX _cairo_ft_unscaled_font_map_mutex = 0;
|
||||
#endif
|
||||
|
||||
static void inline
|
||||
DisableFPUException (void)
|
||||
{
|
||||
|
@ -103,20 +96,10 @@ cairo_os2_init (void)
|
|||
|
||||
DisableFPUException ();
|
||||
|
||||
/* Create the mutex semaphores we'll use! */
|
||||
|
||||
/* cairo-font.c: */
|
||||
DosCreateMutexSem (NULL, &_cairo_scaled_font_map_mutex, 0, FALSE);
|
||||
DosCreateMutexSem (NULL, &_global_image_glyph_cache_mutex, 0, FALSE);
|
||||
DosCreateMutexSem (NULL, &_cairo_font_face_mutex, 0, FALSE);
|
||||
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
/* cairo-ft-font.c: */
|
||||
DosCreateMutexSem (NULL, &_cairo_ft_unscaled_font_map_mutex, 0, FALSE);
|
||||
#endif
|
||||
|
||||
/* Initialize FontConfig */
|
||||
FcInit ();
|
||||
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
}
|
||||
|
||||
cairo_public void
|
||||
|
@ -137,28 +120,7 @@ cairo_os2_fini (void)
|
|||
_cairo_ft_font_reset_static_data ();
|
||||
#endif
|
||||
|
||||
/* Destroy the mutex semaphores we've created! */
|
||||
/* cairo-font.c: */
|
||||
if (_cairo_scaled_font_map_mutex) {
|
||||
DosCloseMutexSem (_cairo_scaled_font_map_mutex);
|
||||
_cairo_scaled_font_map_mutex = 0;
|
||||
}
|
||||
if (_global_image_glyph_cache_mutex) {
|
||||
DosCloseMutexSem (_global_image_glyph_cache_mutex);
|
||||
_global_image_glyph_cache_mutex = 0;
|
||||
}
|
||||
if (_cairo_font_face_mutex) {
|
||||
DosCloseMutexSem (_cairo_font_face_mutex);
|
||||
_cairo_font_face_mutex = 0;
|
||||
}
|
||||
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
/* cairo-ft-font.c: */
|
||||
if (_cairo_ft_unscaled_font_map_mutex) {
|
||||
DosCloseMutexSem (_cairo_ft_unscaled_font_map_mutex);
|
||||
_cairo_ft_unscaled_font_map_mutex = 0;
|
||||
}
|
||||
#endif
|
||||
CAIRO_MUTEX_FINALIZE ();
|
||||
|
||||
/* Uninitialize FontConfig */
|
||||
FcFini ();
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#ifndef CAIRO_OUTPUT_STREAM_PRIVATE_H
|
||||
#define CAIRO_OUTPUT_STREAM_PRIVATE_H
|
||||
|
||||
typedef struct _cairo_output_stream cairo_output_stream_t;
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
typedef cairo_status_t (*cairo_output_stream_write_func_t) (cairo_output_stream_t *output_stream,
|
||||
const unsigned char *data,
|
||||
|
@ -53,7 +53,7 @@ struct _cairo_output_stream {
|
|||
cairo_bool_t closed;
|
||||
};
|
||||
|
||||
extern const cairo_private cairo_output_stream_t cairo_output_stream_nil;
|
||||
extern const cairo_private cairo_output_stream_t _cairo_output_stream_nil;
|
||||
|
||||
cairo_private void
|
||||
_cairo_output_stream_init (cairo_output_stream_t *stream,
|
||||
|
@ -107,7 +107,7 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
|
|||
const char *data,
|
||||
size_t length);
|
||||
|
||||
cairo_private int
|
||||
cairo_private void
|
||||
_cairo_dtostr (char *buffer, size_t size, double d);
|
||||
|
||||
cairo_private void
|
||||
|
|
|
@ -34,11 +34,12 @@
|
|||
* Kristian Høgsberg <krh@redhat.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
#include <locale.h>
|
||||
#include <ctype.h>
|
||||
#include "cairoint.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
|
@ -63,7 +64,7 @@ _cairo_output_stream_fini (cairo_output_stream_t *stream)
|
|||
return _cairo_output_stream_close (stream);
|
||||
}
|
||||
|
||||
const cairo_output_stream_t cairo_output_stream_nil = {
|
||||
const cairo_output_stream_t _cairo_output_stream_nil = {
|
||||
NULL, /* write_func */
|
||||
NULL, /* close_func */
|
||||
0, /* position */
|
||||
|
@ -71,7 +72,7 @@ const cairo_output_stream_t cairo_output_stream_nil = {
|
|||
FALSE /* closed */
|
||||
};
|
||||
|
||||
static const cairo_output_stream_t cairo_output_stream_nil_write_error = {
|
||||
static const cairo_output_stream_t _cairo_output_stream_nil_write_error = {
|
||||
NULL, /* write_func */
|
||||
NULL, /* close_func */
|
||||
0, /* position */
|
||||
|
@ -119,7 +120,7 @@ _cairo_output_stream_create (cairo_write_func_t write_func,
|
|||
|
||||
stream = malloc (sizeof (cairo_output_stream_with_closure_t));
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
|
||||
_cairo_output_stream_init (&stream->base, closure_write, closure_close);
|
||||
stream->write_func = write_func;
|
||||
|
@ -137,8 +138,8 @@ _cairo_output_stream_close (cairo_output_stream_t *stream)
|
|||
if (stream->closed)
|
||||
return stream->status;
|
||||
|
||||
if (stream == &cairo_output_stream_nil ||
|
||||
stream == &cairo_output_stream_nil_write_error)
|
||||
if (stream == &_cairo_output_stream_nil ||
|
||||
stream == &_cairo_output_stream_nil_write_error)
|
||||
{
|
||||
return stream->status;
|
||||
}
|
||||
|
@ -214,52 +215,49 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
|
|||
* has been relicensed under the LGPL/MPL dual license for inclusion
|
||||
* into cairo (see COPYING). -- Kristian Høgsberg <krh@redhat.com>
|
||||
*/
|
||||
|
||||
int
|
||||
void
|
||||
_cairo_dtostr (char *buffer, size_t size, double d)
|
||||
{
|
||||
struct lconv *locale_data;
|
||||
const char *decimal_point;
|
||||
int decimal_point_len;
|
||||
char *p;
|
||||
int decimal_len;
|
||||
struct lconv *locale_data;
|
||||
const char *decimal_point;
|
||||
int decimal_point_len;
|
||||
char *p;
|
||||
int decimal_len;
|
||||
|
||||
/* Omit the minus sign from negative zero. */
|
||||
if (d == 0.0)
|
||||
d = 0.0;
|
||||
/* Omit the minus sign from negative zero. */
|
||||
if (d == 0.0)
|
||||
d = 0.0;
|
||||
|
||||
snprintf (buffer, size, "%f", d);
|
||||
snprintf (buffer, size, "%f", d);
|
||||
|
||||
locale_data = localeconv ();
|
||||
decimal_point = locale_data->decimal_point;
|
||||
decimal_point_len = strlen (decimal_point);
|
||||
locale_data = localeconv ();
|
||||
decimal_point = locale_data->decimal_point;
|
||||
decimal_point_len = strlen (decimal_point);
|
||||
|
||||
assert (decimal_point_len != 0);
|
||||
p = buffer;
|
||||
assert (decimal_point_len != 0);
|
||||
p = buffer;
|
||||
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
|
||||
while (isdigit (*p))
|
||||
p++;
|
||||
while (isdigit (*p))
|
||||
p++;
|
||||
|
||||
if (strncmp (p, decimal_point, decimal_point_len) == 0) {
|
||||
*p = '.';
|
||||
decimal_len = strlen (p + decimal_point_len);
|
||||
memmove (p + 1, p + decimal_point_len, decimal_len);
|
||||
p[1 + decimal_len] = 0;
|
||||
if (strncmp (p, decimal_point, decimal_point_len) == 0) {
|
||||
*p = '.';
|
||||
decimal_len = strlen (p + decimal_point_len);
|
||||
memmove (p + 1, p + decimal_point_len, decimal_len);
|
||||
p[1 + decimal_len] = 0;
|
||||
|
||||
/* Remove trailing zeros and decimal point if possible. */
|
||||
for (p = p + decimal_len; *p == '0'; p--)
|
||||
*p = 0;
|
||||
/* Remove trailing zeros and decimal point if possible. */
|
||||
for (p = p + decimal_len; *p == '0'; p--)
|
||||
*p = 0;
|
||||
|
||||
if (*p == '.') {
|
||||
*p = 0;
|
||||
p--;
|
||||
}
|
||||
}
|
||||
|
||||
return p + 1 - buffer;
|
||||
if (*p == '.') {
|
||||
*p = 0;
|
||||
p--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
|
@ -278,10 +276,13 @@ void
|
|||
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
char buffer[512], single_fmt[32];
|
||||
char *p, *end;
|
||||
#define SINGLE_FMT_BUFFER_SIZE 32
|
||||
char buffer[512], single_fmt[SINGLE_FMT_BUFFER_SIZE];
|
||||
int single_fmt_length;
|
||||
char *p;
|
||||
const char *f, *start;
|
||||
int length_modifier;
|
||||
int length_modifier, width;
|
||||
cairo_bool_t var_width;
|
||||
|
||||
if (stream->status)
|
||||
return;
|
||||
|
@ -305,10 +306,14 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
|
|||
if (*f == '0')
|
||||
f++;
|
||||
|
||||
if (isdigit (*f)) {
|
||||
strtol (f, &end, 10);
|
||||
f = end;
|
||||
}
|
||||
var_width = FALSE;
|
||||
if (*f == '*') {
|
||||
var_width = TRUE;
|
||||
f++;
|
||||
}
|
||||
|
||||
while (isdigit (*f))
|
||||
f++;
|
||||
|
||||
length_modifier = 0;
|
||||
if (*f == 'l') {
|
||||
|
@ -316,9 +321,15 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
|
|||
f++;
|
||||
}
|
||||
|
||||
/* The only format strings exist in the cairo implementation
|
||||
* itself. So there's an internal consistency problem if any
|
||||
* of them is larger than our format buffer size. */
|
||||
single_fmt_length = f - start + 1;
|
||||
assert (single_fmt_length + 1 <= SINGLE_FMT_BUFFER_SIZE);
|
||||
|
||||
/* Reuse the format string for this conversion. */
|
||||
memcpy (single_fmt, start, f + 1 - start);
|
||||
single_fmt[f + 1 - start] = '\0';
|
||||
memcpy (single_fmt, start, single_fmt_length);
|
||||
single_fmt[single_fmt_length] = '\0';
|
||||
|
||||
/* Flush contents of buffer before snprintf()'ing into it. */
|
||||
_cairo_output_stream_write (stream, buffer, p - buffer);
|
||||
|
@ -337,15 +348,27 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
|
|||
case 'o':
|
||||
case 'x':
|
||||
case 'X':
|
||||
snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
|
||||
if (var_width) {
|
||||
width = va_arg (ap, int);
|
||||
snprintf (buffer, sizeof buffer,
|
||||
single_fmt, width, va_arg (ap, int));
|
||||
} else {
|
||||
snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
|
||||
}
|
||||
break;
|
||||
case 'd' | LENGTH_MODIFIER_LONG:
|
||||
case 'u' | LENGTH_MODIFIER_LONG:
|
||||
case 'o' | LENGTH_MODIFIER_LONG:
|
||||
case 'x' | LENGTH_MODIFIER_LONG:
|
||||
case 'X' | LENGTH_MODIFIER_LONG:
|
||||
snprintf (buffer, sizeof buffer,
|
||||
single_fmt, va_arg (ap, long int));
|
||||
if (var_width) {
|
||||
width = va_arg (ap, int);
|
||||
snprintf (buffer, sizeof buffer,
|
||||
single_fmt, width, va_arg (ap, long int));
|
||||
} else {
|
||||
snprintf (buffer, sizeof buffer,
|
||||
single_fmt, va_arg (ap, long int));
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
snprintf (buffer, sizeof buffer,
|
||||
|
@ -446,11 +469,11 @@ _cairo_output_stream_create_for_file (FILE *file)
|
|||
stdio_stream_t *stream;
|
||||
|
||||
if (file == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
|
||||
|
||||
stream = malloc (sizeof *stream);
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
|
||||
_cairo_output_stream_init (&stream->base, stdio_write, stdio_flush);
|
||||
stream->file = file;
|
||||
|
@ -466,12 +489,12 @@ _cairo_output_stream_create_for_filename (const char *filename)
|
|||
|
||||
file = fopen (filename, "wb");
|
||||
if (file == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
|
||||
|
||||
stream = malloc (sizeof *stream);
|
||||
if (stream == NULL) {
|
||||
fclose (file);
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
}
|
||||
|
||||
_cairo_output_stream_init (&stream->base, stdio_write, stdio_close);
|
||||
|
@ -512,7 +535,7 @@ _cairo_memory_stream_create (void)
|
|||
|
||||
stream = malloc (sizeof *stream);
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
|
||||
_cairo_output_stream_init (&stream->base, memory_write, memory_close);
|
||||
_cairo_array_init (&stream->array, 1);
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
*
|
||||
* 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 Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_PAGINATED_H
|
||||
#define CAIRO_PAGINATED_H
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
struct _cairo_paginated_surface_backend {
|
||||
/* Optional. Will be called once for each page.
|
||||
*
|
||||
* NOTE: With respect to the order of drawing operations as seen
|
||||
* by the target, this call will occur before any drawing
|
||||
* operations for the relevant page. However, with respect to the
|
||||
* function calls as made by the user, this call will be *after*
|
||||
* any drawing operations for the page, (that is, it will occur
|
||||
* during the user's call to cairo_show_page or cairo_copy_page).
|
||||
*/
|
||||
cairo_warn cairo_int_status_t
|
||||
(*start_page) (void *surface);
|
||||
|
||||
/* Required. Will be called twice for each page, once with an
|
||||
* argument of CAIRO_PAGINATED_MODE_ANALYZE and once with
|
||||
* CAIRO_PAGINATED_MODE_RENDER. See more details in the
|
||||
* documentation for _cairo_paginated_surface_create below.
|
||||
*/
|
||||
void
|
||||
(*set_paginated_mode) (void *surface,
|
||||
cairo_paginated_mode_t mode);
|
||||
};
|
||||
|
||||
/* A cairo_paginated_surface provides a very convenient wrapper that
|
||||
* is well-suited for doing the analysis common to most surfaces that
|
||||
* have paginated output, (that is, things directed at printers, or
|
||||
* for saving content in files such as PostScript or PDF files).
|
||||
*
|
||||
* To use the paginated surface, you'll first need to create your
|
||||
* 'real' surface using _cairo_surface_init and the standard
|
||||
* cairo_surface_backend_t. Then you also call
|
||||
* _cairo_paginated_surface_create which takes its own, much simpler,
|
||||
* cairo_paginated_surface_backend. You are free to return the result
|
||||
* of _cairo_paginated_surface_create from your public
|
||||
* cairo_<foo>_surface_create. The paginated backend will be careful
|
||||
* to not let the user see that they really got a "wrapped"
|
||||
* surface. See test-paginated-surface.c for a fairly minimal example
|
||||
* of a paginated-using surface. That should be a reasonable example
|
||||
* to follow.
|
||||
*
|
||||
* What the paginated surface does is first save all drawing
|
||||
* operations for a page into a meta-surface. Then when the user calls
|
||||
* cairo_show_page, the paginated surface performs the following
|
||||
* sequence of operations (using the backend functions passed to
|
||||
* cairo_paginated_surface_create):
|
||||
*
|
||||
* 1. Calls start_page (if non NULL). At this point, it is appropriate
|
||||
* for the target to emit any page-specific header information into
|
||||
* its output.
|
||||
*
|
||||
* 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE
|
||||
*
|
||||
* 3. Replays the meta-surface to the target surface, (with an
|
||||
* analysis surface inserted between which watches the return value
|
||||
* from each operation). This analysis stage is used to decide which
|
||||
* operations will require fallbacks.
|
||||
*
|
||||
* 4. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER
|
||||
*
|
||||
* 5. Replays a subset of the meta-surface operations to the target surface
|
||||
*
|
||||
* 6. 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.
|
||||
*
|
||||
* NOTE: The paginated surface layer assumes that the target surface
|
||||
* is "blank" by default at the beginning of each page, without any
|
||||
* need for an explicit erasea operation, (as opposed to an image
|
||||
* surface, for example, which might have uninitialized content
|
||||
* originally). As such, it optimizes away CLEAR operations that
|
||||
* happen at the beginning of each page---the target surface will not
|
||||
* even see these operations.
|
||||
*/
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_paginated_surface_create (cairo_surface_t *target,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
const cairo_paginated_surface_backend_t *backend);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_paginated_surface_get_target (cairo_surface_t *surface);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_is_paginated (cairo_surface_t *surface);
|
||||
|
||||
#endif /* CAIRO_PAGINATED_H */
|
|
@ -36,106 +36,37 @@
|
|||
#ifndef CAIRO_PAGINATED_SURFACE_H
|
||||
#define CAIRO_PAGINATED_SURFACE_H
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo.h"
|
||||
|
||||
typedef enum {
|
||||
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
|
||||
CAIRO_PAGINATED_MODE_RENDER /* render page contents */
|
||||
} cairo_paginated_mode_t;
|
||||
#include "cairo-surface-private.h"
|
||||
|
||||
typedef struct _cairo_paginated_surface_backend {
|
||||
/* Optional. Will be called once for each page.
|
||||
*
|
||||
* NOTE: With respect to the order of drawing operations as seen
|
||||
* by the target, this call will occur before any drawing
|
||||
* operations for the relevant page. However, with respect to the
|
||||
* function calls as made by the user, this call will be *after*
|
||||
* any drawing operations for the page, (that is, it will occur
|
||||
* during the user's call to cairo_show_page or cairo_copy_page).
|
||||
*/
|
||||
cairo_int_status_t
|
||||
(*start_page) (void *surface);
|
||||
typedef struct _cairo_paginated_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
/* Required. Will be called twice for each page, once with an
|
||||
* argument of CAIRO_PAGINATED_MODE_ANALYZE and once with
|
||||
* CAIRO_PAGINATED_MODE_RENDER. See more details in the
|
||||
* documentation for _cairo_paginated_surface_create below.
|
||||
*/
|
||||
void
|
||||
(*set_paginated_mode) (void *surface,
|
||||
cairo_paginated_mode_t mode);
|
||||
} cairo_paginated_surface_backend_t;
|
||||
/* The target surface to hold the final result. */
|
||||
cairo_surface_t *target;
|
||||
|
||||
/* A cairo_paginated_surface provides a very convenient wrapper that
|
||||
* is well-suited for doing the analysis common to most surfaces that
|
||||
* have paginated output, (that is, things directed at printers, or
|
||||
* for saving content in files such as PostScript or PDF files).
|
||||
*
|
||||
* To use the paginated surface, you'll first need to create your
|
||||
* 'real' surface using _cairo_surface_init and the standard
|
||||
* cairo_surface_backend_t. Then you also call
|
||||
* _cairo_paginated_surface_create which takes its own, much simpler,
|
||||
* cairo_paginated_surface_backend. You are free to return the result
|
||||
* of _cairo_paginated_surface_create from your public
|
||||
* cairo_<foo>_surface_create. The paginated backend will be careful
|
||||
* to not let the user see that they really got a "wrapped"
|
||||
* surface. See test-paginated-surface.c for a fairly minimal example
|
||||
* of a paginated-using surface. That should be a reasonable example
|
||||
* to follow.
|
||||
*
|
||||
* What the paginated surface does is first save all drawing
|
||||
* operations for a page into a meta-surface. Then when the user calls
|
||||
* cairo_show_page, the paginated surface performs the following
|
||||
* sequence of operations (using the backend functions passed to
|
||||
* cairo_paginated_surface_create):
|
||||
*
|
||||
* 1. Calls start_page (if non NULL). At this point, it is appropriate
|
||||
* for the target to emit any page-specific header information into
|
||||
* its output.
|
||||
*
|
||||
* 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE
|
||||
*
|
||||
* 3. Replays the meta-surface to the target surface, (with an
|
||||
* analysis surface inserted between which watches the return value
|
||||
* from each operation). This analysis stage is used to decide which
|
||||
* operations will require fallbacks.
|
||||
*
|
||||
* 4. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER
|
||||
*
|
||||
* 5. Replays a subset of the meta-surface operations to the target surface
|
||||
*
|
||||
* 6. 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.
|
||||
*
|
||||
* NOTE: The paginated surface layer assumes that the target surface
|
||||
* is "blank" by default at the beginning of each page, without any
|
||||
* need for an explicit erasea operation, (as opposed to an image
|
||||
* surface, for example, which might have uninitialized content
|
||||
* originally). As such, it optimizes away CLEAR operations that
|
||||
* happen at the beginning of each page---the target surface will not
|
||||
* even see these operations.
|
||||
*/
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_paginated_surface_create (cairo_surface_t *target,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
const cairo_paginated_surface_backend_t *backend);
|
||||
cairo_content_t content;
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_paginated_surface_get_target (cairo_surface_t *surface);
|
||||
/* XXX: These shouldn't actually exist. We inherit this ugliness
|
||||
* from _cairo_meta_surface_create. The width/height parameters
|
||||
* from that function also should not exist. The fix that will
|
||||
* allow us to remove all of these is to fix acquire_source_image
|
||||
* to pass an interest rectangle. */
|
||||
int width;
|
||||
int height;
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_is_paginated (cairo_surface_t *surface);
|
||||
/* Paginated-surface specific functions for the target */
|
||||
const cairo_paginated_surface_backend_t *backend;
|
||||
|
||||
/* A cairo_meta_surface to record all operations. To be replayed
|
||||
* against target, and also against image surface as necessary for
|
||||
* fallbacks. */
|
||||
cairo_surface_t *meta;
|
||||
|
||||
int page_num;
|
||||
cairo_bool_t page_is_blank;
|
||||
|
||||
} cairo_paginated_surface_t;
|
||||
|
||||
#endif /* CAIRO_PAGINATED_SURFACE_H */
|
||||
|
|
|
@ -36,45 +36,17 @@
|
|||
|
||||
/* The paginated surface layer exists to provide as much code sharing
|
||||
* as possible for the various paginated surface backends in cairo
|
||||
* (PostScript, PDF, etc.). See cairo-paginated-surface-private.h for
|
||||
* (PostScript, PDF, etc.). See cairo-paginated-private.h for
|
||||
* more details on how it works and how to use it.
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-paginated-surface-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
|
||||
typedef struct _cairo_paginated_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
/* The target surface to hold the final result. */
|
||||
cairo_surface_t *target;
|
||||
|
||||
cairo_content_t content;
|
||||
|
||||
/* XXX: These shouldn't actually exist. We inherit this ugliness
|
||||
* from _cairo_meta_surface_create. The width/height parameters
|
||||
* from that function also should not exist. The fix that will
|
||||
* allow us to remove all of these is to fix acquire_source_image
|
||||
* to pass an interest rectangle. */
|
||||
int width;
|
||||
int height;
|
||||
|
||||
/* Paginated-surface specific functions for the target */
|
||||
const cairo_paginated_surface_backend_t *backend;
|
||||
|
||||
/* A cairo_meta_surface to record all operations. To be replayed
|
||||
* against target, and also against image surface as necessary for
|
||||
* fallbacks. */
|
||||
cairo_surface_t *meta;
|
||||
|
||||
int page_num;
|
||||
cairo_bool_t page_is_blank;
|
||||
|
||||
} cairo_paginated_surface_t;
|
||||
|
||||
const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -162,11 +134,15 @@ _cairo_paginated_surface_finish (void *abstract_surface)
|
|||
if (surface->page_is_blank == FALSE || surface->page_num == 1)
|
||||
status = _cairo_paginated_surface_show_page (abstract_surface);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
cairo_surface_finish (surface->target);
|
||||
status = cairo_surface_status (surface->target);
|
||||
}
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
cairo_surface_finish (surface->meta);
|
||||
status = cairo_surface_status (surface->meta);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface->target);
|
||||
|
||||
|
@ -201,15 +177,22 @@ _cairo_paginated_surface_acquire_source_image (void *abstract_surface,
|
|||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
cairo_surface_t *image;
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_int16_t extents;
|
||||
|
||||
_cairo_surface_get_extents (surface->target, &extents);
|
||||
status = _cairo_surface_get_extents (surface->target, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
image = _cairo_paginated_surface_create_image_surface (surface,
|
||||
extents.width,
|
||||
extents.height);
|
||||
|
||||
_cairo_meta_surface_replay (surface->meta, image);
|
||||
status = _cairo_meta_surface_replay (surface->meta, image);
|
||||
if (status) {
|
||||
cairo_surface_destroy (image);
|
||||
return status;
|
||||
}
|
||||
|
||||
*image_out = (cairo_image_surface_t*) image;
|
||||
*image_extra = NULL;
|
||||
|
@ -235,13 +218,16 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
|
||||
analysis = _cairo_analysis_surface_create (surface->target,
|
||||
surface->width, surface->height);
|
||||
if (analysis == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
|
||||
_cairo_meta_surface_replay (surface->meta, analysis);
|
||||
status = _cairo_meta_surface_replay (surface->meta, analysis);
|
||||
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
|
||||
|
||||
if (analysis->status) {
|
||||
status = analysis->status;
|
||||
if (status || analysis->status) {
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = analysis->status;
|
||||
cairo_surface_destroy (analysis);
|
||||
return status;
|
||||
}
|
||||
|
@ -257,26 +243,29 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
surface->height * y_scale);
|
||||
_cairo_surface_set_device_scale (image, x_scale, y_scale);
|
||||
|
||||
_cairo_meta_surface_replay (surface->meta, image);
|
||||
status = _cairo_meta_surface_replay (surface->meta, image);
|
||||
if (status)
|
||||
goto CLEANUP_IMAGE;
|
||||
|
||||
pattern = cairo_pattern_create_for_surface (image);
|
||||
cairo_matrix_init_scale (&matrix, x_scale, y_scale);
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
|
||||
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
|
||||
status = _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
CLEANUP_IMAGE:
|
||||
cairo_surface_destroy (image);
|
||||
}
|
||||
else
|
||||
{
|
||||
_cairo_meta_surface_replay (surface->meta, surface->target);
|
||||
status = _cairo_meta_surface_replay (surface->meta, surface->target);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (analysis);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -298,7 +287,9 @@ _cairo_paginated_surface_copy_page (void *abstract_surface)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_paint_page (surface);
|
||||
status = _paint_page (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
surface->page_num++;
|
||||
|
||||
|
@ -323,9 +314,16 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_paint_page (surface);
|
||||
status = _paint_page (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_surface_show_page (surface->target);
|
||||
status = _cairo_surface_show_page (surface->target);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (cairo_surface_status (surface->meta))
|
||||
return cairo_surface_status (surface->meta);
|
||||
|
||||
cairo_surface_destroy (surface->meta);
|
||||
|
||||
|
@ -485,6 +483,7 @@ _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
|
||||
|
@ -505,13 +504,19 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
|
|||
cairo_rectangle_int16_t extents;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
_cairo_surface_get_extents (other->target, &extents);
|
||||
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);
|
||||
|
||||
_cairo_meta_surface_replay (other->meta, surface);
|
||||
status = _cairo_meta_surface_replay (other->meta, surface);
|
||||
if (status) {
|
||||
cairo_surface_destroy (surface);
|
||||
surface = (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
return surface;
|
||||
#endif
|
||||
|
|
|
@ -51,7 +51,7 @@ _cairo_path_bounder_init (cairo_path_bounder_t *bounder);
|
|||
static void
|
||||
_cairo_path_bounder_fini (cairo_path_bounder_t *bounder);
|
||||
|
||||
static cairo_status_t
|
||||
static void
|
||||
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *point);
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -81,7 +81,7 @@ _cairo_path_bounder_fini (cairo_path_bounder_t *bounder)
|
|||
bounder->has_point = 0;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
static void
|
||||
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *point)
|
||||
{
|
||||
if (bounder->has_point) {
|
||||
|
@ -104,8 +104,6 @@ _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *poi
|
|||
|
||||
bounder->has_point = 1;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
|
@ -88,37 +88,28 @@ _cairo_filler_fini (cairo_filler_t *filler)
|
|||
static cairo_status_t
|
||||
_cairo_filler_move_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_filler_t *filler = closure;
|
||||
cairo_polygon_t *polygon = &filler->polygon;
|
||||
|
||||
status = _cairo_polygon_close (polygon);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_polygon_move_to (polygon, point);
|
||||
if (status)
|
||||
return status;
|
||||
_cairo_polygon_close (polygon);
|
||||
_cairo_polygon_move_to (polygon, point);
|
||||
|
||||
filler->current_point = *point;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return _cairo_polygon_status (&filler->polygon);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_filler_line_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_filler_t *filler = closure;
|
||||
cairo_polygon_t *polygon = &filler->polygon;
|
||||
|
||||
status = _cairo_polygon_line_to (polygon, point);
|
||||
if (status)
|
||||
return status;
|
||||
_cairo_polygon_line_to (polygon, point);
|
||||
|
||||
filler->current_point = *point;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return _cairo_polygon_status (&filler->polygon);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -138,15 +129,12 @@ _cairo_filler_curve_to (void *closure,
|
|||
if (status == CAIRO_INT_STATUS_DEGENERATE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_spline_decompose (&spline, filler->tolerance);
|
||||
status = _cairo_spline_decompose (&spline, filler->tolerance);
|
||||
if (status)
|
||||
goto CLEANUP_SPLINE;
|
||||
|
||||
for (i = 1; i < spline.num_points; i++) {
|
||||
status = _cairo_polygon_line_to (polygon, &spline.points[i]);
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
for (i = 1; i < spline.num_points; i++)
|
||||
_cairo_polygon_line_to (polygon, &spline.points[i]);
|
||||
|
||||
CLEANUP_SPLINE:
|
||||
_cairo_spline_fini (&spline);
|
||||
|
@ -159,15 +147,12 @@ _cairo_filler_curve_to (void *closure,
|
|||
static cairo_status_t
|
||||
_cairo_filler_close_path (void *closure)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_filler_t *filler = closure;
|
||||
cairo_polygon_t *polygon = &filler->polygon;
|
||||
|
||||
status = _cairo_polygon_close (polygon);
|
||||
if (status)
|
||||
return status;
|
||||
_cairo_polygon_close (polygon);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return _cairo_polygon_status (polygon);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -201,7 +186,8 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
|
|||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_polygon_close (&filler.polygon);
|
||||
_cairo_polygon_close (&filler.polygon);
|
||||
status = _cairo_polygon_status (&filler.polygon);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-path-fixed-private.h"
|
||||
|
@ -356,8 +355,8 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path,
|
|||
cairo_point_t *points,
|
||||
int num_points)
|
||||
{
|
||||
if (path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE ||
|
||||
path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
|
||||
if ((unsigned int) path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE ||
|
||||
(unsigned int) path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
|
||||
{
|
||||
cairo_path_buf_t *buf;
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ typedef struct cairo_stroker {
|
|||
} cairo_stroker_t;
|
||||
|
||||
/* private functions */
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_stroker_init (cairo_stroker_t *stroker,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
cairo_matrix_t *ctm,
|
||||
|
@ -148,7 +148,7 @@ _cairo_stroker_step_dash (cairo_stroker_t *stroker, double step)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_stroker_init (cairo_stroker_t *stroker,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
cairo_matrix_t *ctm,
|
||||
|
@ -156,15 +156,18 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
|
|||
double tolerance,
|
||||
cairo_traps_t *traps)
|
||||
{
|
||||
cairo_status_t status;
|
||||
stroker->style = stroke_style;
|
||||
stroker->ctm = ctm;
|
||||
stroker->ctm_inverse = ctm_inverse;
|
||||
stroker->tolerance = tolerance;
|
||||
stroker->traps = traps;
|
||||
|
||||
_cairo_pen_init (&stroker->pen,
|
||||
stroke_style->line_width / 2.0,
|
||||
tolerance, ctm);
|
||||
status = _cairo_pen_init (&stroker->pen,
|
||||
stroke_style->line_width / 2.0,
|
||||
tolerance, ctm);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
stroker->has_current_face = FALSE;
|
||||
stroker->has_first_face = FALSE;
|
||||
|
@ -174,6 +177,8 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
|
|||
_cairo_stroker_start_dash (stroker);
|
||||
else
|
||||
stroker->dashed = FALSE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -205,6 +210,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
|
|||
{
|
||||
int clockwise = _cairo_stroker_face_clockwise (out, in);
|
||||
cairo_point_t *inpt, *outpt;
|
||||
cairo_status_t status;
|
||||
|
||||
if (in->cw.x == out->cw.x
|
||||
&& in->cw.y == out->cw.y
|
||||
|
@ -231,13 +237,21 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
|
|||
|
||||
tri[0] = in->point;
|
||||
if (clockwise) {
|
||||
_cairo_pen_find_active_ccw_vertex_index (pen, &in->dev_vector, &start);
|
||||
status = _cairo_pen_find_active_ccw_vertex_index (pen, &in->dev_vector, &start);
|
||||
if (status)
|
||||
return status;
|
||||
step = -1;
|
||||
_cairo_pen_find_active_ccw_vertex_index (pen, &out->dev_vector, &stop);
|
||||
status = _cairo_pen_find_active_ccw_vertex_index (pen, &out->dev_vector, &stop);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
_cairo_pen_find_active_cw_vertex_index (pen, &in->dev_vector, &start);
|
||||
status = _cairo_pen_find_active_cw_vertex_index (pen, &in->dev_vector, &start);
|
||||
if (status)
|
||||
return status;
|
||||
step = +1;
|
||||
_cairo_pen_find_active_cw_vertex_index (pen, &out->dev_vector, &stop);
|
||||
status = _cairo_pen_find_active_cw_vertex_index (pen, &out->dev_vector, &stop);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
i = start;
|
||||
|
@ -245,7 +259,9 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
|
|||
while (i != stop) {
|
||||
tri[2] = in->point;
|
||||
_translate_point (&tri[2], &pen->vertices[i].point);
|
||||
_cairo_traps_tessellate_triangle (stroker->traps, tri);
|
||||
status = _cairo_traps_tessellate_triangle (stroker->traps, tri);
|
||||
if (status)
|
||||
return status;
|
||||
tri[1] = tri[2];
|
||||
i += step;
|
||||
if (i < 0)
|
||||
|
@ -378,17 +394,23 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
|
|||
cairo_pen_t *pen = &stroker->pen;
|
||||
|
||||
slope = f->dev_vector;
|
||||
_cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
|
||||
status = _cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
|
||||
if (status)
|
||||
return status;
|
||||
slope.dx = -slope.dx;
|
||||
slope.dy = -slope.dy;
|
||||
_cairo_pen_find_active_cw_vertex_index (pen, &slope, &stop);
|
||||
status = _cairo_pen_find_active_cw_vertex_index (pen, &slope, &stop);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
tri[0] = f->point;
|
||||
tri[1] = f->cw;
|
||||
for (i=start; i != stop; i = (i+1) % pen->num_vertices) {
|
||||
tri[2] = f->point;
|
||||
_translate_point (&tri[2], &pen->vertices[i].point);
|
||||
_cairo_traps_tessellate_triangle (stroker->traps, tri);
|
||||
status = _cairo_traps_tessellate_triangle (stroker->traps, tri);
|
||||
if (status)
|
||||
return status;
|
||||
tri[1] = tri[2];
|
||||
}
|
||||
tri[2] = f->ccw;
|
||||
|
@ -419,8 +441,14 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
|
|||
_cairo_polygon_line_to (&polygon, &occw);
|
||||
_cairo_polygon_line_to (&polygon, &f->ccw);
|
||||
_cairo_polygon_close (&polygon);
|
||||
status = _cairo_polygon_status (&polygon);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
status = _cairo_bentley_ottmann_tessellate_polygon (stroker->traps,
|
||||
&polygon,
|
||||
CAIRO_FILL_RULE_WINDING);
|
||||
}
|
||||
|
||||
status = _cairo_bentley_ottmann_tessellate_polygon (stroker->traps, &polygon, CAIRO_FILL_RULE_WINDING);
|
||||
_cairo_polygon_fini (&polygon);
|
||||
|
||||
return status;
|
||||
|
@ -967,9 +995,11 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
|
|||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
_cairo_stroker_init (&stroker, stroke_style,
|
||||
ctm, ctm_inverse, tolerance,
|
||||
traps);
|
||||
status = _cairo_stroker_init (&stroker, stroke_style,
|
||||
ctm, ctm_inverse, tolerance,
|
||||
traps);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (stroker.style->dash)
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
|
|
|
@ -34,9 +34,10 @@
|
|||
* Carl D. Worth <cworth@redhat.com>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-path-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-gstate-private.h"
|
||||
|
||||
const cairo_path_t _cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
|
||||
|
||||
|
@ -135,6 +136,7 @@ _cairo_path_count (cairo_path_t *path,
|
|||
double tolerance,
|
||||
cairo_bool_t flatten)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cpc_t cpc;
|
||||
|
||||
cpc.count = 0;
|
||||
|
@ -142,15 +144,17 @@ _cairo_path_count (cairo_path_t *path,
|
|||
cpc.current_point.x = 0;
|
||||
cpc.current_point.y = 0;
|
||||
|
||||
_cairo_path_fixed_interpret (path_fixed,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cpc_move_to,
|
||||
_cpc_line_to,
|
||||
flatten ?
|
||||
_cpc_curve_to_flatten :
|
||||
_cpc_curve_to,
|
||||
_cpc_close_path,
|
||||
&cpc);
|
||||
status = _cairo_path_fixed_interpret (path_fixed,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cpc_move_to,
|
||||
_cpc_line_to,
|
||||
flatten ?
|
||||
_cpc_curve_to_flatten :
|
||||
_cpc_curve_to,
|
||||
_cpc_close_path,
|
||||
&cpc);
|
||||
if (status)
|
||||
return -1;
|
||||
|
||||
return cpc.count;
|
||||
}
|
||||
|
@ -275,7 +279,8 @@ _cpp_curve_to_flatten (void *closure,
|
|||
if (status == CAIRO_INT_STATUS_DEGENERATE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_spline_decompose (&spline, cpp->gstate->tolerance);
|
||||
status = _cairo_spline_decompose (&spline,
|
||||
_cairo_gstate_get_tolerance (cpp->gstate));
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
|
@ -305,12 +310,13 @@ _cpp_close_path (void *closure)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_path_populate (cairo_path_t *path,
|
||||
cairo_path_fixed_t *path_fixed,
|
||||
cairo_gstate_t *gstate,
|
||||
cairo_bool_t flatten)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cpp_t cpp;
|
||||
|
||||
cpp.data = path->data;
|
||||
|
@ -318,18 +324,22 @@ _cairo_path_populate (cairo_path_t *path,
|
|||
cpp.current_point.x = 0;
|
||||
cpp.current_point.y = 0;
|
||||
|
||||
_cairo_path_fixed_interpret (path_fixed,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cpp_move_to,
|
||||
_cpp_line_to,
|
||||
flatten ?
|
||||
_cpp_curve_to_flatten :
|
||||
_cpp_curve_to,
|
||||
_cpp_close_path,
|
||||
&cpp);
|
||||
status = _cairo_path_fixed_interpret (path_fixed,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cpp_move_to,
|
||||
_cpp_line_to,
|
||||
flatten ?
|
||||
_cpp_curve_to_flatten :
|
||||
_cpp_curve_to,
|
||||
_cpp_close_path,
|
||||
&cpp);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Sanity check the count */
|
||||
assert (cpp.data - path->data == path->num_data);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_path_t *
|
||||
|
@ -337,6 +347,10 @@ _cairo_path_create_in_error (cairo_status_t status)
|
|||
{
|
||||
cairo_path_t *path;
|
||||
|
||||
/* special case NO_MEMORY so as to avoid allocations */
|
||||
if (status == CAIRO_STATUS_NO_MEMORY)
|
||||
return (cairo_path_t*) &_cairo_path_nil;
|
||||
|
||||
path = malloc (sizeof (cairo_path_t));
|
||||
if (path == NULL)
|
||||
return (cairo_path_t*) &_cairo_path_nil;
|
||||
|
@ -360,7 +374,12 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed,
|
|||
return (cairo_path_t*) &_cairo_path_nil;
|
||||
|
||||
path->num_data = _cairo_path_count (path, path_fixed,
|
||||
gstate->tolerance, flatten);
|
||||
_cairo_gstate_get_tolerance (gstate),
|
||||
flatten);
|
||||
if (path->num_data <= 0) {
|
||||
free (path);
|
||||
return (cairo_path_t*) &_cairo_path_nil;
|
||||
}
|
||||
|
||||
path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
|
||||
if (path->data == NULL) {
|
||||
|
@ -368,10 +387,8 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed,
|
|||
return (cairo_path_t*) &_cairo_path_nil;
|
||||
}
|
||||
|
||||
path->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_path_populate (path, path_fixed,
|
||||
gstate, flatten);
|
||||
path->status = _cairo_path_populate (path, path_fixed,
|
||||
gstate, flatten);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
@ -460,6 +477,7 @@ _cairo_path_append_to_context (const cairo_path_t *path,
|
|||
{
|
||||
int i;
|
||||
cairo_path_data_t *p;
|
||||
cairo_status_t status;
|
||||
|
||||
for (i=0; i < path->num_data; i += path->data[i].header.length) {
|
||||
p = &path->data[i];
|
||||
|
@ -492,6 +510,10 @@ _cairo_path_append_to_context (const cairo_path_t *path,
|
|||
default:
|
||||
return CAIRO_STATUS_INVALID_PATH_DATA;
|
||||
}
|
||||
|
||||
status = cairo_status (cr);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
const cairo_solid_pattern_t cairo_pattern_nil = {
|
||||
const cairo_solid_pattern_t _cairo_pattern_nil = {
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
|
@ -40,7 +40,7 @@ const cairo_solid_pattern_t cairo_pattern_nil = {
|
|||
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
|
||||
};
|
||||
|
||||
static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
|
||||
static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_NULL_POINTER,/* status */
|
||||
|
@ -50,6 +50,16 @@ static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = {
|
|||
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
|
||||
};
|
||||
|
||||
const cairo_solid_pattern_t cairo_pattern_none = {
|
||||
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
|
||||
CAIRO_REF_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_SUCCESS, /* status */
|
||||
{ 0, 0, 0, NULL }, /* user_data */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
|
||||
};
|
||||
|
||||
/**
|
||||
* _cairo_pattern_set_error:
|
||||
* @pattern: a pattern
|
||||
|
@ -82,6 +92,8 @@ _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;
|
||||
pattern->ref_count = 1;
|
||||
pattern->status = CAIRO_STATUS_SUCCESS;
|
||||
|
@ -98,7 +110,7 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
|
|||
cairo_matrix_init_identity (&pattern->matrix);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
|
||||
const cairo_gradient_pattern_t *other)
|
||||
{
|
||||
|
@ -127,21 +139,23 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
|
|||
pattern->stops_size = 0;
|
||||
pattern->n_stops = 0;
|
||||
_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
|
||||
return;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
memcpy (pattern->stops, other->stops,
|
||||
other->n_stops * sizeof (pixman_gradient_stop_t));
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
cairo_status_t
|
||||
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
||||
const cairo_pattern_t *other)
|
||||
{
|
||||
if (other->status) {
|
||||
_cairo_pattern_set_error (pattern, other->status);
|
||||
return;
|
||||
return other->status;
|
||||
}
|
||||
|
||||
switch (other->type) {
|
||||
|
@ -162,12 +176,18 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
|||
case CAIRO_PATTERN_TYPE_RADIAL: {
|
||||
cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
|
||||
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_gradient_pattern_init_copy (dst, src);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_gradient_pattern_init_copy (dst, src);
|
||||
} break;
|
||||
}
|
||||
|
||||
pattern->ref_count = 1;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -197,10 +217,12 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
|
|||
|
||||
void
|
||||
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
|
||||
const cairo_color_t *color)
|
||||
const cairo_color_t *color,
|
||||
cairo_content_t content)
|
||||
{
|
||||
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
|
||||
pattern->color = *color;
|
||||
pattern->content = content;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -209,7 +231,7 @@ _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
|
|||
{
|
||||
if (surface->status) {
|
||||
/* Force to solid to simplify the pattern_fini process. */
|
||||
pattern->base.type = CAIRO_PATTERN_TYPE_SOLID;
|
||||
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
|
||||
_cairo_pattern_set_error (&pattern->base, surface->status);
|
||||
return;
|
||||
}
|
||||
|
@ -257,29 +279,71 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
|
|||
pattern->gradient.c2.radius = _cairo_fixed_from_double (fabs (radius1));
|
||||
}
|
||||
|
||||
/* We use a small freed pattern cache here, because we don't want to
|
||||
* constantly reallocate simple colors. */
|
||||
#define MAX_PATTERN_CACHE_SIZE 4
|
||||
static struct {
|
||||
cairo_solid_pattern_t *patterns[MAX_PATTERN_CACHE_SIZE];
|
||||
int size;
|
||||
} solid_pattern_cache;
|
||||
|
||||
cairo_pattern_t *
|
||||
_cairo_pattern_create_solid (const cairo_color_t *color)
|
||||
_cairo_pattern_create_solid (const cairo_color_t *color,
|
||||
cairo_content_t content)
|
||||
{
|
||||
cairo_solid_pattern_t *pattern;
|
||||
cairo_solid_pattern_t *pattern = NULL;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
|
||||
|
||||
if (solid_pattern_cache.size) {
|
||||
int i = --solid_pattern_cache.size %
|
||||
ARRAY_LENGTH (solid_pattern_cache.patterns);
|
||||
pattern = solid_pattern_cache.patterns[i];
|
||||
solid_pattern_cache.patterns[i] = NULL;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
|
||||
|
||||
if (pattern == NULL) {
|
||||
/* None cached, need to create a new pattern. */
|
||||
pattern = malloc (sizeof (cairo_solid_pattern_t));
|
||||
}
|
||||
|
||||
pattern = malloc (sizeof (cairo_solid_pattern_t));
|
||||
if (pattern == NULL)
|
||||
return (cairo_pattern_t *) &cairo_pattern_nil.base;
|
||||
|
||||
_cairo_pattern_init_solid (pattern, color);
|
||||
pattern = (cairo_solid_pattern_t *) &_cairo_pattern_nil;
|
||||
else
|
||||
_cairo_pattern_init_solid (pattern, color, content);
|
||||
|
||||
return &pattern->base;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pattern_reset_solid_pattern_cache (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
|
||||
|
||||
for (i = 0; i < MIN (ARRAY_LENGTH (solid_pattern_cache.patterns), solid_pattern_cache.size); i++) {
|
||||
free (solid_pattern_cache.patterns[i]);
|
||||
solid_pattern_cache.patterns[i] = NULL;
|
||||
}
|
||||
solid_pattern_cache.size = 0;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
|
||||
}
|
||||
|
||||
static const cairo_pattern_t *
|
||||
_cairo_pattern_create_in_error (cairo_status_t status)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
|
||||
pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK));
|
||||
if (cairo_pattern_status (pattern))
|
||||
return pattern;
|
||||
if (status == CAIRO_STATUS_NO_MEMORY)
|
||||
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
|
||||
|
||||
pattern = _cairo_pattern_create_solid (_cairo_stock_color (CAIRO_STOCK_BLACK),
|
||||
CAIRO_CONTENT_COLOR);
|
||||
/* no-op on a pattern already in error i.e the _cairo_pattern_nil */
|
||||
_cairo_pattern_set_error (pattern, status);
|
||||
|
||||
return pattern;
|
||||
|
@ -317,7 +381,8 @@ cairo_pattern_create_rgb (double red, double green, double blue)
|
|||
|
||||
_cairo_color_init_rgb (&color, red, green, blue);
|
||||
|
||||
pattern = _cairo_pattern_create_solid (&color);
|
||||
pattern = _cairo_pattern_create_solid (&color,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
if (pattern->status)
|
||||
_cairo_error (pattern->status);
|
||||
|
||||
|
@ -360,7 +425,8 @@ cairo_pattern_create_rgba (double red, double green, double blue,
|
|||
|
||||
_cairo_color_init_rgba (&color, red, green, blue, alpha);
|
||||
|
||||
pattern = _cairo_pattern_create_solid (&color);
|
||||
pattern = _cairo_pattern_create_solid (&color,
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
if (pattern->status)
|
||||
_cairo_error (pattern->status);
|
||||
|
||||
|
@ -389,7 +455,7 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
|
|||
cairo_surface_pattern_t *pattern;
|
||||
|
||||
if (surface == NULL)
|
||||
return (cairo_pattern_t*) &cairo_pattern_nil_null_pointer;
|
||||
return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer;
|
||||
|
||||
if (surface->status)
|
||||
return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
|
||||
|
@ -397,7 +463,7 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
|
|||
pattern = malloc (sizeof (cairo_surface_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_pattern_t *)&cairo_pattern_nil.base;
|
||||
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_for_surface (pattern, surface);
|
||||
|
@ -440,7 +506,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
|
|||
pattern = malloc (sizeof (cairo_linear_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_pattern_t *) &cairo_pattern_nil.base;
|
||||
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
|
||||
|
@ -458,7 +524,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
|
|||
* @radius1: radius of the end circle
|
||||
*
|
||||
* Creates a new radial gradient cairo_pattern_t between the two
|
||||
* circles defined by (x0, y0, c0) and (x1, y1, c0). Before using the
|
||||
* circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1). Before using the
|
||||
* gradient pattern, a number of color stops should be defined using
|
||||
* cairo_pattern_add_color_stop_rgb() or
|
||||
* cairo_pattern_add_color_stop_rgba().
|
||||
|
@ -485,7 +551,7 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
|
|||
pattern = malloc (sizeof (cairo_radial_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_pattern_t *) &cairo_pattern_nil.base;
|
||||
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
|
||||
|
@ -576,7 +642,25 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
|
|||
return;
|
||||
|
||||
_cairo_pattern_fini (pattern);
|
||||
free (pattern);
|
||||
|
||||
/* maintain a small cache of freed patterns */
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||
int i;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
|
||||
|
||||
i = solid_pattern_cache.size++ %
|
||||
ARRAY_LENGTH (solid_pattern_cache.patterns);
|
||||
/* swap an old pattern for this 'cache-hot' pattern */
|
||||
if (solid_pattern_cache.patterns[i])
|
||||
free (solid_pattern_cache.patterns[i]);
|
||||
|
||||
solid_pattern_cache.patterns[i] = (cairo_solid_pattern_t *) pattern;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
|
||||
} else {
|
||||
free (pattern);
|
||||
}
|
||||
}
|
||||
slim_hidden_def (cairo_pattern_destroy);
|
||||
|
||||
|
@ -659,7 +743,7 @@ _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
|
|||
{
|
||||
pixman_gradient_stop_t *new_stops;
|
||||
int old_size = pattern->stops_size;
|
||||
int embedded_size = sizeof (pattern->stops_embedded) / sizeof (pattern->stops_embedded[0]);
|
||||
int embedded_size = ARRAY_LENGTH (pattern->stops_embedded);
|
||||
int new_size = 2 * MAX (old_size, 4);
|
||||
|
||||
/* we have a local buffer at pattern->stops_embedded. try to fulfill the request
|
||||
|
@ -750,6 +834,13 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
|
|||
*
|
||||
* The color is specified in the same way as in cairo_set_source_rgb().
|
||||
*
|
||||
* If two (or more) stops are specified with identical offset values,
|
||||
* they will be sorted according to the order in which the stops are
|
||||
* added, (stops added earlier will compare less than stops added
|
||||
* later). This can be useful for reliably making sharp color
|
||||
* transitions instead of the typical blend.
|
||||
*
|
||||
*
|
||||
* Note: If the pattern is not a gradient pattern, (eg. a linear or
|
||||
* radial pattern), then the pattern will be put into an error status
|
||||
* with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
|
||||
|
@ -797,6 +888,12 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
|
|||
*
|
||||
* The color is specified in the same way as in cairo_set_source_rgba().
|
||||
*
|
||||
* If two (or more) stops are specified with identical offset values,
|
||||
* they will be sorted according to the order in which the stops are
|
||||
* added, (stops added earlier will compare less than stops added
|
||||
* later). This can be useful for reliably making sharp color
|
||||
* transitions instead of the typical blend.
|
||||
*
|
||||
* Note: If the pattern is not a gradient pattern, (eg. a linear or
|
||||
* radial pattern), then the pattern will be put into an error status
|
||||
* with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
|
||||
|
@ -865,10 +962,18 @@ void
|
|||
cairo_pattern_set_matrix (cairo_pattern_t *pattern,
|
||||
const cairo_matrix_t *matrix)
|
||||
{
|
||||
cairo_matrix_t inverse;
|
||||
cairo_status_t status;
|
||||
|
||||
if (pattern->status)
|
||||
return;
|
||||
|
||||
pattern->matrix = *matrix;
|
||||
|
||||
inverse = *matrix;
|
||||
status = cairo_matrix_invert (&inverse);
|
||||
if (status)
|
||||
_cairo_pattern_set_error (pattern, status);
|
||||
}
|
||||
slim_hidden_def (cairo_pattern_set_matrix);
|
||||
|
||||
|
@ -958,7 +1063,8 @@ void
|
|||
_cairo_pattern_transform (cairo_pattern_t *pattern,
|
||||
const cairo_matrix_t *ctm_inverse)
|
||||
{
|
||||
assert (pattern->status == CAIRO_STATUS_SUCCESS);
|
||||
if (pattern->status)
|
||||
return;
|
||||
|
||||
cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
|
||||
}
|
||||
|
@ -978,7 +1084,7 @@ _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
|
|||
cairo_fixed_t factors[3];
|
||||
int i;
|
||||
|
||||
/* To classidy a pattern as horizontal or vertical, we first
|
||||
/* To classify a pattern as horizontal or vertical, we first
|
||||
* compute the (fixed point) factors at the corners of the
|
||||
* pattern. We actually only need 3/4 corners, so we skip the
|
||||
* fourth.
|
||||
|
@ -1113,7 +1219,11 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
|||
pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR);
|
||||
|
||||
_cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform);
|
||||
pixman_image_set_transform (pixman_image, &pixman_transform);
|
||||
if (pixman_image_set_transform (pixman_image, &pixman_transform)) {
|
||||
cairo_surface_destroy (&image->base);
|
||||
pixman_image_destroy (pixman_image);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
switch (pattern->base.extend) {
|
||||
case CAIRO_EXTEND_NONE:
|
||||
|
@ -1156,6 +1266,35 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* We maintain a small cache here, because we don't want to constantly
|
||||
* recreate surfaces for simple solid colors. */
|
||||
#define MAX_SURFACE_CACHE_SIZE 16
|
||||
static struct {
|
||||
struct _cairo_pattern_solid_surface_cache{
|
||||
cairo_color_t color;
|
||||
cairo_surface_t *surface;
|
||||
} cache[MAX_SURFACE_CACHE_SIZE];
|
||||
int size;
|
||||
} solid_surface_cache;
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_pattern_solid_surface_matches (
|
||||
const struct _cairo_pattern_solid_surface_cache *cache,
|
||||
const cairo_solid_pattern_t *pattern,
|
||||
cairo_surface_t *dst)
|
||||
{
|
||||
if (cache->surface->ref_count != 1)
|
||||
return FALSE;
|
||||
|
||||
if (! _cairo_color_equal (&cache->color, &pattern->color))
|
||||
return FALSE;
|
||||
|
||||
if (! _cairo_surface_is_similar (cache->surface, dst, pattern->content))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
|
||||
cairo_surface_t *dst,
|
||||
|
@ -1166,20 +1305,94 @@ _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
|
|||
cairo_surface_t **out,
|
||||
cairo_surface_attributes_t *attribs)
|
||||
{
|
||||
*out = _cairo_surface_create_similar_solid (dst,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
1, 1,
|
||||
&pattern->color);
|
||||
if ((*out)->status)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
static int i;
|
||||
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t status;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
|
||||
|
||||
/* Check cache first */
|
||||
if (i < solid_surface_cache.size &&
|
||||
_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
|
||||
pattern,
|
||||
dst))
|
||||
{
|
||||
if (! _cairo_surface_reset (solid_surface_cache.cache[i].surface))
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < solid_surface_cache.size; i++) {
|
||||
if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
|
||||
pattern,
|
||||
dst))
|
||||
{
|
||||
if (! _cairo_surface_reset (solid_surface_cache.cache[i].surface))
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not cached, need to create new */
|
||||
surface = _cairo_surface_create_similar_solid (dst,
|
||||
pattern->content,
|
||||
1, 1,
|
||||
&pattern->color,
|
||||
&pattern->base);
|
||||
if (surface->status) {
|
||||
status = surface->status;
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
if (! _cairo_surface_is_similar (surface, dst, pattern->content)) {
|
||||
/* in the rare event of a substitute surface being returned (e.g.
|
||||
* malloc failure) don't cache the fallback surface */
|
||||
*out = surface;
|
||||
goto NOCACHE;
|
||||
}
|
||||
|
||||
/* Cache new */
|
||||
if (solid_surface_cache.size < MAX_SURFACE_CACHE_SIZE) {
|
||||
solid_surface_cache.size++;
|
||||
} else {
|
||||
i = rand () % MAX_SURFACE_CACHE_SIZE;
|
||||
|
||||
/* Evict old */
|
||||
cairo_surface_destroy (solid_surface_cache.cache[i].surface);
|
||||
}
|
||||
|
||||
solid_surface_cache.cache[i].color = pattern->color;
|
||||
solid_surface_cache.cache[i].surface = surface;
|
||||
|
||||
DONE:
|
||||
*out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
|
||||
|
||||
NOCACHE:
|
||||
attribs->x_offset = attribs->y_offset = 0;
|
||||
cairo_matrix_init_identity (&attribs->matrix);
|
||||
attribs->extend = CAIRO_EXTEND_REPEAT;
|
||||
attribs->filter = CAIRO_FILTER_NEAREST;
|
||||
attribs->acquired = FALSE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
UNLOCK:
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pattern_reset_solid_surface_cache (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
|
||||
|
||||
for (i = 0; i < solid_surface_cache.size; i++)
|
||||
cairo_surface_destroy (solid_surface_cache.cache[i].surface);
|
||||
solid_surface_cache.size = 0;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1203,7 +1416,7 @@ _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
|
|||
|
||||
solid = (cairo_solid_pattern_t *) pattern;
|
||||
|
||||
return CAIRO_ALPHA_IS_OPAQUE (solid->color.alpha);
|
||||
return CAIRO_COLOR_IS_OPAQUE (&solid->color);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
@ -1212,7 +1425,7 @@ _gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
|
|||
unsigned int i;
|
||||
|
||||
for (i = 0; i < gradient->n_stops; i++)
|
||||
if (! CAIRO_ALPHA_IS_OPAQUE (gradient->stops[i].color.alpha))
|
||||
if (! CAIRO_ALPHA_SHORT_IS_OPAQUE (gradient->stops[i].color.alpha))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
@ -1302,14 +1515,25 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
|
||||
attr->extend = CAIRO_EXTEND_REPEAT;
|
||||
|
||||
/* TODO: Instead of rendering pattern->surface four times to
|
||||
* out, we should first copy pattern->surface to surface similar
|
||||
* to dst and then copy that four times to out. This may cause
|
||||
* an extra copy in the case of image destination, but for X servers,
|
||||
* this will send pattern->surface just once over the wire instead
|
||||
* of current four.
|
||||
*/
|
||||
x = extents.x;
|
||||
y = extents.y;
|
||||
w = 2 * extents.width;
|
||||
h = 2 * extents.height;
|
||||
|
||||
*out = cairo_surface_create_similar (dst, dst->content, w, h);
|
||||
if (!*out)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
status = cairo_surface_status (*out);
|
||||
if (status) {
|
||||
cairo_surface_destroy (*out);
|
||||
*out = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
(*out)->device_transform = pattern->surface->device_transform;
|
||||
(*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
|
||||
|
@ -1334,6 +1558,11 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
status = cairo_status (cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
if (status) {
|
||||
cairo_surface_destroy (*out);
|
||||
*out = NULL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1386,11 +1615,16 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
* in a region larger than the surface, but we never
|
||||
* want to clone more than the surface itself, (we
|
||||
* know we're not repeating at this point due to the
|
||||
* above. */
|
||||
x = MAX (0, floor (x1));
|
||||
y = MAX (0, floor (y1));
|
||||
width = MIN (extents.width, ceil (x2)) - x;
|
||||
height = MIN (extents.height, ceil (y2)) - y;
|
||||
* above.
|
||||
*
|
||||
* XXX: The one padding here is to account for filter
|
||||
* radius. It's a workaround right now, until we get a
|
||||
* proper fix. (see bug #10508)
|
||||
*/
|
||||
x = MAX (0, floor (x1) - 1);
|
||||
y = MAX (0, floor (y1) - 1);
|
||||
width = MIN (extents.width, ceil (x2) + 1) - x;
|
||||
height = MIN (extents.height, ceil (y2) + 1) - y;
|
||||
}
|
||||
x += tx;
|
||||
y += ty;
|
||||
|
@ -1405,8 +1639,12 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
|
||||
*out = cairo_surface_create_similar (dst, dst->content,
|
||||
width, height);
|
||||
if (!*out)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
status = cairo_surface_status (*out);
|
||||
if (status) {
|
||||
cairo_surface_destroy (*out);
|
||||
*out = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
(*out)->device_transform = pattern->surface->device_transform;
|
||||
(*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
|
||||
|
@ -1420,6 +1658,11 @@ _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
|
|||
|
||||
status = cairo_status (cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
if (status) {
|
||||
cairo_surface_destroy (*out);
|
||||
*out = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1489,14 +1732,18 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
src->stops->color.blue / 65535.0,
|
||||
src->stops->color.alpha / 65535.0);
|
||||
|
||||
_cairo_pattern_init_solid (&solid, &color);
|
||||
_cairo_pattern_init_solid (&solid, &color,
|
||||
CAIRO_COLOR_IS_OPAQUE (&color) ?
|
||||
CAIRO_CONTENT_COLOR :
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
const cairo_color_t *color;
|
||||
|
||||
color = _cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
|
||||
_cairo_pattern_init_solid (&solid, color);
|
||||
_cairo_pattern_init_solid (&solid, color,
|
||||
CAIRO_CONTENT_ALPHA);
|
||||
}
|
||||
|
||||
status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
|
||||
|
@ -1598,13 +1845,18 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
|
|||
combined = src_solid->color;
|
||||
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
|
||||
|
||||
_cairo_pattern_init_solid (&src_tmp.solid, &combined);
|
||||
_cairo_pattern_init_solid (&src_tmp.solid, &combined,
|
||||
CAIRO_COLOR_IS_OPAQUE (&combined) ?
|
||||
CAIRO_CONTENT_COLOR :
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
mask = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cairo_pattern_init_copy (&src_tmp.base, src);
|
||||
status = _cairo_pattern_init_copy (&src_tmp.base, src);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_pattern_acquire_surface (&src_tmp.base, dst,
|
||||
|
@ -1623,19 +1875,23 @@ _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_copy (&mask_tmp.base, mask);
|
||||
status = _cairo_pattern_init_copy (&mask_tmp.base, mask);
|
||||
if (status)
|
||||
goto CLEANUP_SOURCE;
|
||||
|
||||
status = _cairo_pattern_acquire_surface (&mask_tmp.base, dst,
|
||||
mask_x, mask_y,
|
||||
width, height,
|
||||
mask_out, mask_attributes);
|
||||
|
||||
_cairo_pattern_fini (&mask_tmp.base);
|
||||
|
||||
CLEANUP_SOURCE:
|
||||
if (status)
|
||||
_cairo_pattern_release_surface (&src_tmp.base,
|
||||
*src_out, src_attributes);
|
||||
|
||||
_cairo_pattern_fini (&src_tmp.base);
|
||||
_cairo_pattern_fini (&mask_tmp.base);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -1677,7 +1933,9 @@ _cairo_pattern_get_extents (cairo_pattern_t *pattern,
|
|||
return status;
|
||||
|
||||
imatrix = pattern->matrix;
|
||||
cairo_matrix_invert (&imatrix);
|
||||
status = cairo_matrix_invert (&imatrix);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* XXX Use _cairo_matrix_transform_bounding_box here */
|
||||
for (sy = 0; sy <= 1; sy++) {
|
||||
|
@ -1956,3 +2214,10 @@ cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
|
|||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_pattern_reset_static_data (void)
|
||||
{
|
||||
_cairo_pattern_reset_solid_pattern_cache ();
|
||||
_cairo_pattern_reset_solid_surface_cache ();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Red Hat, Inc
|
||||
* Copyright © 2006 Red Hat, Inc
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_PDF_SURFACE_PRIVATE_H
|
||||
#define CAIRO_PDF_SURFACE_PRIVATE_H
|
||||
|
||||
#include "cairo-pdf.h"
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
|
||||
typedef struct _cairo_pdf_resource {
|
||||
unsigned int id;
|
||||
} cairo_pdf_resource_t;
|
||||
|
||||
typedef struct _cairo_pdf_surface cairo_pdf_surface_t;
|
||||
|
||||
struct _cairo_pdf_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
/* Prefer the name "output" here to avoid confusion over the
|
||||
* structure within a PDF document known as a "stream". */
|
||||
cairo_output_stream_t *output;
|
||||
|
||||
double width;
|
||||
double height;
|
||||
cairo_matrix_t cairo_to_pdf;
|
||||
|
||||
cairo_array_t objects;
|
||||
cairo_array_t pages;
|
||||
cairo_array_t patterns;
|
||||
cairo_array_t xobjects;
|
||||
cairo_array_t streams;
|
||||
cairo_array_t alphas;
|
||||
cairo_array_t smasks;
|
||||
cairo_array_t rgb_linear_functions;
|
||||
cairo_array_t alpha_linear_functions;
|
||||
|
||||
cairo_scaled_font_subsets_t *font_subsets;
|
||||
cairo_array_t fonts;
|
||||
|
||||
cairo_pdf_resource_t next_available_resource;
|
||||
cairo_pdf_resource_t pages_resource;
|
||||
|
||||
struct {
|
||||
cairo_bool_t active;
|
||||
cairo_pdf_resource_t self;
|
||||
cairo_pdf_resource_t length;
|
||||
long start_offset;
|
||||
cairo_bool_t compressed;
|
||||
cairo_output_stream_t *old_output;
|
||||
} current_stream;
|
||||
|
||||
struct {
|
||||
cairo_pattern_type_t type;
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
int alpha;
|
||||
cairo_pdf_resource_t smask;
|
||||
cairo_pdf_resource_t pattern;
|
||||
} emitted_pattern;
|
||||
|
||||
cairo_bool_t has_clip;
|
||||
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
|
||||
cairo_bool_t force_fallbacks;
|
||||
};
|
||||
|
||||
#endif /* CAIRO_PDF_SURFACE_PRIVATE_H */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -45,15 +45,13 @@ _cairo_pen_compute_slopes (cairo_pen_t *pen);
|
|||
static cairo_status_t
|
||||
_cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon);
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_pen_init_empty (cairo_pen_t *pen)
|
||||
{
|
||||
pen->radius = 0;
|
||||
pen->tolerance = 0;
|
||||
pen->vertices = NULL;
|
||||
pen->num_vertices = 0;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -135,6 +133,7 @@ cairo_status_t
|
|||
_cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points)
|
||||
{
|
||||
cairo_pen_vertex_t *vertices;
|
||||
cairo_status_t status;
|
||||
int num_vertices;
|
||||
int i;
|
||||
|
||||
|
@ -150,7 +149,9 @@ _cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points)
|
|||
for (i=0; i < num_points; i++)
|
||||
pen->vertices[pen->num_vertices-num_points+i].point = point[i];
|
||||
|
||||
_cairo_hull_compute (pen->vertices, &pen->num_vertices);
|
||||
status = _cairo_hull_compute (pen->vertices, &pen->num_vertices);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_pen_compute_slopes (pen);
|
||||
|
||||
|
@ -388,15 +389,18 @@ _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
|
|||
final_slope.dy = -final_slope.dy;
|
||||
}
|
||||
|
||||
_cairo_pen_find_active_cw_vertex_index (pen, &initial_slope, &active);
|
||||
status = _cairo_pen_find_active_cw_vertex_index (pen,
|
||||
&initial_slope,
|
||||
&active);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
i = start;
|
||||
while (i != stop) {
|
||||
hull_point.x = point[i].x + pen->vertices[active].point.x;
|
||||
hull_point.y = point[i].y + pen->vertices[active].point.y;
|
||||
status = _cairo_polygon_line_to (polygon, &hull_point);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_polygon_line_to (polygon, &hull_point);
|
||||
|
||||
if (i + step == stop)
|
||||
slope = final_slope;
|
||||
|
@ -437,19 +441,24 @@ _cairo_pen_stroke_spline (cairo_pen_t *pen,
|
|||
|
||||
status = _cairo_spline_decompose (spline, tolerance);
|
||||
if (status)
|
||||
return status;
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_FORWARD, &polygon);
|
||||
if (status)
|
||||
return status;
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_REVERSE, &polygon);
|
||||
if (status)
|
||||
return status;
|
||||
goto BAIL;
|
||||
|
||||
_cairo_polygon_close (&polygon);
|
||||
_cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
|
||||
status = _cairo_polygon_status (&polygon);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
|
||||
BAIL:
|
||||
_cairo_polygon_fini (&polygon);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -93,4 +93,6 @@
|
|||
#define FLOAT_WORDS_BIGENDIAN
|
||||
#endif
|
||||
|
||||
#define CAIRO_NO_MUTEX 1
|
||||
|
||||
#endif /* CAIRO_PLATFORM_H */
|
||||
|
|
|
@ -35,8 +35,9 @@
|
|||
* Kristian Høgsberg <krh@redhat.com>
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <png.h>
|
||||
|
||||
/* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
|
||||
|
@ -82,6 +83,25 @@ convert_data_to_bytes (png_structp png, png_row_infop row_info, png_bytep data)
|
|||
}
|
||||
}
|
||||
|
||||
/* Use a couple of simple error callbacks that do not print anything to
|
||||
* stderr and rely on the user to check for errors via the cairo_status_t
|
||||
* return.
|
||||
*/
|
||||
static void
|
||||
png_simple_error_callback (png_structp png_save_ptr,
|
||||
png_const_charp error_msg)
|
||||
{
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
longjmp (png_save_ptr->jmpbuf, CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
static void
|
||||
png_simple_warning_callback (png_structp png_save_ptr,
|
||||
png_const_charp error_msg)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
write_png (cairo_surface_t *surface,
|
||||
png_rw_ptr write_func,
|
||||
|
@ -117,7 +137,9 @@ write_png (cairo_surface_t *surface,
|
|||
for (i = 0; i < image->height; i++)
|
||||
rows[i] = (png_byte *) image->data + i * image->stride;
|
||||
|
||||
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
|
||||
png_simple_error_callback,
|
||||
png_simple_warning_callback);
|
||||
if (png == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto BAIL2;
|
||||
|
@ -129,10 +151,9 @@ write_png (cairo_surface_t *surface,
|
|||
goto BAIL3;
|
||||
}
|
||||
|
||||
if (setjmp (png_jmpbuf (png))) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
status = setjmp (png_jmpbuf (png));
|
||||
if (status)
|
||||
goto BAIL3;
|
||||
}
|
||||
|
||||
png_set_write_fn (png, closure, write_func, NULL);
|
||||
|
||||
|
@ -154,7 +175,7 @@ write_png (cairo_surface_t *surface,
|
|||
png_color_type = PNG_COLOR_TYPE_GRAY;
|
||||
break;
|
||||
default:
|
||||
status = CAIRO_STATUS_NULL_POINTER;
|
||||
status = CAIRO_STATUS_INVALID_FORMAT;
|
||||
goto BAIL3;
|
||||
}
|
||||
|
||||
|
@ -206,8 +227,13 @@ stdio_write_func (png_structp png, png_bytep data, png_size_t size)
|
|||
FILE *fp;
|
||||
|
||||
fp = png_get_io_ptr (png);
|
||||
if (fwrite (data, 1, size, fp) != size)
|
||||
png_error(png, "Write Error");
|
||||
while (size) {
|
||||
size_t ret = fwrite (data, 1, size, fp);
|
||||
size -= ret;
|
||||
data += ret;
|
||||
if (size && ferror (fp))
|
||||
png_error(png, "Write Error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,20 +358,20 @@ read_png (png_rw_ptr read_func,
|
|||
void *closure)
|
||||
{
|
||||
cairo_surface_t *surface = (cairo_surface_t*) &_cairo_surface_nil;
|
||||
png_byte *data = NULL;
|
||||
unsigned int i;
|
||||
png_struct *png = NULL;
|
||||
png_info *info;
|
||||
png_byte *data = NULL;
|
||||
png_byte **row_pointers = NULL;
|
||||
png_uint_32 png_width, png_height, stride;
|
||||
int depth, color_type, interlace;
|
||||
unsigned int i;
|
||||
unsigned int pixel_size;
|
||||
png_byte **row_pointers = NULL;
|
||||
|
||||
/* XXX: Perhaps we'll want some other error handlers? */
|
||||
png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
png_simple_error_callback,
|
||||
png_simple_warning_callback);
|
||||
if (png == NULL)
|
||||
goto BAIL;
|
||||
|
||||
|
@ -373,7 +399,11 @@ read_png (png_rw_ptr read_func,
|
|||
|
||||
/* expand gray bit depth if needed */
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8)
|
||||
#if PNG_LIBPNG_VER >= 10209
|
||||
png_set_expand_gray_1_2_4_to_8 (png);
|
||||
#else
|
||||
png_set_gray_1_2_4_to_8 (png);
|
||||
#endif
|
||||
/* transform transparency to alpha */
|
||||
if (png_get_valid(png, info, PNG_INFO_tRNS))
|
||||
png_set_tRNS_to_alpha (png);
|
||||
|
@ -442,8 +472,13 @@ stdio_read_func (png_structp png, png_bytep data, png_size_t size)
|
|||
FILE *fp;
|
||||
|
||||
fp = png_get_io_ptr (png);
|
||||
if (fread (data, 1, size, fp) != size)
|
||||
png_error(png, "Read Error");
|
||||
while (size) {
|
||||
size_t ret = fread (data, 1, size, fp);
|
||||
size -= ret;
|
||||
data += ret;
|
||||
if (size && ferror (fp))
|
||||
png_error(png, "Read Error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
/* private functions */
|
||||
|
@ -45,6 +44,8 @@ _cairo_polygon_grow (cairo_polygon_t *polygon);
|
|||
void
|
||||
_cairo_polygon_init (cairo_polygon_t *polygon)
|
||||
{
|
||||
polygon->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
polygon->num_edges = 0;
|
||||
|
||||
polygon->edges_size = 0;
|
||||
|
@ -66,13 +67,19 @@ _cairo_polygon_fini (cairo_polygon_t *polygon)
|
|||
polygon->has_current_point = FALSE;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_polygon_status (cairo_polygon_t *polygon)
|
||||
{
|
||||
return polygon->status;
|
||||
}
|
||||
|
||||
/* make room for at least one more edge */
|
||||
static cairo_status_t
|
||||
_cairo_polygon_grow (cairo_polygon_t *polygon)
|
||||
{
|
||||
cairo_edge_t *new_edges;
|
||||
int old_size = polygon->edges_size;
|
||||
int embedded_size = sizeof (polygon->edges_embedded) / sizeof (polygon->edges_embedded[0]);
|
||||
int embedded_size = ARRAY_LENGTH (polygon->edges_embedded);
|
||||
int new_size = 2 * MAX (old_size, 16);
|
||||
|
||||
/* we have a local buffer at polygon->edges_embedded. try to fulfill the request
|
||||
|
@ -103,22 +110,22 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_edge_t *edge;
|
||||
|
||||
if (polygon->status)
|
||||
return;
|
||||
|
||||
/* drop horizontal edges */
|
||||
if (p1->y == p2->y) {
|
||||
if (p1->y == p2->y)
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
if (polygon->num_edges >= polygon->edges_size) {
|
||||
status = _cairo_polygon_grow (polygon);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
polygon->status = _cairo_polygon_grow (polygon);
|
||||
if (polygon->status)
|
||||
return;
|
||||
}
|
||||
|
||||
edge = &polygon->edges[polygon->num_edges];
|
||||
|
@ -136,49 +143,45 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_poin
|
|||
|
||||
DONE:
|
||||
_cairo_polygon_move_to (polygon, p2);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
|
||||
{
|
||||
if (polygon->status)
|
||||
return;
|
||||
|
||||
if (! polygon->has_current_point)
|
||||
polygon->first_point = *point;
|
||||
|
||||
polygon->current_point = *point;
|
||||
polygon->has_current_point = TRUE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
if (polygon->status)
|
||||
return;
|
||||
|
||||
if (polygon->has_current_point) {
|
||||
status = _cairo_polygon_add_edge (polygon, &polygon->current_point, point);
|
||||
_cairo_polygon_add_edge (polygon, &polygon->current_point, point);
|
||||
} else {
|
||||
_cairo_polygon_move_to (polygon, point);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_polygon_close (cairo_polygon_t *polygon)
|
||||
{
|
||||
cairo_status_t status;
|
||||
if (polygon->status)
|
||||
return;
|
||||
|
||||
if (polygon->has_current_point) {
|
||||
status = _cairo_polygon_add_edge (polygon,
|
||||
&polygon->current_point,
|
||||
&polygon->first_point);
|
||||
if (status)
|
||||
return status;
|
||||
_cairo_polygon_add_edge (polygon,
|
||||
&polygon->current_point,
|
||||
&polygon->first_point);
|
||||
|
||||
polygon->has_current_point = FALSE;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2003 University of Southern California
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
*
|
||||
* 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):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Kristian Høgsberg <krh@redhat.com>
|
||||
* Keith Packard <keithp@keithp.com>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_PS_SURFACE_PRIVATE_H
|
||||
#define CAIRO_PS_SURFACE_PRIVATE_H
|
||||
|
||||
#include "cairo-ps.h"
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
|
||||
typedef struct cairo_ps_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
/* Here final_stream corresponds to the stream/file passed to
|
||||
* cairo_ps_surface_create surface is built. Meanwhile stream is a
|
||||
* temporary stream in which the file output is built, (so that
|
||||
* the header can be built and inserted into the target stream
|
||||
* before the contents of the temporary stream are copied). */
|
||||
cairo_output_stream_t *final_stream;
|
||||
|
||||
FILE *tmpfile;
|
||||
cairo_output_stream_t *stream;
|
||||
|
||||
double width;
|
||||
double height;
|
||||
double max_width;
|
||||
double max_height;
|
||||
|
||||
int num_pages;
|
||||
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
|
||||
cairo_bool_t force_fallbacks;
|
||||
|
||||
cairo_scaled_font_subsets_t *font_subsets;
|
||||
|
||||
cairo_array_t dsc_header_comments;
|
||||
cairo_array_t dsc_setup_comments;
|
||||
cairo_array_t dsc_page_setup_comments;
|
||||
|
||||
cairo_array_t *dsc_comment_target;
|
||||
} cairo_ps_surface_t;
|
||||
|
||||
#endif /* CAIRO_PS_SURFACE_PRIVATE_H */
|
|
@ -39,9 +39,9 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-ps.h"
|
||||
#include "cairo-ps-test.h"
|
||||
#include "cairo-ps-surface-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
#include "cairo-paginated-surface-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
|
@ -52,40 +52,6 @@
|
|||
static const cairo_surface_backend_t cairo_ps_surface_backend;
|
||||
static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
|
||||
|
||||
typedef struct cairo_ps_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
/* Here final_stream corresponds to the stream/file passed to
|
||||
* cairo_ps_surface_create surface is built. Meanwhile stream is a
|
||||
* temporary stream in which the file output is built, (so that
|
||||
* the header can be built and inserted into the target stream
|
||||
* before the contents of the temporary stream are copied). */
|
||||
cairo_output_stream_t *final_stream;
|
||||
|
||||
FILE *tmpfile;
|
||||
cairo_output_stream_t *stream;
|
||||
|
||||
double width;
|
||||
double height;
|
||||
double max_width;
|
||||
double max_height;
|
||||
|
||||
int num_pages;
|
||||
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
|
||||
cairo_scaled_font_subsets_t *font_subsets;
|
||||
|
||||
cairo_array_t dsc_header_comments;
|
||||
cairo_array_t dsc_setup_comments;
|
||||
cairo_array_t dsc_page_setup_comments;
|
||||
|
||||
cairo_array_t *dsc_comment_target;
|
||||
|
||||
} cairo_ps_surface_t;
|
||||
|
||||
#define PS_SURFACE_MAX_GLYPHS_PER_FONT 256
|
||||
|
||||
/* A word wrap stream can be used as a filter to do word wrapping on
|
||||
* top of an existing output stream. The word wrapping is quite
|
||||
* simple, using isspace to determine characters that separate
|
||||
|
@ -182,7 +148,7 @@ _word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
|
|||
|
||||
stream = malloc (sizeof (word_wrap_stream_t));
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
|
||||
_cairo_output_stream_init (&stream->base,
|
||||
_word_wrap_stream_write,
|
||||
|
@ -297,7 +263,7 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface,
|
|||
cairo_line_cap_t line_cap)
|
||||
{
|
||||
cairo_output_stream_t *word_wrap;
|
||||
cairo_status_t status;
|
||||
cairo_status_t status, status2;
|
||||
ps_path_info_t path_info;
|
||||
|
||||
word_wrap = _word_wrap_stream_create (stream, 79);
|
||||
|
@ -315,7 +281,9 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface,
|
|||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = _cairo_output_stream_get_status (word_wrap);
|
||||
_cairo_output_stream_destroy (word_wrap);
|
||||
status2 = _cairo_output_stream_destroy (word_wrap);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -484,18 +452,18 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
|
|||
|
||||
/* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
for (i = 1; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"Encoding %d /g%d put\n", i, i);
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/CharStrings %d dict dup begin\n"
|
||||
"/.notdef 0 def\n",
|
||||
font_subset->num_glyphs + 1);
|
||||
font_subset->num_glyphs);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++)
|
||||
for (i = 1; i < font_subset->num_glyphs; i++)
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"/g%d %d def\n", i, i + 1);
|
||||
"/g%d %d def\n", i, i);
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
"end readonly def\n");
|
||||
|
@ -579,6 +547,8 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
|
|||
CAIRO_SCALED_GLYPH_INFO_METRICS|
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
&scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
image = scaled_glyph->surface;
|
||||
if (image->format != CAIRO_FORMAT_A1) {
|
||||
|
@ -634,7 +604,7 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
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,
|
||||
|
@ -658,6 +628,8 @@ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
|
|||
|
||||
if (status)
|
||||
_cairo_surface_set_error (&surface->base, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -666,6 +638,7 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
|||
|
||||
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t matrix;
|
||||
unsigned int i;
|
||||
|
||||
|
@ -678,7 +651,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
|||
font_subset->subset_id);
|
||||
|
||||
matrix = font_subset->scaled_font->scale;
|
||||
cairo_matrix_invert (&matrix);
|
||||
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"
|
||||
|
@ -691,9 +666,11 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
|
|||
-matrix.yy);
|
||||
|
||||
for (i = 0; i < font_subset->num_glyphs; i++) {
|
||||
_cairo_ps_surface_emit_glyph (surface,
|
||||
font_subset->scaled_font,
|
||||
font_subset->glyphs[i], i);
|
||||
status = _cairo_ps_surface_emit_glyph (surface,
|
||||
font_subset->scaled_font,
|
||||
font_subset->glyphs[i], i);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (surface->final_stream,
|
||||
|
@ -809,8 +786,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
if (status)
|
||||
goto CLEANUP_TMPFILE;
|
||||
|
||||
surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT,
|
||||
PS_SURFACE_MAX_GLYPHS_PER_FONT);
|
||||
surface->font_subsets = _cairo_scaled_font_subsets_create_simple ();
|
||||
if (! surface->font_subsets)
|
||||
goto CLEANUP_OUTPUT_STREAM;
|
||||
|
||||
|
@ -819,6 +795,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
surface->max_width = width;
|
||||
surface->max_height = height;
|
||||
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
|
||||
surface->force_fallbacks = FALSE;
|
||||
|
||||
surface->num_pages = 0;
|
||||
|
||||
|
@ -834,7 +811,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
&cairo_ps_surface_paginated_backend);
|
||||
|
||||
CLEANUP_OUTPUT_STREAM:
|
||||
_cairo_output_stream_destroy (surface->stream);
|
||||
status = _cairo_output_stream_destroy (surface->stream);
|
||||
/* Ignore status---we're already on a failure path. */
|
||||
CLEANUP_TMPFILE:
|
||||
fclose (surface->tmpfile);
|
||||
CLEANUP_SURFACE:
|
||||
|
@ -1201,7 +1179,7 @@ cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface)
|
|||
static cairo_status_t
|
||||
_cairo_ps_surface_finish (void *abstract_surface)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_status_t status, status2;
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
int i, num_comments;
|
||||
char **comments;
|
||||
|
@ -1214,16 +1192,13 @@ _cairo_ps_surface_finish (void *abstract_surface)
|
|||
|
||||
_cairo_ps_surface_emit_footer (surface);
|
||||
|
||||
_cairo_output_stream_close (surface->stream);
|
||||
status = _cairo_output_stream_get_status (surface->stream);
|
||||
_cairo_output_stream_destroy (surface->stream);
|
||||
status = _cairo_output_stream_destroy (surface->stream);
|
||||
|
||||
fclose (surface->tmpfile);
|
||||
|
||||
_cairo_output_stream_close (surface->final_stream);
|
||||
status2 = _cairo_output_stream_destroy (surface->final_stream);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = _cairo_output_stream_get_status (surface->final_stream);
|
||||
_cairo_output_stream_destroy (surface->final_stream);
|
||||
status = status2;
|
||||
|
||||
num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
|
||||
comments = _cairo_array_index (&surface->dsc_header_comments, 0);
|
||||
|
@ -1383,32 +1358,12 @@ pattern_supported (const cairo_pattern_t *pattern)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_bool_t cairo_ps_force_fallbacks = FALSE;
|
||||
|
||||
/**
|
||||
* _cairo_ps_test_force_fallbacks
|
||||
*
|
||||
* Force the PS surface backend to use image fallbacks for every
|
||||
* operation.
|
||||
*
|
||||
* <note>
|
||||
* This function is <emphasis>only</emphasis> intended for internal
|
||||
* testing use within the cairo distribution. It is not installed in
|
||||
* any public header file.
|
||||
* </note>
|
||||
**/
|
||||
void
|
||||
_cairo_ps_test_force_fallbacks (void)
|
||||
{
|
||||
cairo_ps_force_fallbacks = TRUE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
if (cairo_ps_force_fallbacks)
|
||||
if (surface->force_fallbacks)
|
||||
return FALSE;
|
||||
|
||||
if (! pattern_supported (pattern))
|
||||
|
@ -1542,7 +1497,7 @@ _string_array_stream_create (cairo_output_stream_t *output)
|
|||
|
||||
stream = malloc (sizeof (string_array_stream_t));
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
|
||||
_cairo_output_stream_init (&stream->base,
|
||||
_string_array_stream_write,
|
||||
|
@ -1562,7 +1517,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
|||
cairo_image_surface_t *image,
|
||||
const char *name)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_status_t status, status2;
|
||||
unsigned char *rgb, *compressed;
|
||||
unsigned long rgb_size, compressed_size;
|
||||
cairo_surface_t *opaque;
|
||||
|
@ -1588,20 +1543,29 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
|||
|
||||
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
|
||||
|
||||
_cairo_surface_fill_rectangle (opaque,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
CAIRO_COLOR_WHITE,
|
||||
0, 0, image->width, image->height);
|
||||
status = _cairo_surface_fill_rectangle (opaque,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
CAIRO_COLOR_WHITE,
|
||||
0, 0,
|
||||
image->width, image->height);
|
||||
if (status) {
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
goto bail0;
|
||||
}
|
||||
|
||||
_cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||
&pattern.base,
|
||||
NULL,
|
||||
opaque,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
image->width,
|
||||
image->height);
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||
&pattern.base,
|
||||
NULL,
|
||||
opaque,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
image->width,
|
||||
image->height);
|
||||
if (status) {
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
goto bail0;
|
||||
}
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
opaque_image = (cairo_image_surface_t *) opaque;
|
||||
|
@ -1646,8 +1610,12 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
|||
|
||||
_cairo_output_stream_write (base85_stream, compressed, compressed_size);
|
||||
|
||||
_cairo_output_stream_destroy (base85_stream);
|
||||
_cairo_output_stream_destroy (string_array_stream);
|
||||
status = _cairo_output_stream_destroy (base85_stream);
|
||||
status2 = _cairo_output_stream_destroy (string_array_stream);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
if (status)
|
||||
goto bail3;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"] def\n");
|
||||
|
@ -1679,6 +1647,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
|||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
bail3:
|
||||
free (compressed);
|
||||
bail2:
|
||||
free (rgb);
|
||||
|
@ -1705,19 +1674,26 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
|
|||
pattern->color.blue);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
cairo_status_t status;
|
||||
double bbox_width, bbox_height;
|
||||
double xstep, ystep;
|
||||
cairo_matrix_t inverse = pattern->base.matrix;
|
||||
|
||||
cairo_matrix_invert (&inverse);
|
||||
status = cairo_matrix_invert (&inverse);
|
||||
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (_cairo_surface_is_meta (pattern->surface)) {
|
||||
_cairo_output_stream_printf (surface->stream, "/MyPattern {\n");
|
||||
_cairo_meta_surface_replay (pattern->surface, &surface->base);
|
||||
|
||||
status = _cairo_meta_surface_replay (pattern->surface, &surface->base);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
bbox_width = surface->width;
|
||||
bbox_height = surface->height;
|
||||
xstep = surface->width;
|
||||
|
@ -1805,6 +1781,8 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
|||
inverse.x0, inverse.y0);
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"makepattern setpattern\n");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1821,12 +1799,13 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
|
|||
/* XXX: NYI */
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
|
||||
{
|
||||
/* FIXME: We should keep track of what pattern is currently set in
|
||||
* the postscript file and only emit code if we're setting a
|
||||
* different pattern. */
|
||||
cairo_status_t status;
|
||||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
|
@ -1834,7 +1813,10 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pa
|
|||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
_cairo_ps_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
|
||||
status = _cairo_ps_surface_emit_surface_pattern (surface,
|
||||
(cairo_surface_pattern_t *) pattern);
|
||||
if (status)
|
||||
return status;
|
||||
break;
|
||||
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
|
@ -1845,6 +1827,8 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pa
|
|||
_cairo_ps_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
|
||||
break;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -1930,6 +1914,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_output_stream_t *stream = surface->stream;
|
||||
cairo_rectangle_int16_t extents, pattern_extents;
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_ps_surface_analyze_operation (surface, op, source);
|
||||
|
@ -1941,17 +1926,25 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
* possible only because there is nothing between the fallback
|
||||
* images and the paper, nor is anything painted above. */
|
||||
/*
|
||||
assert (__cairo_ps_surface_operation_supported (op, source));
|
||||
assert (_cairo_ps_surface_operation_supported (op, source));
|
||||
*/
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _cairo_ps_surface_paint\n");
|
||||
|
||||
_cairo_surface_get_extents (&surface->base, &extents);
|
||||
_cairo_pattern_get_extents (source, &pattern_extents);
|
||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_pattern_get_extents (source, &pattern_extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_rectangle_intersect (&extents, &pattern_extents);
|
||||
|
||||
_cairo_ps_surface_emit_pattern (surface, source);
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (stream, "%d %d M\n",
|
||||
extents.x, extents.y);
|
||||
|
@ -1965,6 +1958,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
extents.x,
|
||||
extents.y + extents.height);
|
||||
_cairo_output_stream_printf (stream, "P F\n");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2200,7 +2194,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_output_stream_t *stream = surface->stream;
|
||||
unsigned int current_subset_id = -1;
|
||||
unsigned int font_id;
|
||||
cairo_scaled_font_subsets_glyph_t subset_glyph;
|
||||
cairo_ps_glyph_id_t *glyph_ids;
|
||||
cairo_status_t status;
|
||||
unsigned int num_glyphs_unsigned, i, j, last, end;
|
||||
|
@ -2228,11 +2222,11 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
for (i = 0; i < num_glyphs_unsigned; i++) {
|
||||
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
|
||||
scaled_font, glyphs[i].index,
|
||||
&font_id,
|
||||
&(glyph_ids[i].subset_id),
|
||||
&(glyph_ids[i].glyph_id));
|
||||
&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;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
@ -2242,7 +2236,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
"/CairoFont-%d-%d findfont\n"
|
||||
"[ %f %f %f %f 0 0 ] makefont\n"
|
||||
"setfont\n",
|
||||
font_id,
|
||||
subset_glyph.font_id,
|
||||
glyph_ids[i].subset_id,
|
||||
scaled_font->scale.xx,
|
||||
scaled_font->scale.yx,
|
||||
|
|
|
@ -56,8 +56,11 @@ typedef struct cairo_quartz_surface {
|
|||
/* These are stored while drawing operations are in place, set up
|
||||
* by quartz_setup_source() and quartz_finish_source()
|
||||
*/
|
||||
CGAffineTransform imageTransform;
|
||||
CGImageRef sourceImage;
|
||||
cairo_surface_t *sourceImageSurface;
|
||||
CGAffineTransform sourceImageTransform;
|
||||
CGRect sourceImageRect;
|
||||
|
||||
CGShadingRef sourceShading;
|
||||
CGPatternRef sourcePattern;
|
||||
} cairo_quartz_surface_t;
|
||||
|
|
|
@ -34,12 +34,12 @@
|
|||
* Vladimir Vukicevic <vladimir@mozilla.com>
|
||||
*/
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-quartz-private.h"
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#undef QUARTZ_DEBUG
|
||||
|
||||
#ifdef QUARTZ_DEBUG
|
||||
|
@ -101,47 +101,24 @@ static void quartz_image_to_png (CGImageRef, char *dest);
|
|||
* Cairo path -> Quartz path conversion helpers
|
||||
*/
|
||||
|
||||
/* cairo path -> mutable path */
|
||||
static cairo_status_t
|
||||
_cairo_path_to_quartz_path_move_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
CGPathMoveToPoint ((CGMutablePathRef) closure, NULL,
|
||||
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_path_to_quartz_path_line_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
CGPathAddLineToPoint ((CGMutablePathRef) closure, NULL,
|
||||
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_path_to_quartz_path_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
|
||||
{
|
||||
CGPathAddCurveToPoint ((CGMutablePathRef) closure, NULL,
|
||||
_cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
|
||||
_cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
|
||||
_cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_path_to_quartz_path_close_path (void *closure)
|
||||
{
|
||||
CGPathCloseSubpath ((CGMutablePathRef) closure);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
typedef struct _quartz_stroke {
|
||||
CGContextRef cgContext;
|
||||
cairo_matrix_t *ctm_inverse;
|
||||
} quartz_stroke_t;
|
||||
|
||||
/* cairo path -> execute in context */
|
||||
static cairo_status_t
|
||||
_cairo_path_to_quartz_context_move_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
//ND((stderr, "moveto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
|
||||
CGContextMoveToPoint ((CGContextRef) closure,
|
||||
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
|
||||
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);
|
||||
|
||||
CGContextMoveToPoint (stroke->cgContext, x, y);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -149,12 +126,17 @@ static cairo_status_t
|
|||
_cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point)
|
||||
{
|
||||
//ND((stderr, "lineto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
|
||||
if (CGContextIsPathEmpty ((CGContextRef) closure))
|
||||
CGContextMoveToPoint ((CGContextRef) closure,
|
||||
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
|
||||
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);
|
||||
|
||||
if (CGContextIsPathEmpty (stroke->cgContext))
|
||||
CGContextMoveToPoint (stroke->cgContext, x, y);
|
||||
else
|
||||
CGContextAddLineToPoint ((CGContextRef) closure,
|
||||
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
|
||||
CGContextAddLineToPoint (stroke->cgContext, x, y);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -165,11 +147,22 @@ _cairo_path_to_quartz_context_curve_to (void *closure, cairo_point_t *p0, cairo_
|
|||
// _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
|
||||
// _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
|
||||
// _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y)));
|
||||
quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
|
||||
double x0 = _cairo_fixed_to_double (p0->x);
|
||||
double y0 = _cairo_fixed_to_double (p0->y);
|
||||
double x1 = _cairo_fixed_to_double (p1->x);
|
||||
double y1 = _cairo_fixed_to_double (p1->y);
|
||||
double x2 = _cairo_fixed_to_double (p2->x);
|
||||
double y2 = _cairo_fixed_to_double (p2->y);
|
||||
|
||||
CGContextAddCurveToPoint ((CGContextRef) closure,
|
||||
_cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
|
||||
_cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
|
||||
_cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
|
||||
if (stroke->ctm_inverse) {
|
||||
cairo_matrix_transform_point (stroke->ctm_inverse, &x0, &y0);
|
||||
cairo_matrix_transform_point (stroke->ctm_inverse, &x1, &y1);
|
||||
cairo_matrix_transform_point (stroke->ctm_inverse, &x2, &y2);
|
||||
}
|
||||
|
||||
CGContextAddCurveToPoint (stroke->cgContext,
|
||||
x0, y0, x1, y1, x2, y2);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -177,26 +170,14 @@ static cairo_status_t
|
|||
_cairo_path_to_quartz_context_close_path (void *closure)
|
||||
{
|
||||
//ND((stderr, "closepath\n"));
|
||||
CGContextClosePath ((CGContextRef) closure);
|
||||
quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
|
||||
CGContextClosePath (stroke->cgContext);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_quartz_cairo_path_to_quartz_path (cairo_path_fixed_t *path,
|
||||
CGMutablePathRef cgPath)
|
||||
{
|
||||
return _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_path_to_quartz_path_move_to,
|
||||
_cairo_path_to_quartz_path_line_to,
|
||||
_cairo_path_to_quartz_path_curve_to,
|
||||
_cairo_path_to_quartz_path_close_path,
|
||||
cgPath);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_quartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path,
|
||||
CGContextRef cgc)
|
||||
quartz_stroke_t *stroke)
|
||||
{
|
||||
return _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
|
@ -204,7 +185,7 @@ _cairo_quartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path,
|
|||
_cairo_path_to_quartz_context_line_to,
|
||||
_cairo_path_to_quartz_context_curve_to,
|
||||
_cairo_path_to_quartz_context_close_path,
|
||||
cgc);
|
||||
stroke);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -286,8 +267,8 @@ _cairo_quartz_cairo_matrix_to_quartz (const cairo_matrix_t *src,
|
|||
CGAffineTransform *dst)
|
||||
{
|
||||
dst->a = src->xx;
|
||||
dst->b = src->xy;
|
||||
dst->c = src->yx;
|
||||
dst->b = src->yx;
|
||||
dst->c = src->xy;
|
||||
dst->d = src->yy;
|
||||
dst->tx = src->x0;
|
||||
dst->ty = src->y0;
|
||||
|
@ -365,6 +346,13 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
|
|||
abspat->type != CAIRO_PATTERN_TYPE_RADIAL)
|
||||
return NULL;
|
||||
|
||||
/* 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 NULL;
|
||||
|
||||
/* 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;
|
||||
|
@ -435,38 +423,30 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Generic cairo_pattern -> CGPattern function */
|
||||
static void
|
||||
SurfacePatternDrawFunc (void *info, CGContextRef context)
|
||||
/* generic cairo surface -> cairo_quartz_surface_t function */
|
||||
static cairo_quartz_surface_t *
|
||||
_cairo_quartz_surface_to_quartz (cairo_surface_t *target, cairo_surface_t *pat_surf)
|
||||
{
|
||||
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
|
||||
cairo_surface_t *pat_surf = spat->surface;
|
||||
|
||||
cairo_quartz_surface_t *quartz_surf = NULL;
|
||||
|
||||
cairo_bool_t flip = FALSE;
|
||||
|
||||
CGImageRef img;
|
||||
|
||||
if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) {
|
||||
/* This sucks; we should really store a dummy quartz surface
|
||||
* for passing in here
|
||||
* XXXtodo store a dummy quartz surface somewhere for handing off to clone_similar
|
||||
* XXXtodo/perf don't use clone if the source surface is an image surface! Instead,
|
||||
/* XXXtodo/perf don't use clone if the source surface is an image surface! Instead,
|
||||
* just create the CGImage directly!
|
||||
*/
|
||||
|
||||
cairo_surface_t *dummy = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
|
||||
cairo_surface_t *ref_type = target;
|
||||
cairo_surface_t *new_surf = NULL;
|
||||
cairo_rectangle_int16_t rect;
|
||||
if (ref_type == NULL)
|
||||
ref_type = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
|
||||
|
||||
_cairo_surface_get_extents (pat_surf, &rect);
|
||||
|
||||
_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
|
||||
_cairo_surface_clone_similar (ref_type, pat_surf, rect.x, rect.y,
|
||||
rect.width, rect.height, &new_surf);
|
||||
|
||||
cairo_surface_destroy(dummy);
|
||||
if (target == NULL)
|
||||
cairo_surface_destroy(ref_type);
|
||||
|
||||
quartz_surf = (cairo_quartz_surface_t *) new_surf;
|
||||
} else {
|
||||
|
@ -476,15 +456,21 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
|
|||
cairo_surface_reference (pat_surf);
|
||||
quartz_surf = (cairo_quartz_surface_t*) pat_surf;
|
||||
|
||||
/* XXXtodo WHY does this need to be flipped? Writing this stuff
|
||||
* to disk shows that in both this path and the path above the source image
|
||||
* has an identical orientation, and the destination context at all times has a Y
|
||||
* flip. So why do we need to flip in this case?
|
||||
*/
|
||||
flip = TRUE;
|
||||
}
|
||||
|
||||
img = CGBitmapContextCreateImage (quartz_surf->cgContext);
|
||||
return quartz_surf;
|
||||
}
|
||||
|
||||
/* Generic cairo_pattern -> CGPattern function */
|
||||
static void
|
||||
SurfacePatternDrawFunc (void *info, CGContextRef context)
|
||||
{
|
||||
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
|
||||
cairo_surface_t *pat_surf = spat->surface;
|
||||
|
||||
cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz (NULL, pat_surf);
|
||||
CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
|
||||
CGRect imageBounds;
|
||||
|
||||
if (!img) {
|
||||
// ... give up.
|
||||
|
@ -493,17 +479,33 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
|
|||
return;
|
||||
}
|
||||
|
||||
if (flip) {
|
||||
/* XXXtodo WHY does this need to be flipped? Writing this stuff
|
||||
* to disk shows that in both this path and the path above the source image
|
||||
* has an identical orientation, and the destination context at all times has a Y
|
||||
* flip. So why do we need to flip in this case?
|
||||
*/
|
||||
if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
|
||||
CGContextTranslateCTM (context, 0, CGImageGetHeight(img));
|
||||
CGContextScaleCTM (context, 1, -1);
|
||||
}
|
||||
|
||||
CGRect imageBounds;
|
||||
imageBounds.size = CGSizeMake (CGImageGetWidth(img), CGImageGetHeight(img));
|
||||
imageBounds.origin.x = 0;
|
||||
imageBounds.origin.y = 0;
|
||||
|
||||
CGContextDrawImage (context, imageBounds, img);
|
||||
if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
|
||||
/* draw 3 more copies of the image, flipped. */
|
||||
CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
|
||||
CGContextScaleCTM (context, 1, -1);
|
||||
CGContextDrawImage (context, imageBounds, img);
|
||||
CGContextTranslateCTM (context, 2 * imageBounds.size.width, 0);
|
||||
CGContextScaleCTM (context, -1, 1);
|
||||
CGContextDrawImage (context, imageBounds, img);
|
||||
CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
|
||||
CGContextScaleCTM (context, 1, -1);
|
||||
CGContextDrawImage (context, imageBounds, img);
|
||||
}
|
||||
|
||||
CGImageRelease (img);
|
||||
|
||||
|
@ -515,7 +517,11 @@ static cairo_status_t
|
|||
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
|
||||
const cairo_pattern_t *other)
|
||||
{
|
||||
_cairo_pattern_init_copy (pattern, other);
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_pattern_init_copy (pattern, other);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
|
@ -563,8 +569,24 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
|
|||
_cairo_surface_get_extents (pat_surf, &extents);
|
||||
pbounds.origin.x = 0;
|
||||
pbounds.origin.y = 0;
|
||||
pbounds.size.width = extents.width;
|
||||
pbounds.size.height = extents.height;
|
||||
|
||||
// kjs seems to indicate this should work (setting to 0,0 to avoid
|
||||
// tiling); however, the pattern CTM scaling ends up being NaN in
|
||||
// the pattern draw function if either rw or rh are 0.
|
||||
// XXXtodo get pattern drawing working with extend options
|
||||
// XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
|
||||
if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
|
||||
/* XXX broken; need to emulate by reflecting the image into 4 quadrants
|
||||
* and then tiling that
|
||||
*/
|
||||
pbounds.size.width = 2 * extents.width;
|
||||
pbounds.size.height = 2 * extents.height;
|
||||
} else {
|
||||
pbounds.size.width = extents.width;
|
||||
pbounds.size.height = extents.height;
|
||||
}
|
||||
rw = pbounds.size.width;
|
||||
rh = pbounds.size.height;
|
||||
|
||||
m = spat->base.matrix;
|
||||
cairo_matrix_invert(&m);
|
||||
|
@ -584,38 +606,6 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
|
|||
ND((stderr, " context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d));
|
||||
#endif
|
||||
|
||||
// kjs seems to indicate this should work (setting to 0,0 to avoid
|
||||
// tiling); however, the pattern CTM scaling ends up being NaN in
|
||||
// the pattern draw function if either rw or rh are 0.
|
||||
// XXXtodo get pattern drawing working with extend options
|
||||
// XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
|
||||
#if 0
|
||||
if (spat->base.extend == CAIRO_EXTEND_NONE) {
|
||||
/* XXX wasteful; this will keep drawing the pattern in the
|
||||
* original location. We need to set up the clip region
|
||||
* instead to do this right.
|
||||
*/
|
||||
rw = 0;
|
||||
rh = 0;
|
||||
} else if (spat->base.extend == CAIRO_EXTEND_REPEAT) {
|
||||
rw = extents.width;
|
||||
rh = extents.height;
|
||||
} else if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
|
||||
/* XXX broken; need to emulate by reflecting the image into 4 quadrants
|
||||
* and then tiling that
|
||||
*/
|
||||
rw = extents.width;
|
||||
rh = extents.height;
|
||||
} else {
|
||||
/* CAIRO_EXTEND_PAD */
|
||||
/* XXX broken. */
|
||||
rw = 0;
|
||||
rh = 0;
|
||||
}
|
||||
#else
|
||||
rw = extents.width;
|
||||
rh = extents.height;
|
||||
#endif
|
||||
|
||||
/* XXX fixme: only do snapshots if the context is for printing, or get rid of the
|
||||
other block if it doesn't fafect performance */
|
||||
|
@ -642,12 +632,13 @@ typedef enum {
|
|||
DO_SOLID,
|
||||
DO_SHADING,
|
||||
DO_PATTERN,
|
||||
DO_IMAGE,
|
||||
DO_UNSUPPORTED
|
||||
} cairo_quartz_action_t;
|
||||
|
||||
static cairo_quartz_action_t
|
||||
_cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
|
||||
cairo_pattern_t *source)
|
||||
cairo_pattern_t *source)
|
||||
{
|
||||
assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
|
||||
|
||||
|
@ -676,19 +667,44 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
|
|||
surface->sourceShading = shading;
|
||||
|
||||
return DO_SHADING;
|
||||
} else if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
source->extend == CAIRO_EXTEND_NONE)
|
||||
{
|
||||
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source;
|
||||
cairo_surface_t *pat_surf = spat->surface;
|
||||
cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf);
|
||||
CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
|
||||
cairo_matrix_t m = spat->base.matrix;
|
||||
cairo_rectangle_int16_t extents;
|
||||
|
||||
if (!img)
|
||||
return DO_UNSUPPORTED;
|
||||
|
||||
surface->sourceImage = img;
|
||||
|
||||
cairo_matrix_invert(&m);
|
||||
_cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceImageTransform);
|
||||
|
||||
_cairo_surface_get_extents (pat_surf, &extents);
|
||||
surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height);
|
||||
|
||||
surface->sourceImageSurface = (cairo_surface_t *)quartz_surf;
|
||||
|
||||
return DO_IMAGE;
|
||||
} else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
float patternAlpha = 1.0f;
|
||||
CGColorSpaceRef patternSpace;
|
||||
|
||||
CGPatternRef pattern = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source);
|
||||
if (!pattern)
|
||||
return DO_UNSUPPORTED;
|
||||
|
||||
float patternAlpha = 1.0f;
|
||||
|
||||
// Save before we change the pattern, colorspace, etc. so that
|
||||
// we can restore and make sure that quartz releases our
|
||||
// pattern (which may be stack allocated)
|
||||
CGContextSaveGState(surface->cgContext);
|
||||
|
||||
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
|
||||
patternSpace = CGColorSpaceCreatePattern(NULL);
|
||||
CGContextSetFillColorSpace (surface->cgContext, patternSpace);
|
||||
CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
|
||||
CGContextSetStrokeColorSpace (surface->cgContext, patternSpace);
|
||||
|
@ -716,7 +732,11 @@ _cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
|
|||
cairo_pattern_t *source)
|
||||
{
|
||||
if (surface->sourceImage) {
|
||||
// nothing to do; we don't use sourceImage yet
|
||||
CGImageRelease(surface->sourceImage);
|
||||
surface->sourceImage = NULL;
|
||||
|
||||
cairo_surface_destroy(surface->sourceImageSurface);
|
||||
surface->sourceImageSurface = NULL;
|
||||
}
|
||||
|
||||
if (surface->sourceShading) {
|
||||
|
@ -865,6 +885,15 @@ _cairo_quartz_surface_acquire_source_image (void *abstract_surface,
|
|||
return _cairo_quartz_get_image (surface, image_out, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_quartz_surface_release_source_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image,
|
||||
void *image_extra)
|
||||
{
|
||||
cairo_surface_destroy ((cairo_surface_t *) image);
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_quartz_surface_acquire_dest_image (void *abstract_surface,
|
||||
cairo_rectangle_int16_t *interest_rect,
|
||||
|
@ -965,7 +994,6 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
|
|||
int height,
|
||||
cairo_surface_t **clone_out)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_quartz_surface_t *new_surface = NULL;
|
||||
cairo_format_t new_format;
|
||||
|
||||
|
@ -1086,6 +1114,19 @@ _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) {
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
(cairo_surface_pattern_t *) source;
|
||||
cairo_surface_t *pat_surf = surface_pattern->surface;
|
||||
CGContextSaveGState (surface->cgContext);
|
||||
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);
|
||||
CGContextRestoreGState (surface->cgContext);
|
||||
} else {
|
||||
rv = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
@ -1108,6 +1149,7 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
|
||||
cairo_quartz_action_t action;
|
||||
quartz_stroke_t stroke;
|
||||
|
||||
ND((stderr, "%p _cairo_quartz_surface_fill op %d source->type %d\n", surface, op, source->type));
|
||||
|
||||
|
@ -1126,7 +1168,10 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
}
|
||||
|
||||
CGContextBeginPath (surface->cgContext);
|
||||
_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
|
||||
|
||||
stroke.cgContext = surface->cgContext;
|
||||
stroke.ctm_inverse = NULL;
|
||||
_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
|
||||
|
||||
if (action == DO_SOLID || action == DO_PATTERN) {
|
||||
if (fill_rule == CAIRO_FILL_RULE_WINDING)
|
||||
|
@ -1143,6 +1188,21 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
CGContextEOClip (surface->cgContext);
|
||||
|
||||
CGContextDrawShading (surface->cgContext, surface->sourceShading);
|
||||
} else if (action == DO_IMAGE) {
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
(cairo_surface_pattern_t *) source;
|
||||
cairo_surface_t *pat_surf = surface_pattern->surface;
|
||||
if (fill_rule == CAIRO_FILL_RULE_WINDING)
|
||||
CGContextClip (surface->cgContext);
|
||||
else
|
||||
CGContextEOClip (surface->cgContext);
|
||||
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 {
|
||||
rv = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
@ -1169,6 +1229,8 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
|
|||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
|
||||
cairo_quartz_action_t action;
|
||||
quartz_stroke_t stroke;
|
||||
CGAffineTransform strokeTransform;
|
||||
|
||||
ND((stderr, "%p _cairo_quartz_surface_stroke op %d source->type %d\n", surface, op, source->type));
|
||||
|
||||
|
@ -1184,6 +1246,8 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
|
|||
CGContextSetLineCap (surface->cgContext, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap));
|
||||
CGContextSetLineJoin (surface->cgContext, _cairo_quartz_cairo_line_join_to_quartz (style->line_join));
|
||||
CGContextSetMiterLimit (surface->cgContext, style->miter_limit);
|
||||
_cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
|
||||
CGContextConcatCTM (surface->cgContext, strokeTransform);
|
||||
|
||||
if (style->dash && style->num_dashes) {
|
||||
#define STATIC_DASH 32
|
||||
|
@ -1211,13 +1275,25 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
|
|||
}
|
||||
|
||||
CGContextBeginPath (surface->cgContext);
|
||||
_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
|
||||
|
||||
stroke.cgContext = surface->cgContext;
|
||||
stroke.ctm_inverse = ctm_inverse;
|
||||
_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
|
||||
|
||||
if (action == DO_SOLID || action == DO_PATTERN) {
|
||||
CGContextStrokePath (surface->cgContext);
|
||||
} else if (action == DO_IMAGE) {
|
||||
CGContextReplacePathWithStrokedPath (surface->cgContext);
|
||||
CGContextClip (surface->cgContext);
|
||||
|
||||
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);
|
||||
} else if (action == DO_SHADING) {
|
||||
// we have to clip and then paint the shading; first we have to convert
|
||||
// the stroke to a path that we can fill
|
||||
CGContextReplacePathWithStrokedPath (surface->cgContext);
|
||||
CGContextClip (surface->cgContext);
|
||||
|
||||
|
@ -1243,9 +1319,21 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
ATSUFontID fid;
|
||||
ATSFontRef atsfref;
|
||||
CGFontRef cgfref;
|
||||
CGAffineTransform cairoTextTransform, textTransform, ctm;
|
||||
// XXXtodo/perf: stack storage for glyphs/sizes
|
||||
#define STATIC_BUF_SIZE 64
|
||||
CGGlyph glyphs_static[STATIC_BUF_SIZE];
|
||||
CGSize cg_advances_static[STATIC_BUF_SIZE];
|
||||
CGGlyph *cg_glyphs = &glyphs_static[0];
|
||||
CGSize *cg_advances = &cg_advances_static[0];
|
||||
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
|
||||
cairo_quartz_action_t action;
|
||||
float xprev, yprev;
|
||||
int i;
|
||||
|
||||
if (num_glyphs <= 0)
|
||||
|
@ -1262,7 +1350,7 @@ _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_SHADING) {
|
||||
} else if (action == DO_IMAGE || action == DO_SHADING) {
|
||||
CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
|
||||
} else {
|
||||
/* Unsupported */
|
||||
|
@ -1272,9 +1360,9 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
|
||||
CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op));
|
||||
|
||||
ATSUFontID fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font);
|
||||
ATSFontRef atsfref = FMGetATSFontRefFromFont (fid);
|
||||
CGFontRef cgfref = CGFontCreateWithPlatformFont (&atsfref);
|
||||
fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font);
|
||||
atsfref = FMGetATSFontRefFromFont (fid);
|
||||
cgfref = CGFontCreateWithPlatformFont (&atsfref);
|
||||
|
||||
CGContextSetFont (surface->cgContext, cgfref);
|
||||
CGFontRelease (cgfref);
|
||||
|
@ -1285,8 +1373,11 @@ _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));
|
||||
CGAffineTransform cairoTextTransform, textTransform, ctm;
|
||||
_cairo_quartz_cairo_matrix_to_quartz (&scaled_font->font_matrix, &cairoTextTransform);
|
||||
cairoTextTransform = CGAffineTransformMake (scaled_font->font_matrix.xx,
|
||||
scaled_font->font_matrix.yx,
|
||||
scaled_font->font_matrix.xy,
|
||||
scaled_font->font_matrix.yy,
|
||||
0., 0.);
|
||||
|
||||
textTransform = CGAffineTransformMakeTranslation (glyphs[0].x, glyphs[0].y);
|
||||
textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0);
|
||||
|
@ -1302,51 +1393,27 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
CGContextSetTextMatrix (surface->cgContext, textTransform);
|
||||
CGContextSetFontSize (surface->cgContext, 1.0);
|
||||
|
||||
// XXXtodo/perf: stack storage for glyphs/sizes
|
||||
#define STATIC_BUF_SIZE 64
|
||||
CGGlyph glyphs_static[STATIC_BUF_SIZE];
|
||||
CGSize cg_advances_static[STATIC_BUF_SIZE];
|
||||
CGGlyph *cg_glyphs = &glyphs_static[0];
|
||||
CGSize *cg_advances = &cg_advances_static[0];
|
||||
|
||||
if (num_glyphs > STATIC_BUF_SIZE) {
|
||||
cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs);
|
||||
cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs);
|
||||
}
|
||||
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
float xprev = glyphs[0].x;
|
||||
float yprev = glyphs[0].y;
|
||||
xprev = glyphs[0].x;
|
||||
yprev = glyphs[0].y;
|
||||
|
||||
cg_glyphs[0] = glyphs[0].index;
|
||||
cg_advances[0].width = 0;
|
||||
cg_advances[0].height = 0;
|
||||
|
||||
for (i = 1; i < num_glyphs; i++) {
|
||||
float xf = glyphs[i].x;
|
||||
float yf = glyphs[i].y;
|
||||
cg_glyphs[i] = glyphs[i].index;
|
||||
float xf = glyphs[i].x;
|
||||
float yf = glyphs[i].y;
|
||||
cg_advances[i-1].width = xf - xprev;
|
||||
cg_advances[i-1].height = yf - yprev;
|
||||
xprev = xf;
|
||||
yprev = yf;
|
||||
}
|
||||
#else
|
||||
double xprev = glyphs[0].x;
|
||||
double yprev = glyphs[0].y;
|
||||
|
||||
cg_glyphs[0] = glyphs[0].index;
|
||||
cg_advances[0].width = 0;
|
||||
cg_advances[0].height = 0;
|
||||
|
||||
for (i = 1; i < num_glyphs; i++) {
|
||||
cg_glyphs[i] = glyphs[i].index;
|
||||
cg_advances[i-1].width = glyphs[i].x - xprev;
|
||||
cg_advances[i-1].height = glyphs[i].y - yprev;
|
||||
xprev = glyphs[i].x;
|
||||
yprev = glyphs[i].y;
|
||||
}
|
||||
#endif /* MOZCAIRO */
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
|
@ -1364,8 +1431,17 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
free (cg_advances);
|
||||
}
|
||||
|
||||
if (action == DO_SHADING)
|
||||
if (action == DO_IMAGE) {
|
||||
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);
|
||||
} else if (action == DO_SHADING) {
|
||||
CGContextDrawShading (surface->cgContext, surface->sourceShading);
|
||||
}
|
||||
|
||||
_cairo_quartz_teardown_source (surface, source);
|
||||
|
||||
|
@ -1421,6 +1497,7 @@ _cairo_quartz_surface_intersect_clip_path (void *abstract_surface,
|
|||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
quartz_stroke_t stroke;
|
||||
|
||||
ND((stderr, "%p _cairo_quartz_surface_intersect_clip_path path: %p\n", surface, path));
|
||||
|
||||
|
@ -1436,7 +1513,9 @@ _cairo_quartz_surface_intersect_clip_path (void *abstract_surface,
|
|||
CGContextSaveGState (surface->cgContext);
|
||||
} else {
|
||||
CGContextBeginPath (surface->cgContext);
|
||||
_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
|
||||
stroke.cgContext = surface->cgContext;
|
||||
stroke.ctm_inverse = NULL;
|
||||
_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
|
||||
if (fill_rule == CAIRO_FILL_RULE_WINDING)
|
||||
CGContextClip (surface->cgContext);
|
||||
else
|
||||
|
@ -1455,7 +1534,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
|
|||
_cairo_quartz_surface_create_similar,
|
||||
_cairo_quartz_surface_finish,
|
||||
_cairo_quartz_surface_acquire_source_image,
|
||||
NULL, /* release_source_image */
|
||||
_cairo_quartz_surface_release_source_image,
|
||||
_cairo_quartz_surface_acquire_dest_image,
|
||||
_cairo_quartz_surface_release_dest_image,
|
||||
_cairo_quartz_surface_clone_similar,
|
||||
|
|
|
@ -33,34 +33,7 @@
|
|||
* Owen Taylor <otaylor@redhat.com>
|
||||
*/
|
||||
|
||||
#include <cairoint.h>
|
||||
|
||||
/**
|
||||
* _cairo_region_create_from_rectangle:
|
||||
* @rect: a #cairo_rectangle_int16_t
|
||||
*
|
||||
* Creates a region with extents initialized from the given
|
||||
* rectangle.
|
||||
*
|
||||
* Return value: a newly created #pixman_region16_t or %NULL if
|
||||
* memory couldn't a allocated.
|
||||
**/
|
||||
pixman_region16_t *
|
||||
_cairo_region_create_from_rectangle (cairo_rectangle_int16_t *rect)
|
||||
{
|
||||
/* We can't use pixman_region_create_simple(), because it doesn't
|
||||
* have an error return
|
||||
*/
|
||||
pixman_region16_t *region = pixman_region_create ();
|
||||
if (pixman_region_union_rect (region, region,
|
||||
rect->x, rect->y,
|
||||
rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) {
|
||||
pixman_region_destroy (region);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
#include "cairoint.h"
|
||||
|
||||
/**
|
||||
* _cairo_region_extents_rectangle:
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#define _cairo_image_surface_nil_invalid_format __moz__cairo_image_surface_nil_invalid_format
|
||||
#define _cairo_pdf_test_force_fallbacks _moz__cairo_pdf_test_force_fallbacks
|
||||
#define _cairo_ps_test_force_fallbacks _moz__cairo_ps_test_force_fallbacks
|
||||
#define _cairo_scaled_font_test_set_max_glyphs_cached_per_font _moz__cairo_scaled_font_test_set_max_glyphs_cached_per_font
|
||||
|
@ -259,7 +258,6 @@
|
|||
#define cairo_version_string _moz_cairo_version_string
|
||||
#define cairo_win32_font_face_create_for_hfont _moz_cairo_win32_font_face_create_for_hfont
|
||||
#define cairo_win32_font_face_create_for_logfontw _moz_cairo_win32_font_face_create_for_logfontw
|
||||
#define cairo_win32_font_face_create_for_logfontw_hfont _moz_cairo_win32_font_face_create_for_logfontw_hfont
|
||||
#define cairo_win32_scaled_font_done_font _moz_cairo_win32_scaled_font_done_font
|
||||
#define cairo_win32_scaled_font_get_device_to_logical _moz_cairo_win32_scaled_font_get_device_to_logical
|
||||
#define cairo_win32_scaled_font_get_logical_to_device _moz_cairo_win32_scaled_font_get_logical_to_device
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* 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):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_SCALED_FONT_PRIVATE_H
|
||||
#define CAIRO_SCALED_FONT_PRIVATE_H
|
||||
|
||||
#include "cairo.h"
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-mutex-type-private.h"
|
||||
|
||||
struct _cairo_scaled_font {
|
||||
/* For most cairo objects, the rule for multiple threads is that
|
||||
* the user is responsible for any locking if the same object is
|
||||
* manipulated from multiple threads simultaneously.
|
||||
*
|
||||
* However, with the caching that cairo does for scaled fonts, a
|
||||
* user can easily end up with the same cairo_scaled_font object
|
||||
* being manipulated from multiple threads without the user ever
|
||||
* being aware of this, (and in fact, unable to control it).
|
||||
*
|
||||
* So, as a special exception, the cairo implementation takes care
|
||||
* of all locking needed for cairo_scaled_font_t. Most of what is
|
||||
* in the scaled font is immutable, (which is what allows for the
|
||||
* sharing in the first place). The things that are modified and
|
||||
* the locks protecting them are as follows:
|
||||
*
|
||||
* 1. The reference count (scaled_font->ref_count)
|
||||
*
|
||||
* Modifications to the reference count are protected by the
|
||||
* _cairo_scaled_font_map_mutex. This is because the reference
|
||||
* count of a scaled font is intimately related with the font
|
||||
* map itself, (and the magic holdovers array).
|
||||
*
|
||||
* 2. The cache of glyphs (scaled_font->glyphs)
|
||||
* 3. The backend private data (scaled_font->surface_backend,
|
||||
* scaled_font->surface_private)
|
||||
*
|
||||
* Modifications to these fields are protected with locks on
|
||||
* scaled_font->mutex in the generic scaled_font code.
|
||||
*/
|
||||
|
||||
/* must be first to be stored in a hash table */
|
||||
cairo_hash_entry_t hash_entry;
|
||||
|
||||
/* useful bits for _cairo_scaled_font_nil */
|
||||
cairo_status_t status;
|
||||
unsigned int ref_count;
|
||||
cairo_user_data_array_t user_data;
|
||||
|
||||
/* hash key members */
|
||||
cairo_font_face_t *font_face; /* may be NULL */
|
||||
cairo_matrix_t font_matrix; /* font space => user space */
|
||||
cairo_matrix_t ctm; /* user space => device space */
|
||||
cairo_font_options_t options;
|
||||
|
||||
/* "live" scaled_font members */
|
||||
cairo_matrix_t scale; /* font space => device space */
|
||||
cairo_font_extents_t extents; /* user space */
|
||||
|
||||
/* The mutex protects modification to all subsequent fields. */
|
||||
cairo_mutex_t mutex;
|
||||
|
||||
cairo_cache_t *glyphs; /* glyph index -> cairo_scaled_glyph_t */
|
||||
|
||||
/*
|
||||
* One surface backend may store data in each glyph.
|
||||
* Whichever surface manages to store its pointer here
|
||||
* first gets to store data in each glyph
|
||||
*/
|
||||
const cairo_surface_backend_t *surface_backend;
|
||||
void *surface_private;
|
||||
|
||||
/* font backend managing this scaled font */
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
};
|
||||
|
||||
#endif /* CAIRO_SCALED_FONT_PRIVATE_H */
|
|
@ -39,19 +39,17 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
|
||||
typedef struct _cairo_scaled_font_subsets_glyph {
|
||||
unsigned int font_id;
|
||||
unsigned int subset_id;
|
||||
unsigned int subset_glyph_index;
|
||||
cairo_bool_t is_scaled;
|
||||
cairo_bool_t is_composite;
|
||||
double x_advance;
|
||||
} cairo_scaled_font_subsets_glyph_t;
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_subsets_create:
|
||||
*
|
||||
* @max_glyphs_per_unscaled_subset: the maximum number of glyphs that
|
||||
* should appear in any unscaled subset. A value of 0 indicates that
|
||||
* no unscaled subset will be created. All glyphs will mapped to
|
||||
* scaled subsets.
|
||||
*
|
||||
* @max_glyphs_per_scaled_subset: the maximum number of glyphs that
|
||||
* should appear in any scaled subset. A value of 0 indicates that
|
||||
* no scaled subset will be created.
|
||||
* _cairo_scaled_font_subsets_create_scaled:
|
||||
*
|
||||
* Create a new #cairo_scaled_font_subsets_t object which can be used
|
||||
* to create subsets of any number of cairo_scaled_font_t
|
||||
|
@ -60,16 +58,57 @@ typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
|
|||
* subsets with glyph indices packed into the range
|
||||
* [0 .. max_glyphs_per_subset).
|
||||
*
|
||||
* @max_glyphs_per_unscaled_subset and @max_glyphs_per_scaled_subset
|
||||
* cannot both be 0.
|
||||
* Return value: a pointer to the newly creates font subsets. The
|
||||
* caller owns this object and should call
|
||||
* _cairo_scaled_font_subsets_destroy() when done with it.
|
||||
**/
|
||||
cairo_private cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create_scaled (void);
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_subsets_create_simple:
|
||||
*
|
||||
* Create a new #cairo_scaled_font_subsets_t object which can be used
|
||||
* to create font subsets suitable for embedding as Postscript or PDF
|
||||
* simple fonts.
|
||||
*
|
||||
* Glyphs with an outline path available will be mapped to one font
|
||||
* subset for each font face. Glyphs from bitmap fonts will mapped to
|
||||
* separate font subsets for each cairo_scaled_font_t object.
|
||||
*
|
||||
* The maximum number of glyphs per subset is 256. Each subset
|
||||
* reserves the first glyph for the .notdef glyph.
|
||||
*
|
||||
* Return value: a pointer to the newly creates font subsets. The
|
||||
* caller owns this object and should call
|
||||
* _cairo_scaled_font_subsets_destroy() when done with it.
|
||||
**/
|
||||
cairo_private cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create (int max_glyphs_unscaled_per_subset,
|
||||
int max_glyphs_scaled_per_subset);
|
||||
_cairo_scaled_font_subsets_create_simple (void);
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_subsets_create_composite:
|
||||
*
|
||||
* Create a new #cairo_scaled_font_subsets_t object which can be used
|
||||
* to create font subsets suitable for embedding as Postscript or PDF
|
||||
* composite fonts.
|
||||
*
|
||||
* Glyphs with an outline path available will be mapped to one font
|
||||
* subset for each font face. Each unscaled subset has a maximum of
|
||||
* 65536 glyphs except for Type1 fonts which have a maximum of 256 glyphs.
|
||||
*
|
||||
* Glyphs from bitmap fonts will mapped to separate font subsets for
|
||||
* each cairo_scaled_font_t object. Each unscaled subset has a maximum
|
||||
* of 256 glyphs.
|
||||
*
|
||||
* Each subset reserves the first glyph for the .notdef glyph.
|
||||
*
|
||||
* Return value: a pointer to the newly creates font subsets. The
|
||||
* caller owns this object and should call
|
||||
* _cairo_scaled_font_subsets_destroy() when done with it.
|
||||
**/
|
||||
cairo_private cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create_composite (void);
|
||||
|
||||
/**
|
||||
* _cairo_scaled_font_subsets_destroy:
|
||||
|
@ -85,6 +124,8 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
|
|||
* @font_subsets: a #cairo_scaled_font_subsets_t
|
||||
* @scaled_font: the font of the glyph to be mapped
|
||||
* @scaled_font_glyph_index: the index of the glyph to be mapped
|
||||
* @subset_glyph_ret: return structure containing subset font and glyph id
|
||||
*
|
||||
* @font_id_ret: return value giving the font ID of the mapped glyph
|
||||
* @subset_id_ret: return value giving the subset ID of the mapped glyph within the @font_id_ret
|
||||
* @subset_glyph_index_ret: return value giving the index of the mapped glyph within the @subset_id_ret subset
|
||||
|
@ -126,6 +167,17 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
|
|||
* used by #cairo_scaled_font_subset_t as provided by
|
||||
* _cairo_scaled_font_subsets_foreach.
|
||||
*
|
||||
* The returned values in the cairo_scaled_font_subsets_glyph_t struct are:
|
||||
*
|
||||
* @font_id: The font ID of the mapped glyph
|
||||
* @subset_id : The subset ID of the mapped glyph within the @font_id
|
||||
* @subset_glyph_index: The index of the mapped glyph within the @subset_id subset
|
||||
* @is_scaled: If true, the mapped glyph is from a bitmap font, and separate font
|
||||
* subset is created for each font scale used. If false, the outline of the mapped glyph
|
||||
* is available. One font subset for each font face is created.
|
||||
* @x_advance: When @is_scaled is true, @x_advance contains the x_advance for the mapped glyph in device space.
|
||||
* When @is_scaled is false, @x_advance contains the x_advance for the the mapped glyph from an unhinted 1 point font.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful, or a non-zero
|
||||
* value indicating an error. Possible errors include
|
||||
* CAIRO_STATUS_NO_MEMORY.
|
||||
|
@ -134,9 +186,7 @@ cairo_private cairo_status_t
|
|||
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *font_subsets,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned long scaled_font_glyph_index,
|
||||
unsigned int *font_id_ret,
|
||||
unsigned int *subset_id_ret,
|
||||
unsigned int *subset_glyph_index_ret);
|
||||
cairo_scaled_font_subsets_glyph_t *subset_glyph_ret);
|
||||
|
||||
typedef void
|
||||
(*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset,
|
||||
|
@ -253,6 +303,37 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
|
|||
cairo_private void
|
||||
_cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
|
||||
|
||||
/**
|
||||
* _cairo_cff_fallback_init:
|
||||
* @cff_subset: a #cairo_cff_subset_t to initialize
|
||||
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
|
||||
*
|
||||
* If possible (depending on the format of the underlying
|
||||
* cairo_scaled_font_t and the font backend in use) generate a cff
|
||||
* file corresponding to @font_subset and initialize @cff_subset
|
||||
* with information about the subset and the cff data.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful,
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
|
||||
* cff file, or an non-zero value indicating an error. Possible
|
||||
* errors include CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
|
||||
const char *name,
|
||||
cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
/**
|
||||
* _cairo_cff_fallback_fini:
|
||||
* @cff_subset: a #cairo_cff_subset_t
|
||||
*
|
||||
* Free all resources associated with @cff_subset. After this
|
||||
* call, @cff_subset should not be used again without a
|
||||
* subsequent call to _cairo_cff_subset_init() again first.
|
||||
**/
|
||||
cairo_private void
|
||||
_cairo_cff_fallback_fini (cairo_cff_subset_t *cff_subset);
|
||||
|
||||
typedef struct _cairo_truetype_subset {
|
||||
char *base_font;
|
||||
double *widths;
|
||||
|
@ -341,6 +422,15 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type_subset,
|
|||
cairo_private void
|
||||
_cairo_type1_subset_fini (cairo_type1_subset_t *subset);
|
||||
|
||||
/**
|
||||
* _cairo_type1_scaled_font_is_type1:
|
||||
* @scaled_font: a #cairo_scaled_font_t
|
||||
*
|
||||
* Return TRUE if @scaled_font is a Type 1 font, otherwise return FALSE.
|
||||
**/
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font);
|
||||
|
||||
/**
|
||||
* _cairo_type1_fallback_init_binary:
|
||||
* @type1_subset: a #cairo_type1_subset_t to initialize
|
||||
|
@ -394,6 +484,43 @@ _cairo_type1_fallback_init_hex (cairo_type1_subset_t *type_subset,
|
|||
cairo_private void
|
||||
_cairo_type1_fallback_fini (cairo_type1_subset_t *subset);
|
||||
|
||||
typedef struct _cairo_type2_charstrings {
|
||||
int *widths;
|
||||
long x_min, y_min, x_max, y_max;
|
||||
long ascent, descent;
|
||||
cairo_array_t charstrings;
|
||||
} cairo_type2_charstrings_t;
|
||||
|
||||
/**
|
||||
* _cairo_type2_charstrings_init:
|
||||
* @type2_subset: a #cairo_type2_subset_t to initialize
|
||||
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
|
||||
*
|
||||
* If possible (depending on the format of the underlying
|
||||
* cairo_scaled_font_t and the font backend in use) generate type2
|
||||
* charstrings to @font_subset and initialize @type2_subset
|
||||
* with information about the subset.
|
||||
*
|
||||
* Return value: CAIRO_STATUS_SUCCESS if successful,
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type2
|
||||
* charstrings, or an non-zero value indicating an error. Possible errors
|
||||
* include CAIRO_STATUS_NO_MEMORY.
|
||||
**/
|
||||
cairo_private cairo_status_t
|
||||
_cairo_type2_charstrings_init (cairo_type2_charstrings_t *charstrings,
|
||||
cairo_scaled_font_subset_t *font_subset);
|
||||
|
||||
/**
|
||||
* _cairo_type2_charstrings_fini:
|
||||
* @subset: a #cairo_type2_charstrings_t
|
||||
*
|
||||
* Free all resources associated with @type2_charstring. After this call,
|
||||
* @type2_charstring should not be used again without a subsequent call to
|
||||
* _cairo_type2_charstring_init() again first.
|
||||
**/
|
||||
cairo_private void
|
||||
_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *charstrings);
|
||||
|
||||
/**
|
||||
* _cairo_truetype_create_glyph_to_unicode_map:
|
||||
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
|
||||
|
|
|
@ -42,12 +42,21 @@
|
|||
#include "cairoint.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
|
||||
#define MAX_GLYPHS_PER_SIMPLE_FONT 256
|
||||
#define MAX_GLYPHS_PER_COMPOSITE_FONT 65536
|
||||
|
||||
typedef enum {
|
||||
CAIRO_SUBSETS_SCALED,
|
||||
CAIRO_SUBSETS_SIMPLE,
|
||||
CAIRO_SUBSETS_COMPOSITE
|
||||
} cairo_subsets_type_t;
|
||||
|
||||
struct _cairo_scaled_font_subsets {
|
||||
int max_glyphs_per_unscaled_subset_limit;
|
||||
cairo_subsets_type_t type;
|
||||
|
||||
int max_glyphs_per_unscaled_subset_used;
|
||||
cairo_hash_table_t *unscaled_sub_fonts;
|
||||
|
||||
int max_glyphs_per_scaled_subset_limit;
|
||||
int max_glyphs_per_scaled_subset_used;
|
||||
cairo_hash_table_t *scaled_sub_fonts;
|
||||
|
||||
|
@ -58,6 +67,7 @@ typedef struct _cairo_sub_font {
|
|||
cairo_hash_entry_t base;
|
||||
|
||||
cairo_bool_t is_scaled;
|
||||
cairo_bool_t is_composite;
|
||||
cairo_scaled_font_subsets_t *parent;
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
unsigned int font_id;
|
||||
|
@ -74,6 +84,7 @@ typedef struct _cairo_sub_font_glyph {
|
|||
|
||||
unsigned int subset_id;
|
||||
unsigned int subset_glyph_index;
|
||||
double x_advance;
|
||||
} cairo_sub_font_glyph_t;
|
||||
|
||||
typedef struct _cairo_sub_font_collection {
|
||||
|
@ -107,7 +118,8 @@ _cairo_sub_font_glyphs_equal (const void *key_a, const void *key_b)
|
|||
static cairo_sub_font_glyph_t *
|
||||
_cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
|
||||
unsigned int subset_id,
|
||||
unsigned int subset_glyph_index)
|
||||
unsigned int subset_glyph_index,
|
||||
double x_advance)
|
||||
{
|
||||
cairo_sub_font_glyph_t *sub_font_glyph;
|
||||
|
||||
|
@ -118,6 +130,7 @@ _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
|
|||
_cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index);
|
||||
sub_font_glyph->subset_id = subset_id;
|
||||
sub_font_glyph->subset_glyph_index = subset_glyph_index;
|
||||
sub_font_glyph->x_advance = x_advance;
|
||||
|
||||
return sub_font_glyph;
|
||||
}
|
||||
|
@ -195,7 +208,8 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
|||
cairo_scaled_font_t *scaled_font,
|
||||
unsigned int font_id,
|
||||
int max_glyphs_per_subset,
|
||||
cairo_bool_t is_scaled)
|
||||
cairo_bool_t is_scaled,
|
||||
cairo_bool_t is_composite)
|
||||
{
|
||||
cairo_sub_font_t *sub_font;
|
||||
|
||||
|
@ -204,10 +218,11 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
|||
return NULL;
|
||||
|
||||
sub_font->is_scaled = is_scaled;
|
||||
sub_font->is_composite = is_composite;
|
||||
_cairo_sub_font_init_key (sub_font, scaled_font);
|
||||
|
||||
sub_font->parent = parent;
|
||||
sub_font->scaled_font = cairo_scaled_font_reference (scaled_font);
|
||||
sub_font->scaled_font = scaled_font;
|
||||
sub_font->font_id = font_id;
|
||||
|
||||
sub_font->current_subset = 0;
|
||||
|
@ -220,6 +235,11 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (parent->type != CAIRO_SUBSETS_SCALED) {
|
||||
/* Reserve first glyph in subset for the .notdef glyph */
|
||||
sub_font->num_glyphs_in_current_subset++;
|
||||
}
|
||||
|
||||
return sub_font;
|
||||
}
|
||||
|
||||
|
@ -245,10 +265,9 @@ _cairo_sub_font_pluck (void *entry, void *closure)
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
|
||||
unsigned long scaled_font_glyph_index,
|
||||
unsigned int *subset_id,
|
||||
unsigned int *subset_glyph_index)
|
||||
_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
|
||||
unsigned long scaled_font_glyph_index,
|
||||
cairo_scaled_font_subsets_glyph_t *subset_glyph)
|
||||
{
|
||||
cairo_sub_font_glyph_t key, *sub_font_glyph;
|
||||
|
||||
|
@ -256,8 +275,12 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
|
|||
if (_cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font_glyph))
|
||||
{
|
||||
*subset_id = sub_font_glyph->subset_id;
|
||||
*subset_glyph_index = sub_font_glyph->subset_glyph_index;
|
||||
subset_glyph->font_id = sub_font->font_id;
|
||||
subset_glyph->subset_id = sub_font_glyph->subset_id;
|
||||
subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
|
||||
subset_glyph->is_scaled = sub_font->is_scaled;
|
||||
subset_glyph->is_composite = sub_font->is_composite;
|
||||
subset_glyph->x_advance = sub_font_glyph->x_advance;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -268,11 +291,11 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
|
|||
static cairo_status_t
|
||||
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
||||
unsigned long scaled_font_glyph_index,
|
||||
unsigned int *subset_id,
|
||||
unsigned int *subset_glyph_index)
|
||||
cairo_scaled_font_subsets_glyph_t *subset_glyph)
|
||||
{
|
||||
cairo_sub_font_glyph_t key, *sub_font_glyph;
|
||||
cairo_status_t status;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
|
||||
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
|
||||
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
|
||||
|
@ -282,11 +305,24 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
|||
{
|
||||
sub_font->current_subset++;
|
||||
sub_font->num_glyphs_in_current_subset = 0;
|
||||
|
||||
if (sub_font->parent->type != CAIRO_SUBSETS_SCALED) {
|
||||
/* Reserve first glyph in subset for the .notdef glyph */
|
||||
sub_font->num_glyphs_in_current_subset++;
|
||||
}
|
||||
}
|
||||
|
||||
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
|
||||
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
|
||||
scaled_font_glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
||||
&scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
|
||||
sub_font->current_subset,
|
||||
sub_font->num_glyphs_in_current_subset++);
|
||||
sub_font->num_glyphs_in_current_subset++,
|
||||
scaled_glyph->metrics.x_advance);
|
||||
if (sub_font_glyph == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
|
@ -302,12 +338,18 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
|
|||
}
|
||||
|
||||
status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
|
||||
if (status)
|
||||
if (status) {
|
||||
_cairo_sub_font_glyph_destroy (sub_font_glyph);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
*subset_id = sub_font_glyph->subset_id;
|
||||
*subset_glyph_index = sub_font_glyph->subset_glyph_index;
|
||||
subset_glyph->font_id = sub_font->font_id;
|
||||
subset_glyph->subset_id = sub_font_glyph->subset_id;
|
||||
subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
|
||||
subset_glyph->is_scaled = sub_font->is_scaled;
|
||||
subset_glyph->is_composite = sub_font->is_composite;
|
||||
subset_glyph->x_advance = sub_font_glyph->x_advance;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -324,16 +366,24 @@ _cairo_sub_font_collect (void *entry, void *closure)
|
|||
for (i = 0; i <= sub_font->current_subset; i++) {
|
||||
collection->subset_id = i;
|
||||
|
||||
collection->num_glyphs = 0;
|
||||
collection->max_glyph = 0;
|
||||
if (sub_font->parent->type == CAIRO_SUBSETS_SCALED) {
|
||||
collection->num_glyphs = 0;
|
||||
collection->max_glyph = 0;
|
||||
} else {
|
||||
/* Assign .notdef glyph to the first glyph in the subset */
|
||||
collection->glyphs[0] = 0;
|
||||
collection->num_glyphs = 1;
|
||||
collection->max_glyph = 0;
|
||||
}
|
||||
|
||||
_cairo_hash_table_foreach (sub_font->sub_font_glyphs,
|
||||
_cairo_sub_font_glyph_collect, collection);
|
||||
|
||||
/* Ensure the resulting array has no uninitialized holes */
|
||||
/* Ensure the resulting array has no uninitialized holes */
|
||||
assert (collection->num_glyphs == collection->max_glyph + 1);
|
||||
|
||||
subset.scaled_font = sub_font->scaled_font;
|
||||
subset.is_composite = sub_font->is_composite;
|
||||
subset.font_id = sub_font->font_id;
|
||||
subset.subset_id = i;
|
||||
subset.glyphs = collection->glyphs;
|
||||
|
@ -355,9 +405,8 @@ _cairo_sub_font_collect (void *entry, void *closure)
|
|||
}
|
||||
}
|
||||
|
||||
cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
|
||||
int max_glyphs_per_scaled_subset)
|
||||
static cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
|
||||
{
|
||||
cairo_scaled_font_subsets_t *subsets;
|
||||
|
||||
|
@ -365,12 +414,9 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
|
|||
if (subsets == NULL)
|
||||
return NULL;
|
||||
|
||||
subsets->max_glyphs_per_unscaled_subset_limit = max_glyphs_per_unscaled_subset;
|
||||
subsets->type = type;
|
||||
subsets->max_glyphs_per_unscaled_subset_used = 0;
|
||||
|
||||
subsets->max_glyphs_per_scaled_subset_limit = max_glyphs_per_scaled_subset;
|
||||
subsets->max_glyphs_per_scaled_subset_used = 0;
|
||||
|
||||
subsets->num_sub_fonts = 0;
|
||||
|
||||
subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
|
||||
|
@ -381,7 +427,7 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
|
|||
|
||||
subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
|
||||
if (! subsets->scaled_sub_fonts) {
|
||||
free (subsets->unscaled_sub_fonts);
|
||||
_cairo_hash_table_destroy (subsets->unscaled_sub_fonts);
|
||||
free (subsets);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -389,6 +435,24 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
|
|||
return subsets;
|
||||
}
|
||||
|
||||
cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create_scaled (void)
|
||||
{
|
||||
return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SCALED);
|
||||
}
|
||||
|
||||
cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create_simple (void)
|
||||
{
|
||||
return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SIMPLE);
|
||||
}
|
||||
|
||||
cairo_scaled_font_subsets_t *
|
||||
_cairo_scaled_font_subsets_create_composite (void)
|
||||
{
|
||||
return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_COMPOSITE);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
|
||||
{
|
||||
|
@ -404,44 +468,44 @@ cairo_private 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,
|
||||
unsigned int *font_id,
|
||||
unsigned int *subset_id,
|
||||
unsigned int *subset_glyph_index)
|
||||
cairo_scaled_font_subsets_glyph_t *subset_glyph)
|
||||
{
|
||||
cairo_sub_font_t key, *sub_font;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_font_face_t *font_face;
|
||||
cairo_matrix_t identity;
|
||||
cairo_font_options_t font_options;
|
||||
cairo_scaled_font_t *unscaled_font;
|
||||
cairo_status_t status;
|
||||
int max_glyphs;
|
||||
cairo_bool_t type1_font;
|
||||
|
||||
/* Lookup glyph in unscaled subsets */
|
||||
if (subsets->max_glyphs_per_unscaled_subset_limit > 0) {
|
||||
if (subsets->type != CAIRO_SUBSETS_SCALED) {
|
||||
key.is_scaled = FALSE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font))
|
||||
{
|
||||
status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
|
||||
subset_id, subset_glyph_index);
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
*font_id = sub_font->font_id;
|
||||
status = _cairo_sub_font_lookup_glyph (sub_font,
|
||||
scaled_font_glyph_index,
|
||||
subset_glyph);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Lookup glyph in scaled subsets */
|
||||
if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
|
||||
key.is_scaled = TRUE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font))
|
||||
{
|
||||
status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
|
||||
subset_id, subset_glyph_index);
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
*font_id = sub_font->font_id;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
key.is_scaled = TRUE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font))
|
||||
{
|
||||
status = _cairo_sub_font_lookup_glyph (sub_font,
|
||||
scaled_font_glyph_index,
|
||||
subset_glyph);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Glyph not found. Determine whether the glyph is outline or
|
||||
|
@ -450,51 +514,96 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
|
|||
scaled_font_glyph_index,
|
||||
CAIRO_SCALED_GLYPH_INFO_PATH,
|
||||
&scaled_glyph);
|
||||
if (status == 0 && subsets->max_glyphs_per_unscaled_subset_limit > 0) {
|
||||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
if (status == 0 && subsets->type != CAIRO_SUBSETS_SCALED) {
|
||||
/* Path available. Add to unscaled subset. */
|
||||
key.is_scaled = FALSE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
if (! _cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font))
|
||||
{
|
||||
sub_font = _cairo_sub_font_create (subsets, scaled_font,
|
||||
font_face = cairo_scaled_font_get_font_face (scaled_font);
|
||||
cairo_matrix_init_identity (&identity);
|
||||
_cairo_font_options_init_default (&font_options);
|
||||
cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
|
||||
cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);
|
||||
unscaled_font = cairo_scaled_font_create (font_face,
|
||||
&identity,
|
||||
&identity,
|
||||
&font_options);
|
||||
if (unscaled_font->status)
|
||||
return unscaled_font->status;
|
||||
|
||||
subset_glyph->is_scaled = FALSE;
|
||||
type1_font = FALSE;
|
||||
#if CAIRO_HAS_FT_FONT
|
||||
type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font);
|
||||
#endif
|
||||
if (subsets->type == CAIRO_SUBSETS_COMPOSITE && !type1_font) {
|
||||
max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT;
|
||||
subset_glyph->is_composite = TRUE;
|
||||
} else {
|
||||
max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
|
||||
subset_glyph->is_composite = FALSE;
|
||||
}
|
||||
|
||||
sub_font = _cairo_sub_font_create (subsets,
|
||||
unscaled_font,
|
||||
subsets->num_sub_fonts++,
|
||||
subsets->max_glyphs_per_unscaled_subset_limit,
|
||||
FALSE);
|
||||
if (sub_font == NULL)
|
||||
max_glyphs,
|
||||
subset_glyph->is_scaled,
|
||||
subset_glyph->is_composite);
|
||||
if (sub_font == NULL) {
|
||||
cairo_scaled_font_destroy (unscaled_font);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts,
|
||||
&sub_font->base);
|
||||
if (status)
|
||||
if (status) {
|
||||
_cairo_sub_font_destroy (sub_font);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
} else if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
|
||||
} else {
|
||||
/* No path available. Add to scaled subset. */
|
||||
key.is_scaled = TRUE;
|
||||
_cairo_sub_font_init_key (&key, scaled_font);
|
||||
if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
|
||||
(cairo_hash_entry_t **) &sub_font))
|
||||
{
|
||||
sub_font = _cairo_sub_font_create (subsets, scaled_font,
|
||||
subset_glyph->is_scaled = TRUE;
|
||||
subset_glyph->is_composite = FALSE;
|
||||
if (subsets->type == CAIRO_SUBSETS_SCALED)
|
||||
max_glyphs = INT_MAX;
|
||||
else
|
||||
max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
|
||||
|
||||
sub_font = _cairo_sub_font_create (subsets,
|
||||
cairo_scaled_font_reference (scaled_font),
|
||||
subsets->num_sub_fonts++,
|
||||
subsets->max_glyphs_per_scaled_subset_limit,
|
||||
TRUE);
|
||||
if (sub_font == NULL)
|
||||
max_glyphs,
|
||||
subset_glyph->is_scaled,
|
||||
subset_glyph->is_composite);
|
||||
if (sub_font == NULL) {
|
||||
cairo_scaled_font_destroy (scaled_font);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = _cairo_hash_table_insert (subsets->scaled_sub_fonts,
|
||||
&sub_font->base);
|
||||
if (status)
|
||||
if (status) {
|
||||
_cairo_sub_font_destroy (sub_font);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
*font_id = sub_font->font_id;
|
||||
|
||||
return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index,
|
||||
subset_id, subset_glyph_index);
|
||||
return _cairo_sub_font_map_glyph (sub_font,
|
||||
scaled_font_glyph_index,
|
||||
subset_glyph);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -509,6 +618,10 @@ _cairo_scaled_font_subsets_foreach_internal (cairo_scaled_font_subsets_t
|
|||
collection.glyphs_size = font_subsets->max_glyphs_per_scaled_subset_used;
|
||||
else
|
||||
collection.glyphs_size = font_subsets->max_glyphs_per_unscaled_subset_used;
|
||||
|
||||
if (! collection.glyphs_size)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
collection.glyphs = malloc (collection.glyphs_size * sizeof(unsigned long));
|
||||
if (collection.glyphs == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
@ -540,7 +653,7 @@ _cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *fon
|
|||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
|
||||
_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
|
||||
cairo_scaled_font_subset_callback_func_t font_subset_callback,
|
||||
void *closure)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-scaled-font-test.h"
|
||||
#include "cairo-scaled-font-private.h"
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
|
||||
|
@ -135,6 +135,9 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
|
|||
cairo_font_type_t
|
||||
cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return CAIRO_FONT_TYPE_TOY;
|
||||
|
||||
return scaled_font->backend->type;
|
||||
}
|
||||
|
||||
|
@ -153,6 +156,7 @@ cairo_scaled_font_status (cairo_scaled_font_t *scaled_font)
|
|||
{
|
||||
return scaled_font->status;
|
||||
}
|
||||
slim_hidden_def (cairo_scaled_font_status);
|
||||
|
||||
/* Here we keep a unique mapping from
|
||||
* cairo_font_face_t/matrix/ctm/options => cairo_scaled_font_t.
|
||||
|
@ -185,8 +189,6 @@ typedef struct _cairo_scaled_font_map {
|
|||
|
||||
static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
|
||||
|
||||
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex);
|
||||
|
||||
static int
|
||||
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b);
|
||||
|
||||
|
@ -213,6 +215,7 @@ _cairo_scaled_font_map_lock (void)
|
|||
|
||||
CLEANUP_SCALED_FONT_MAP:
|
||||
free (cairo_scaled_font_map);
|
||||
cairo_scaled_font_map = NULL;
|
||||
CLEANUP_MUTEX_LOCK:
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
|
||||
return NULL;
|
||||
|
@ -331,14 +334,7 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_
|
|||
* separately is probably not what we want anyway. Would probably be
|
||||
* much better to have a single cache for glyphs with random
|
||||
* replacement across all glyphs of all fonts. */
|
||||
static int max_glyphs_cached_per_font = 256;
|
||||
|
||||
/* For internal testing purposes only. Not part of the supported API. */
|
||||
void
|
||||
_cairo_scaled_font_test_set_max_glyphs_cached_per_font (int max)
|
||||
{
|
||||
max_glyphs_cached_per_font = max;
|
||||
}
|
||||
#define MAX_GLYPHS_CACHED_PER_FONT 256
|
||||
|
||||
/*
|
||||
* Basic cairo_scaled_font_t object management
|
||||
|
@ -352,23 +348,40 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
|||
const cairo_font_options_t *options,
|
||||
const cairo_scaled_font_backend_t *backend)
|
||||
{
|
||||
scaled_font->ref_count = 1;
|
||||
cairo_matrix_t inverse;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_user_data_array_init (&scaled_font->user_data);
|
||||
status = cairo_font_options_status ((cairo_font_options_t *) options);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Initialize scaled_font->scale early for easier bail out on an
|
||||
* invalid matrix. */
|
||||
_cairo_scaled_font_init_key (scaled_font, font_face,
|
||||
font_matrix, ctm, options);
|
||||
|
||||
cairo_font_face_reference (font_face);
|
||||
|
||||
cairo_matrix_multiply (&scaled_font->scale,
|
||||
&scaled_font->font_matrix,
|
||||
&scaled_font->ctm);
|
||||
|
||||
CAIRO_MUTEX_INIT (&scaled_font->mutex);
|
||||
inverse = scaled_font->scale;
|
||||
status = cairo_matrix_invert (&inverse);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
|
||||
_cairo_scaled_glyph_destroy,
|
||||
max_glyphs_cached_per_font);
|
||||
MAX_GLYPHS_CACHED_PER_FONT);
|
||||
if (scaled_font->glyphs == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
scaled_font->ref_count = 1;
|
||||
|
||||
_cairo_user_data_array_init (&scaled_font->user_data);
|
||||
|
||||
cairo_font_face_reference (font_face);
|
||||
|
||||
CAIRO_MUTEX_INIT (scaled_font->mutex);
|
||||
|
||||
scaled_font->surface_backend = NULL;
|
||||
scaled_font->surface_private = NULL;
|
||||
|
@ -396,7 +409,7 @@ _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
|
|||
_cairo_cache_destroy (scaled_font->glyphs);
|
||||
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
|
||||
_cairo_scaled_glyph_destroy,
|
||||
max_glyphs_cached_per_font);
|
||||
MAX_GLYPHS_CACHED_PER_FONT);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -430,7 +443,7 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
|||
if (scaled_font->glyphs != NULL)
|
||||
_cairo_cache_destroy (scaled_font->glyphs);
|
||||
|
||||
CAIRO_MUTEX_FINI (&scaled_font->mutex);
|
||||
CAIRO_MUTEX_FINI (scaled_font->mutex);
|
||||
|
||||
if (scaled_font->surface_backend != NULL &&
|
||||
scaled_font->surface_backend->scaled_font_fini != NULL)
|
||||
|
@ -474,9 +487,12 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
|||
if (font_face->status)
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
|
||||
if (cairo_font_options_status ((cairo_font_options_t *) options))
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
|
||||
font_map = _cairo_scaled_font_map_lock ();
|
||||
if (font_map == NULL)
|
||||
return NULL;
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
|
||||
_cairo_scaled_font_init_key (&key, font_face,
|
||||
font_matrix, ctm, options);
|
||||
|
@ -501,35 +517,44 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
|||
memmove (&font_map->holdovers[i],
|
||||
&font_map->holdovers[i+1],
|
||||
(font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
|
||||
|
||||
/* reset any error status */
|
||||
scaled_font->status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* We increment the reference count manually here, (rather
|
||||
* than calling into cairo_scaled_font_reference), since we
|
||||
* must modify the reference count while our lock is still
|
||||
* held. */
|
||||
scaled_font->ref_count++;
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
} else {
|
||||
/* Otherwise create it and insert it into the hash table. */
|
||||
status = font_face->backend->scaled_font_create (font_face, font_matrix,
|
||||
ctm, options, &scaled_font);
|
||||
if (status) {
|
||||
if (scaled_font->status == CAIRO_STATUS_SUCCESS) {
|
||||
/* We increment the reference count manually here, (rather
|
||||
* than calling into cairo_scaled_font_reference), since we
|
||||
* must modify the reference count while our lock is still
|
||||
* held. */
|
||||
scaled_font->ref_count++;
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
return NULL;
|
||||
return scaled_font;
|
||||
}
|
||||
|
||||
status = _cairo_hash_table_insert (font_map->hash_table,
|
||||
&scaled_font->hash_entry);
|
||||
/* the font has been put into an error status - abandon the cache */
|
||||
_cairo_hash_table_remove (font_map->hash_table, &key.hash_entry);
|
||||
}
|
||||
|
||||
/* Otherwise create it and insert it into the hash table. */
|
||||
status = font_face->backend->scaled_font_create (font_face, font_matrix,
|
||||
ctm, options, &scaled_font);
|
||||
if (status) {
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
/* We can't call _cairo_scaled_font_destroy here since it expects
|
||||
* that the font has already been successfully inserted into the
|
||||
* hash table. */
|
||||
_cairo_scaled_font_fini (scaled_font);
|
||||
free (scaled_font);
|
||||
return NULL;
|
||||
}
|
||||
status = _cairo_hash_table_insert (font_map->hash_table,
|
||||
&scaled_font->hash_entry);
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
|
||||
if (status) {
|
||||
/* We can't call _cairo_scaled_font_destroy here since it expects
|
||||
* that the font has already been successfully inserted into the
|
||||
* hash table. */
|
||||
_cairo_scaled_font_fini (scaled_font);
|
||||
free (scaled_font);
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
}
|
||||
|
||||
return scaled_font;
|
||||
|
@ -748,10 +773,13 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
|
|||
const char *utf8,
|
||||
cairo_text_extents_t *extents)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_status_t status;
|
||||
cairo_glyph_t *glyphs;
|
||||
int num_glyphs;
|
||||
|
||||
if (scaled_font->status)
|
||||
return;
|
||||
|
||||
status = _cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., utf8, &glyphs, &num_glyphs);
|
||||
if (status) {
|
||||
_cairo_scaled_font_set_error (scaled_font, status);
|
||||
|
@ -774,7 +802,7 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
|
|||
* graphics state were set to the same font_face, font_matrix, ctm,
|
||||
* and font_options as @scaled_font). Additionally, the x_advance and
|
||||
* y_advance values indicate the amount by which the current point
|
||||
* would be advanced by cairo_show_glyphs.
|
||||
* would be advanced by cairo_show_glyphs().
|
||||
*
|
||||
* Note that whitespace glyphs do not contribute to the size of the
|
||||
* rectangle (extents.width and extents.height).
|
||||
|
@ -785,7 +813,7 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
|
|||
int num_glyphs,
|
||||
cairo_text_extents_t *extents)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0;
|
||||
cairo_bool_t visible = FALSE;
|
||||
|
@ -1100,7 +1128,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
|
||||
_cairo_pattern_fini (&glyph_pattern.base);
|
||||
if (status)
|
||||
break;
|
||||
goto CLEANUP_MASK;
|
||||
}
|
||||
|
||||
if (mask != NULL) {
|
||||
|
@ -1176,6 +1204,42 @@ _scaled_glyph_path_close_path (void *abstract_closure)
|
|||
return _cairo_path_fixed_close_path (closure->path);
|
||||
}
|
||||
|
||||
/* Add a single-device-unit rectangle to a path. */
|
||||
static cairo_status_t
|
||||
_add_unit_rectangle_to_path (cairo_path_fixed_t *path, int x, int y)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_path_fixed_move_to (path,
|
||||
_cairo_fixed_from_int (x),
|
||||
_cairo_fixed_from_int (y));
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_path_fixed_rel_line_to (path,
|
||||
_cairo_fixed_from_int (1),
|
||||
_cairo_fixed_from_int (0));
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_path_fixed_rel_line_to (path,
|
||||
_cairo_fixed_from_int (0),
|
||||
_cairo_fixed_from_int (1));
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_path_fixed_rel_line_to (path,
|
||||
_cairo_fixed_from_int (-1),
|
||||
_cairo_fixed_from_int (0));
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_path_fixed_close_path (path);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* _trace_mask_to_path:
|
||||
|
@ -1198,6 +1262,7 @@ static cairo_status_t
|
|||
_trace_mask_to_path (cairo_image_surface_t *mask,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_image_surface_t *a1_mask;
|
||||
unsigned char *row, *byte_ptr, byte;
|
||||
int rows, cols, bytes_per_row;
|
||||
|
@ -1220,19 +1285,10 @@ _trace_mask_to_path (cairo_image_surface_t *mask,
|
|||
byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte_ptr);
|
||||
for (bit = 7; bit >= 0 && x < a1_mask->width; bit--, x++) {
|
||||
if (byte & (1 << bit)) {
|
||||
_cairo_path_fixed_move_to (path,
|
||||
_cairo_fixed_from_int (x + xoff),
|
||||
_cairo_fixed_from_int (y + yoff));
|
||||
_cairo_path_fixed_rel_line_to (path,
|
||||
_cairo_fixed_from_int (1),
|
||||
_cairo_fixed_from_int (0));
|
||||
_cairo_path_fixed_rel_line_to (path,
|
||||
_cairo_fixed_from_int (0),
|
||||
_cairo_fixed_from_int (1));
|
||||
_cairo_path_fixed_rel_line_to (path,
|
||||
_cairo_fixed_from_int (-1),
|
||||
_cairo_fixed_from_int (0));
|
||||
_cairo_path_fixed_close_path (path);
|
||||
status = _add_unit_rectangle_to_path (path,
|
||||
x + xoff, y + yoff);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1278,6 +1334,8 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
|||
glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
&scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
glyph_path = _cairo_path_fixed_create ();
|
||||
if (glyph_path == NULL)
|
||||
|
@ -1302,6 +1360,9 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
|||
&closure);
|
||||
if (glyph_path != scaled_glyph->path)
|
||||
_cairo_path_fixed_destroy (glyph_path);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -1601,6 +1662,9 @@ void
|
|||
cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font,
|
||||
cairo_font_options_t *options)
|
||||
{
|
||||
if (cairo_font_options_status (options))
|
||||
return;
|
||||
|
||||
if (scaled_font->status) {
|
||||
_cairo_font_options_init_default (options);
|
||||
return;
|
||||
|
|
|
@ -26,7 +26,24 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#define MAX_LEVEL 31
|
||||
/*
|
||||
* Skip lists are described in detail here:
|
||||
*
|
||||
* http://citeseer.ist.psu.edu/pugh90skip.html
|
||||
*/
|
||||
|
||||
/* Note that random_level() called from alloc_node_for_level() depends on
|
||||
* this being not more than 16.
|
||||
*/
|
||||
#define MAX_LEVEL 15
|
||||
|
||||
/* Returns the index of the free-list to use for a node at level 'level' */
|
||||
#define FREELIST_FOR_LEVEL(level) (((level) - 1) / 2)
|
||||
|
||||
/* Returns the maximum level that uses the same free-list as 'level' does */
|
||||
#define FREELIST_MAX_LEVEL_FOR(level) (((level) + 1) & ~1)
|
||||
|
||||
#define MAX_FREELIST_LEVEL (FREELIST_FOR_LEVEL (MAX_LEVEL - 1) + 1)
|
||||
|
||||
/*
|
||||
* Skip list element. In order to use the skip list, the caller must
|
||||
|
@ -52,7 +69,7 @@ typedef struct _skip_list {
|
|||
size_t elt_size;
|
||||
size_t data_size;
|
||||
skip_elt_t *chains[MAX_LEVEL];
|
||||
skip_elt_t *freelists[MAX_LEVEL];
|
||||
skip_elt_t *freelists[MAX_FREELIST_LEVEL];
|
||||
int max_level;
|
||||
} cairo_skip_list_t;
|
||||
|
||||
|
|
|
@ -21,11 +21,7 @@
|
|||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-skiplist-private.h"
|
||||
|
||||
|
@ -236,6 +232,9 @@ _cairo_skip_list_init (cairo_skip_list_t *list,
|
|||
|
||||
for (i = 0; i < MAX_LEVEL; i++) {
|
||||
list->chains[i] = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_FREELIST_LEVEL; i++) {
|
||||
list->freelists[i] = NULL;
|
||||
}
|
||||
|
||||
|
@ -251,7 +250,7 @@ _cairo_skip_list_fini (cairo_skip_list_t *list)
|
|||
while ((elt = list->chains[0])) {
|
||||
_cairo_skip_list_delete_given (list, elt);
|
||||
}
|
||||
for (i=0; i<MAX_LEVEL; i++) {
|
||||
for (i=0; i<MAX_FREELIST_LEVEL; i++) {
|
||||
elt = list->freelists[i];
|
||||
while (elt) {
|
||||
skip_elt_t *nextfree = elt->prev;
|
||||
|
@ -265,14 +264,17 @@ _cairo_skip_list_fini (cairo_skip_list_t *list)
|
|||
* Generate a random level number, distributed
|
||||
* so that each level is 1/4 as likely as the one before
|
||||
*
|
||||
* Note that level numbers run 1 <= level <= MAX_LEVEL
|
||||
* Note that level numbers run 1 <= level < MAX_LEVEL
|
||||
*/
|
||||
static int
|
||||
random_level (void)
|
||||
{
|
||||
/* tricky bit -- each bit is '1' 75% of the time */
|
||||
long int bits = lfsr_random() | lfsr_random();
|
||||
int level = 0;
|
||||
/* tricky bit -- each bit is '1' 75% of the time.
|
||||
* This works because we only use the lower MAX_LEVEL
|
||||
* bits, and MAX_LEVEL < 16 */
|
||||
long int bits = lfsr_random();
|
||||
bits |= bits >> 16;
|
||||
|
||||
while (++level < MAX_LEVEL)
|
||||
{
|
||||
|
@ -286,19 +288,23 @@ random_level (void)
|
|||
static void *
|
||||
alloc_node_for_level (cairo_skip_list_t *list, unsigned level)
|
||||
{
|
||||
if (list->freelists[level-1]) {
|
||||
skip_elt_t *elt = list->freelists[level-1];
|
||||
list->freelists[level-1] = elt->prev;
|
||||
int freelist_level = FREELIST_FOR_LEVEL (level);
|
||||
if (list->freelists[freelist_level]) {
|
||||
skip_elt_t *elt = list->freelists[freelist_level];
|
||||
list->freelists[freelist_level] = elt->prev;
|
||||
return ELT_DATA(elt);
|
||||
}
|
||||
return malloc (list->elt_size + (level-1) * sizeof (skip_elt_t *));
|
||||
return malloc (list->elt_size
|
||||
+ (FREELIST_MAX_LEVEL_FOR (level) - 1) * sizeof (skip_elt_t *));
|
||||
}
|
||||
|
||||
static void
|
||||
free_elt (cairo_skip_list_t *list, skip_elt_t *elt)
|
||||
{
|
||||
elt->prev = list->freelists[elt->prev_index];
|
||||
list->freelists[elt->prev_index] = elt;
|
||||
int level = elt->prev_index + 1;
|
||||
int freelist_level = FREELIST_FOR_LEVEL (level);
|
||||
elt->prev = list->freelists[freelist_level];
|
||||
list->freelists[freelist_level] = elt;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -349,6 +355,8 @@ _cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique)
|
|||
}
|
||||
|
||||
data_and_elt = alloc_node_for_level (list, level);
|
||||
if (data_and_elt == NULL)
|
||||
return NULL;
|
||||
memcpy (data_and_elt, data, list->data_size);
|
||||
elt = (skip_elt_t *) (data_and_elt + list->data_size);
|
||||
|
||||
|
|
|
@ -80,9 +80,9 @@ _cairo_spline_init (cairo_spline_t *spline,
|
|||
else
|
||||
_cairo_slope_init (&spline->final_slope, &spline->a, &spline->d);
|
||||
|
||||
spline->points = spline->points_embedded;
|
||||
spline->points_size = ARRAY_LENGTH (spline->points_embedded);
|
||||
spline->num_points = 0;
|
||||
spline->points_size = 0;
|
||||
spline->points = NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -90,11 +90,11 @@ _cairo_spline_init (cairo_spline_t *spline,
|
|||
void
|
||||
_cairo_spline_fini (cairo_spline_t *spline)
|
||||
{
|
||||
if (spline->points && spline->points != spline->points_embedded)
|
||||
if (spline->points != spline->points_embedded)
|
||||
free (spline->points);
|
||||
|
||||
spline->points = NULL;
|
||||
spline->points_size = 0;
|
||||
spline->points = spline->points_embedded;
|
||||
spline->points_size = ARRAY_LENGTH (spline->points_embedded);
|
||||
spline->num_points = 0;
|
||||
}
|
||||
|
||||
|
@ -104,17 +104,8 @@ _cairo_spline_grow (cairo_spline_t *spline)
|
|||
{
|
||||
cairo_point_t *new_points;
|
||||
int old_size = spline->points_size;
|
||||
int embedded_size = sizeof (spline->points_embedded) / sizeof (spline->points_embedded[0]);
|
||||
int new_size = 2 * MAX (old_size, 16);
|
||||
|
||||
/* we have a local buffer at spline->points_embedded. try to fulfill the request
|
||||
* from there. */
|
||||
if (old_size < embedded_size) {
|
||||
spline->points = spline->points_embedded;
|
||||
spline->points_size = embedded_size;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
assert (spline->num_points <= spline->points_size);
|
||||
|
||||
if (spline->points == spline->points_embedded) {
|
||||
|
@ -284,9 +275,8 @@ _cairo_spline_decompose (cairo_spline_t *spline, double tolerance)
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (spline->points_size) {
|
||||
_cairo_spline_fini (spline);
|
||||
}
|
||||
/* reset the spline, but keep the buffer */
|
||||
spline->num_points = 0;
|
||||
|
||||
status = _cairo_spline_decompose_into (spline, tolerance * tolerance, spline);
|
||||
if (status)
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-surface-fallback-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
|
@ -363,7 +365,8 @@ _clip_and_composite (cairo_clip_t *clip,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
|
||||
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
src = &solid_pattern.base;
|
||||
op = CAIRO_OPERATOR_DEST_OUT;
|
||||
}
|
||||
|
@ -418,7 +421,8 @@ _composite_trap_region (cairo_clip_t *clip,
|
|||
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
|
||||
|
||||
if (clip_surface && op == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
|
||||
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
src = &solid_pattern.base;
|
||||
op = CAIRO_OPERATOR_DEST_OUT;
|
||||
}
|
||||
|
@ -452,8 +456,11 @@ _composite_trap_region (cairo_clip_t *clip,
|
|||
extents->width, extents->height);
|
||||
|
||||
/* Restore the original clip if we modified it temporarily. */
|
||||
if (num_rects >1)
|
||||
_cairo_surface_set_clip (dst, clip);
|
||||
if (num_rects > 1) {
|
||||
cairo_status_t status2 = _cairo_surface_set_clip (dst, clip);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
}
|
||||
|
||||
if (clip_surface)
|
||||
_cairo_pattern_fini (&mask.base);
|
||||
|
@ -485,7 +492,8 @@ _composite_traps_draw_func (void *closure,
|
|||
if (dst_x != 0 || dst_y != 0)
|
||||
_cairo_traps_translate (info->traps, - dst_x, - dst_y);
|
||||
|
||||
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
|
||||
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
if (!src)
|
||||
src = &pattern.base;
|
||||
|
||||
|
@ -511,145 +519,156 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
|
|||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_status_t status;
|
||||
pixman_region16_t *trap_region = NULL;
|
||||
pixman_region16_t *clear_region = NULL;
|
||||
pixman_region16_t trap_region;
|
||||
pixman_region16_t clear_region;
|
||||
cairo_bool_t has_trap_region = FALSE;
|
||||
cairo_bool_t has_clear_region = FALSE;
|
||||
cairo_rectangle_int16_t extents;
|
||||
cairo_composite_traps_info_t traps_info;
|
||||
|
||||
if (traps->num_traps == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_surface_get_extents (dst, &extents);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
return status;
|
||||
|
||||
status = _cairo_traps_extract_region (traps, &trap_region);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (_cairo_operator_bounded_by_mask (op))
|
||||
{
|
||||
cairo_rectangle_int16_t trap_extents;
|
||||
if (trap_region) {
|
||||
status = _cairo_clip_intersect_to_region (clip, trap_region);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
_cairo_region_extents_rectangle (trap_region, &trap_extents);
|
||||
} else {
|
||||
cairo_box_t trap_box;
|
||||
_cairo_traps_extents (traps, &trap_box);
|
||||
_cairo_box_round_to_rectangle (&trap_box, &trap_extents);
|
||||
}
|
||||
|
||||
_cairo_rectangle_intersect (&extents, &trap_extents);
|
||||
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
|
||||
if (status)
|
||||
goto out;
|
||||
if (CAIRO_INT_STATUS_UNSUPPORTED == status) {
|
||||
has_trap_region = FALSE;
|
||||
} else if (status) {
|
||||
return status;
|
||||
} else {
|
||||
has_trap_region = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
|
||||
|
||||
if (trap_region && !clip_surface) {
|
||||
/* If we optimize drawing with an unbounded operator to
|
||||
* _cairo_surface_fill_rectangles() or to drawing with a
|
||||
* clip region, then we have an additional region to clear.
|
||||
*/
|
||||
clear_region = _cairo_region_create_from_rectangle (&extents);
|
||||
if (clear_region == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
if (_cairo_operator_bounded_by_mask (op)) {
|
||||
cairo_rectangle_int16_t trap_extents;
|
||||
|
||||
status = _cairo_clip_intersect_to_region (clip, clear_region);
|
||||
if (status)
|
||||
return status;
|
||||
if (has_trap_region) {
|
||||
status = _cairo_clip_intersect_to_region (clip, &trap_region);
|
||||
|
||||
_cairo_region_extents_rectangle (clear_region, &extents);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
_cairo_region_extents_rectangle (&trap_region, &trap_extents);
|
||||
} else {
|
||||
cairo_box_t trap_box;
|
||||
_cairo_traps_extents (traps, &trap_box);
|
||||
_cairo_box_round_to_rectangle (&trap_box, &trap_extents);
|
||||
}
|
||||
|
||||
if (!pixman_region_not_empty (clear_region)) {
|
||||
pixman_region_destroy (clear_region);
|
||||
clear_region = NULL;
|
||||
}
|
||||
} else {
|
||||
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
_cairo_rectangle_intersect (&extents, &trap_extents);
|
||||
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
|
||||
|
||||
if (status)
|
||||
goto out;
|
||||
} else {
|
||||
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
|
||||
|
||||
if (has_trap_region && !clip_surface) {
|
||||
/* If we optimize drawing with an unbounded operator to
|
||||
* _cairo_surface_fill_rectangles() or to drawing with a
|
||||
* clip region, then we have an additional region to clear.
|
||||
*/
|
||||
pixman_region_init_rect (&clear_region,
|
||||
extents.x, extents.y,
|
||||
extents.width, extents.height);
|
||||
|
||||
has_clear_region = TRUE;
|
||||
status = _cairo_clip_intersect_to_region (clip, &clear_region);
|
||||
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
_cairo_region_extents_rectangle (&clear_region, &extents);
|
||||
|
||||
if (PIXMAN_REGION_STATUS_SUCCESS !=
|
||||
pixman_region_subtract (&clear_region, &clear_region, &trap_region)) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!pixman_region_not_empty (&clear_region)) {
|
||||
pixman_region_fini (&clear_region);
|
||||
has_clear_region = FALSE;
|
||||
}
|
||||
} else {
|
||||
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
|
||||
}
|
||||
}
|
||||
|
||||
if (status)
|
||||
goto out;
|
||||
goto out;
|
||||
|
||||
if (trap_region)
|
||||
{
|
||||
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
|
||||
if (has_trap_region) {
|
||||
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
|
||||
|
||||
if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
|
||||
!clip_surface)
|
||||
{
|
||||
const cairo_color_t *color;
|
||||
if ((src->type == CAIRO_PATTERN_TYPE_SOLID ||
|
||||
op == CAIRO_OPERATOR_CLEAR) && !clip_surface) {
|
||||
const cairo_color_t *color;
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR)
|
||||
color = CAIRO_COLOR_TRANSPARENT;
|
||||
else
|
||||
color = &((cairo_solid_pattern_t *)src)->color;
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
color = CAIRO_COLOR_TRANSPARENT;
|
||||
} else {
|
||||
color = &((cairo_solid_pattern_t *)src)->color;
|
||||
}
|
||||
|
||||
/* Solid rectangles special case */
|
||||
status = _cairo_surface_fill_region (dst, op, color, trap_region);
|
||||
if (!status && clear_region)
|
||||
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
clear_region);
|
||||
/* Solid rectangles special case */
|
||||
status = _cairo_surface_fill_region (dst, op, color, &trap_region);
|
||||
|
||||
goto out;
|
||||
}
|
||||
if (!status && has_clear_region)
|
||||
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
&clear_region);
|
||||
|
||||
if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) ||
|
||||
!clip_surface)
|
||||
{
|
||||
/* For a simple rectangle, we can just use composite(), for more
|
||||
* rectangles, we have to set a clip region. The cost of rasterizing
|
||||
* trapezoids is pretty high for most backends currently, so it's
|
||||
* worthwhile even if a region is needed.
|
||||
*
|
||||
* If we have a clip surface, we set it as the mask; this only works
|
||||
* for bounded operators other than SOURCE; for unbounded operators,
|
||||
* clip and mask cannot be interchanged. For SOURCE, the operator
|
||||
* as implemented by the backends is different in it's handling
|
||||
* of the mask then what we want.
|
||||
*
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
|
||||
* more than rectangle and the destination doesn't support clip
|
||||
* regions. In that case, we fall through.
|
||||
*/
|
||||
status = _composite_trap_region (clip, src, op, dst,
|
||||
trap_region, &extents);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
{
|
||||
if (!status && clear_region)
|
||||
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
clear_region);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((_cairo_operator_bounded_by_mask (op) &&
|
||||
op != CAIRO_OPERATOR_SOURCE) || !clip_surface) {
|
||||
/* For a simple rectangle, we can just use composite(), for more
|
||||
* rectangles, we have to set a clip region. The cost of rasterizing
|
||||
* trapezoids is pretty high for most backends currently, so it's
|
||||
* worthwhile even if a region is needed.
|
||||
*
|
||||
* If we have a clip surface, we set it as the mask; this only works
|
||||
* for bounded operators other than SOURCE; for unbounded operators,
|
||||
* clip and mask cannot be interchanged. For SOURCE, the operator
|
||||
* as implemented by the backends is different in it's handling
|
||||
* of the mask then what we want.
|
||||
*
|
||||
* CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
|
||||
* more than rectangle and the destination doesn't support clip
|
||||
* regions. In that case, we fall through.
|
||||
*/
|
||||
status = _composite_trap_region (clip, src, op, dst,
|
||||
&trap_region, &extents);
|
||||
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
if (!status && has_clear_region)
|
||||
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
&clear_region);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traps_info.traps = traps;
|
||||
traps_info.antialias = antialias;
|
||||
|
||||
status = _clip_and_composite (clip, op, src,
|
||||
_composite_traps_draw_func, &traps_info,
|
||||
dst, &extents);
|
||||
_composite_traps_draw_func,
|
||||
&traps_info, dst, &extents);
|
||||
|
||||
out:
|
||||
if (trap_region)
|
||||
pixman_region_destroy (trap_region);
|
||||
if (clear_region)
|
||||
pixman_region_destroy (clear_region);
|
||||
out:
|
||||
if (has_trap_region)
|
||||
pixman_region_fini (&trap_region);
|
||||
if (has_clear_region)
|
||||
pixman_region_fini (&clear_region);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -690,16 +709,16 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_clip_and_composite_trapezoids (source,
|
||||
op,
|
||||
surface,
|
||||
&traps,
|
||||
surface->clip,
|
||||
CAIRO_ANTIALIAS_NONE);
|
||||
status = _clip_and_composite_trapezoids (source,
|
||||
op,
|
||||
surface,
|
||||
&traps,
|
||||
surface->clip,
|
||||
CAIRO_ANTIALIAS_NONE);
|
||||
|
||||
_cairo_traps_fini (&traps);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -785,9 +804,35 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
|
|||
{
|
||||
cairo_status_t status;
|
||||
cairo_traps_t traps;
|
||||
cairo_box_t box;
|
||||
cairo_rectangle_int16_t extents;
|
||||
|
||||
status = _cairo_surface_get_extents (surface, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (_cairo_operator_bounded_by_source (op)) {
|
||||
cairo_rectangle_int16_t source_extents;
|
||||
status = _cairo_pattern_get_extents (source, &source_extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_rectangle_intersect (&extents, &source_extents);
|
||||
}
|
||||
|
||||
status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
box.p1.x = _cairo_fixed_from_int (extents.x);
|
||||
box.p1.y = _cairo_fixed_from_int (extents.y);
|
||||
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
|
||||
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
|
||||
_cairo_traps_limit (&traps, &box);
|
||||
|
||||
status = _cairo_path_fixed_stroke_to_traps (path,
|
||||
stroke_style,
|
||||
ctm, ctm_inverse,
|
||||
|
@ -798,16 +843,16 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
_clip_and_composite_trapezoids (source,
|
||||
op,
|
||||
surface,
|
||||
&traps,
|
||||
surface->clip,
|
||||
antialias);
|
||||
status = _clip_and_composite_trapezoids (source,
|
||||
op,
|
||||
surface,
|
||||
&traps,
|
||||
surface->clip,
|
||||
antialias);
|
||||
|
||||
_cairo_traps_fini (&traps);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -821,9 +866,35 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
|
|||
{
|
||||
cairo_status_t status;
|
||||
cairo_traps_t traps;
|
||||
cairo_box_t box;
|
||||
cairo_rectangle_int16_t extents;
|
||||
|
||||
status = _cairo_surface_get_extents (surface, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (_cairo_operator_bounded_by_source (op)) {
|
||||
cairo_rectangle_int16_t source_extents;
|
||||
status = _cairo_pattern_get_extents (source, &source_extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_rectangle_intersect (&extents, &source_extents);
|
||||
}
|
||||
|
||||
status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
box.p1.x = _cairo_fixed_from_int (extents.x);
|
||||
box.p1.y = _cairo_fixed_from_int (extents.y);
|
||||
box.p2.x = _cairo_fixed_from_int (extents.x + extents.width);
|
||||
box.p2.y = _cairo_fixed_from_int (extents.y + extents.height);
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
|
||||
_cairo_traps_limit (&traps, &box);
|
||||
|
||||
status = _cairo_path_fixed_fill_to_traps (path,
|
||||
fill_rule,
|
||||
tolerance,
|
||||
|
@ -878,7 +949,8 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
|
|||
}
|
||||
}
|
||||
|
||||
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
|
||||
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
if (!src)
|
||||
src = &pattern.base;
|
||||
|
||||
|
@ -979,17 +1051,21 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
|
||||
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
|
||||
|
||||
_cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base,
|
||||
NULL,
|
||||
snapshot,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
image->width,
|
||||
image->height);
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base,
|
||||
NULL,
|
||||
snapshot,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
image->width,
|
||||
image->height);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
if (status) {
|
||||
cairo_surface_destroy (snapshot);
|
||||
return (cairo_surface_t *) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
_cairo_surface_release_source_image (surface,
|
||||
image, &image_extra);
|
||||
|
@ -1158,13 +1234,14 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
|
|||
traps = offset_traps;
|
||||
}
|
||||
|
||||
_cairo_surface_composite_trapezoids (op, pattern,
|
||||
&state.image->base,
|
||||
antialias,
|
||||
src_x, src_y,
|
||||
dst_x - state.image_rect.x,
|
||||
dst_y - state.image_rect.y,
|
||||
width, height, traps, num_traps);
|
||||
status = _cairo_surface_composite_trapezoids (op, pattern,
|
||||
&state.image->base,
|
||||
antialias,
|
||||
src_x, src_y,
|
||||
dst_x - state.image_rect.x,
|
||||
dst_y - state.image_rect.y,
|
||||
width, height,
|
||||
traps, num_traps);
|
||||
if (offset_traps)
|
||||
free (offset_traps);
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* 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):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_SURFACE_PRIVATE_H
|
||||
#define CAIRO_SURFACE_PRIVATE_H
|
||||
|
||||
#include "cairo.h"
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
struct _cairo_surface {
|
||||
const cairo_surface_backend_t *backend;
|
||||
|
||||
/* We allow surfaces to override the backend->type by shoving something
|
||||
* else into surface->type. This is for "wrapper" surfaces that want to
|
||||
* hide their internal type from the user-level API. */
|
||||
cairo_surface_type_t type;
|
||||
|
||||
cairo_content_t content;
|
||||
|
||||
unsigned int ref_count;
|
||||
cairo_status_t status;
|
||||
cairo_bool_t finished;
|
||||
cairo_user_data_array_t user_data;
|
||||
|
||||
cairo_matrix_t device_transform;
|
||||
cairo_matrix_t device_transform_inverse;
|
||||
|
||||
double x_fallback_resolution;
|
||||
double y_fallback_resolution;
|
||||
|
||||
cairo_clip_t *clip;
|
||||
|
||||
/*
|
||||
* Each time a clip region is modified, it gets the next value in this
|
||||
* sequence. This means that clip regions for this surface are uniquely
|
||||
* identified and updates to the clip can be readily identified
|
||||
*/
|
||||
unsigned int next_clip_serial;
|
||||
/*
|
||||
* The serial number of the current clip. This is set when
|
||||
* the surface clipping is set. The gstate can then cheaply
|
||||
* check whether the surface clipping is already correct before
|
||||
* performing a rendering operation.
|
||||
*
|
||||
* The special value '0' is reserved for the unclipped case.
|
||||
*/
|
||||
unsigned int current_clip_serial;
|
||||
|
||||
/* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */
|
||||
cairo_bool_t is_snapshot;
|
||||
|
||||
/*
|
||||
* Surface font options, falling back to backend's default options,
|
||||
* and set using _cairo_surface_set_font_options(), and propagated by
|
||||
* cairo_surface_create_similar().
|
||||
*/
|
||||
cairo_bool_t has_font_options;
|
||||
cairo_font_options_t font_options;
|
||||
};
|
||||
|
||||
#endif /* CAIRO_SURFACE_PRIVATE_H */
|
|
@ -35,9 +35,8 @@
|
|||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-surface-fallback-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
|
@ -81,7 +80,7 @@ DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_foun
|
|||
DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error);
|
||||
DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
|
||||
cairo_surface_t *destination,
|
||||
cairo_pattern_t *pattern_out);
|
||||
|
@ -180,10 +179,10 @@ _cairo_surface_init (cairo_surface_t *surface,
|
|||
const cairo_surface_backend_t *backend,
|
||||
cairo_content_t content)
|
||||
{
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
|
||||
surface->backend = backend;
|
||||
|
||||
surface->content = content;
|
||||
|
||||
surface->type = backend->type;
|
||||
|
||||
surface->ref_count = 1;
|
||||
|
@ -289,7 +288,8 @@ cairo_surface_create_similar (cairo_surface_t *other,
|
|||
|
||||
return _cairo_surface_create_similar_solid (other, content,
|
||||
width, height,
|
||||
CAIRO_COLOR_TRANSPARENT);
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
NULL);
|
||||
}
|
||||
slim_hidden_def (cairo_surface_create_similar);
|
||||
|
||||
|
@ -298,7 +298,8 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
|
|||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
const cairo_color_t *color)
|
||||
const cairo_color_t *color,
|
||||
cairo_pattern_t *pattern)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *surface;
|
||||
|
@ -311,19 +312,23 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
|
|||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
source = _cairo_pattern_create_solid (color);
|
||||
if (source->status) {
|
||||
cairo_surface_destroy (surface);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
if (pattern == NULL) {
|
||||
source = _cairo_pattern_create_solid (color, content);
|
||||
if (source->status) {
|
||||
cairo_surface_destroy (surface);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
} else
|
||||
source = pattern;
|
||||
|
||||
status = _cairo_surface_paint (surface,
|
||||
color == CAIRO_COLOR_TRANSPARENT ?
|
||||
CAIRO_OPERATOR_CLEAR :
|
||||
CAIRO_OPERATOR_SOURCE, source);
|
||||
|
||||
cairo_pattern_destroy (source);
|
||||
if (source != pattern)
|
||||
cairo_pattern_destroy (source);
|
||||
|
||||
if (status) {
|
||||
cairo_surface_destroy (surface);
|
||||
|
@ -374,7 +379,7 @@ slim_hidden_def (cairo_surface_reference);
|
|||
|
||||
/**
|
||||
* cairo_surface_destroy:
|
||||
* @surface: a #cairo_t
|
||||
* @surface: a #cairo_surface_t
|
||||
*
|
||||
* Decreases the reference count on @surface by one. If the result is
|
||||
* zero, then @surface and all associated resources are freed. See
|
||||
|
@ -401,6 +406,34 @@ cairo_surface_destroy (cairo_surface_t *surface)
|
|||
}
|
||||
slim_hidden_def(cairo_surface_destroy);
|
||||
|
||||
/**
|
||||
* cairo_surface_reset:
|
||||
* @surface: a #cairo_surface_t
|
||||
*
|
||||
* Resets the surface back to defaults such that it may be reused in lieu
|
||||
* of creating a new surface.
|
||||
**/
|
||||
cairo_status_t
|
||||
_cairo_surface_reset (cairo_surface_t *surface)
|
||||
{
|
||||
if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
assert (surface->ref_count == 1);
|
||||
|
||||
_cairo_user_data_array_fini (&surface->user_data);
|
||||
|
||||
if (surface->backend->reset != NULL) {
|
||||
cairo_status_t status = surface->backend->reset (surface);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_surface_init (surface, surface->backend, surface->content);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_get_reference_count:
|
||||
* @surface: a #cairo_surface_t
|
||||
|
@ -469,10 +502,8 @@ cairo_surface_finish (cairo_surface_t *surface)
|
|||
}
|
||||
|
||||
status = surface->backend->finish (surface);
|
||||
if (status) {
|
||||
if (status)
|
||||
_cairo_surface_set_error (surface, status);
|
||||
return;
|
||||
}
|
||||
|
||||
surface->finished = TRUE;
|
||||
}
|
||||
|
@ -570,13 +601,16 @@ void
|
|||
cairo_surface_get_font_options (cairo_surface_t *surface,
|
||||
cairo_font_options_t *options)
|
||||
{
|
||||
if (cairo_font_options_status (options))
|
||||
return;
|
||||
|
||||
if (!surface->has_font_options) {
|
||||
surface->has_font_options = TRUE;
|
||||
|
||||
_cairo_font_options_init_default (&surface->font_options);
|
||||
|
||||
if (!surface->finished && surface->backend->get_font_options) {
|
||||
surface->backend->get_font_options (surface, &surface->font_options);
|
||||
} else {
|
||||
_cairo_font_options_init_default (&surface->font_options);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1057,6 +1091,35 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
|
|||
return _cairo_surface_fallback_snapshot (surface);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_surface_is_similar
|
||||
* @surface_a: a #cairo_surface_t
|
||||
* @surface_b: a #cairo_surface_t
|
||||
* @content: a #cairo_content_t
|
||||
*
|
||||
* Find out whether the given surfaces share the same backend,
|
||||
* and if so, whether they can be considered similar.
|
||||
*
|
||||
* The definition of "similar" depends on the backend. In
|
||||
* general, it means that the surface is equivalent to one
|
||||
* that would have been generated by a call to cairo_surface_create_similar.
|
||||
*
|
||||
* Return value: TRUE if the surfaces are similar.
|
||||
**/
|
||||
cairo_bool_t
|
||||
_cairo_surface_is_similar (cairo_surface_t *surface_a,
|
||||
cairo_surface_t *surface_b,
|
||||
cairo_content_t content)
|
||||
{
|
||||
if (surface_a->backend != surface_b->backend)
|
||||
return FALSE;
|
||||
|
||||
if (surface_a->backend->is_similar != NULL)
|
||||
return surface_a->backend->is_similar (surface_a, surface_b, content);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_composite (cairo_operator_t op,
|
||||
cairo_pattern_t *src,
|
||||
|
@ -1170,6 +1233,7 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
|
|||
{
|
||||
int num_rects = pixman_region_num_rects (region);
|
||||
pixman_box16_t *boxes = pixman_region_rects (region);
|
||||
cairo_rectangle_int16_t stack_rects[CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_rectangle_int16_t)];
|
||||
cairo_rectangle_int16_t *rects;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
@ -1179,9 +1243,12 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
|
|||
if (!num_rects)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
rects = malloc (sizeof (pixman_rectangle_t) * num_rects);
|
||||
if (!rects)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
rects = stack_rects;
|
||||
if (num_rects > ARRAY_LENGTH (stack_rects)) {
|
||||
rects = malloc (sizeof (cairo_rectangle_int16_t) * num_rects);
|
||||
if (!rects)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_rects; i++) {
|
||||
rects[i].x = boxes[i].x1;
|
||||
|
@ -1193,7 +1260,8 @@ _cairo_surface_fill_region (cairo_surface_t *surface,
|
|||
status = _cairo_surface_fill_rectangles (surface, op,
|
||||
color, rects, num_rects);
|
||||
|
||||
free (rects);
|
||||
if (rects != stack_rects)
|
||||
free (rects);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -1255,7 +1323,9 @@ _cairo_surface_paint (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (surface->backend->paint) {
|
||||
status = surface->backend->paint (surface, op, &dev_source.base);
|
||||
|
@ -1283,20 +1353,26 @@ _cairo_surface_mask (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
_cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
if (status)
|
||||
goto FINISH;
|
||||
status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
|
||||
if (status)
|
||||
goto CLEANUP_SOURCE;
|
||||
|
||||
if (surface->backend->mask) {
|
||||
status = surface->backend->mask (surface, op, &dev_source.base, &dev_mask.base);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
goto FINISH;
|
||||
goto CLEANUP_MASK;
|
||||
}
|
||||
|
||||
status = _cairo_surface_fallback_mask (surface, op, &dev_source.base, &dev_mask.base);
|
||||
|
||||
FINISH:
|
||||
CLEANUP_MASK:
|
||||
_cairo_pattern_fini (&dev_mask.base);
|
||||
CLEANUP_SOURCE:
|
||||
_cairo_pattern_fini (&dev_source.base);
|
||||
FINISH:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -1321,7 +1397,9 @@ _cairo_surface_stroke (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (surface->backend->stroke) {
|
||||
status = surface->backend->stroke (surface, op, &dev_source.base,
|
||||
|
@ -1360,7 +1438,9 @@ _cairo_surface_fill (cairo_surface_t *surface,
|
|||
|
||||
assert (! surface->is_snapshot);
|
||||
|
||||
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (surface->backend->fill) {
|
||||
status = surface->backend->fill (surface, op, &dev_source.base,
|
||||
|
@ -1430,10 +1510,7 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
|
|||
traps, num_traps);
|
||||
}
|
||||
|
||||
/* _copy_page and _show_page are unique among _cairo_surface functions
|
||||
* in that they will actually return CAIRO_INT_STATUS_UNSUPPORTED
|
||||
* rather than performing any fallbacks. */
|
||||
cairo_int_status_t
|
||||
cairo_status_t
|
||||
_cairo_surface_copy_page (cairo_surface_t *surface)
|
||||
{
|
||||
assert (! surface->is_snapshot);
|
||||
|
@ -1444,16 +1521,14 @@ _cairo_surface_copy_page (cairo_surface_t *surface)
|
|||
if (surface->finished)
|
||||
return CAIRO_STATUS_SURFACE_FINISHED;
|
||||
|
||||
/* It's fine if some backends don't implement copy_page */
|
||||
if (surface->backend->copy_page == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return surface->backend->copy_page (surface);
|
||||
}
|
||||
|
||||
/* _show_page and _copy_page are unique among _cairo_surface functions
|
||||
* in that they will actually return CAIRO_INT_STATUS_UNSUPPORTED
|
||||
* rather than performing any fallbacks. */
|
||||
cairo_int_status_t
|
||||
cairo_status_t
|
||||
_cairo_surface_show_page (cairo_surface_t *surface)
|
||||
{
|
||||
assert (! surface->is_snapshot);
|
||||
|
@ -1464,8 +1539,9 @@ _cairo_surface_show_page (cairo_surface_t *surface)
|
|||
if (surface->finished)
|
||||
return CAIRO_STATUS_SURFACE_FINISHED;
|
||||
|
||||
/* It's fine if some backends don't implement show_page */
|
||||
if (surface->backend->show_page == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return surface->backend->show_page (surface);
|
||||
}
|
||||
|
@ -1700,9 +1776,9 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
|
|||
clip->path,
|
||||
clip->serial);
|
||||
|
||||
if (clip->region)
|
||||
if (clip->has_region)
|
||||
return _cairo_surface_set_clip_region (surface,
|
||||
clip->region,
|
||||
&clip->region,
|
||||
clip->serial);
|
||||
}
|
||||
|
||||
|
@ -1764,9 +1840,11 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
|
|||
if (!num_glyphs)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_surface_copy_pattern_for_destination (source,
|
||||
surface,
|
||||
&dev_source.base);
|
||||
status = _cairo_surface_copy_pattern_for_destination (source,
|
||||
surface,
|
||||
&dev_source.base);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
|
||||
|
||||
|
@ -1787,6 +1865,11 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
|
|||
font_options);
|
||||
cairo_font_options_destroy (font_options);
|
||||
}
|
||||
status = cairo_scaled_font_status (dev_scaled_font);
|
||||
if (status) {
|
||||
_cairo_pattern_fini (&dev_source.base);
|
||||
return status;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_LOCK (dev_scaled_font->mutex);
|
||||
|
||||
|
@ -1865,9 +1948,11 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
|
|||
{
|
||||
cairo_rectangle_int16_t dst_rectangle;
|
||||
cairo_rectangle_int16_t drawn_rectangle;
|
||||
pixman_region16_t *drawn_region;
|
||||
pixman_region16_t *clear_region;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_bool_t has_drawn_region = FALSE;
|
||||
cairo_bool_t has_clear_region = FALSE;
|
||||
pixman_region16_t drawn_region;
|
||||
pixman_region16_t clear_region;
|
||||
cairo_status_t status;
|
||||
|
||||
/* The area that was drawn is the area in the destination rectangle but not within
|
||||
* the source or the mask.
|
||||
|
@ -1880,34 +1965,38 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
|
|||
drawn_rectangle = dst_rectangle;
|
||||
|
||||
if (src_rectangle)
|
||||
_cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
|
||||
_cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
|
||||
|
||||
if (mask_rectangle)
|
||||
_cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
|
||||
_cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
|
||||
|
||||
/* Now compute the area that is in dst_rectangle but not in drawn_rectangle
|
||||
*/
|
||||
drawn_region = _cairo_region_create_from_rectangle (&drawn_rectangle);
|
||||
clear_region = _cairo_region_create_from_rectangle (&dst_rectangle);
|
||||
if (!drawn_region || !clear_region) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto CLEANUP_REGIONS;
|
||||
}
|
||||
pixman_region_init_rect (&drawn_region,
|
||||
drawn_rectangle.x, drawn_rectangle.y,
|
||||
drawn_rectangle.width, drawn_rectangle.height);
|
||||
pixman_region_init_rect (&clear_region,
|
||||
dst_rectangle.x, dst_rectangle.y,
|
||||
dst_rectangle.width, dst_rectangle.height);
|
||||
|
||||
if (pixman_region_subtract (clear_region, clear_region, drawn_region) != PIXMAN_REGION_STATUS_SUCCESS) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto CLEANUP_REGIONS;
|
||||
has_drawn_region = TRUE;
|
||||
has_clear_region = TRUE;
|
||||
|
||||
if (PIXMAN_REGION_STATUS_SUCCESS !=
|
||||
pixman_region_subtract (&clear_region, &clear_region, &drawn_region)) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto CLEANUP_REGIONS;
|
||||
}
|
||||
|
||||
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
clear_region);
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
&clear_region);
|
||||
|
||||
CLEANUP_REGIONS:
|
||||
if (drawn_region)
|
||||
pixman_region_destroy (drawn_region);
|
||||
if (clear_region)
|
||||
pixman_region_destroy (clear_region);
|
||||
CLEANUP_REGIONS:
|
||||
if (has_drawn_region)
|
||||
pixman_region_fini (&drawn_region);
|
||||
if (has_clear_region)
|
||||
pixman_region_fini (&clear_region);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -2068,16 +2157,19 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
|
|||
* Copies the given pattern, taking into account device scale and offsets
|
||||
* of the destination surface.
|
||||
*/
|
||||
void
|
||||
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_init_copy (pattern_out, pattern);
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_pattern_init_copy (pattern_out, pattern);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (_cairo_surface_has_device_transform (destination)) {
|
||||
cairo_matrix_t device_to_surface = destination->device_transform;
|
||||
cairo_status_t status;
|
||||
|
||||
status = cairo_matrix_invert (&device_to_surface);
|
||||
/* We only ever allow for scaling (under the implementation's
|
||||
|
@ -2087,6 +2179,8 @@ _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
|
|||
|
||||
_cairo_pattern_transform (pattern_out, &device_to_surface);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* LocalWords: rasterized
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2004 Red Hat, Inc
|
||||
* Copyright © 2005-2006 Emmanuel Pacaud <emmanuel.pacaud@free.fr>
|
||||
* Copyright © 2006 Red Hat, Inc
|
||||
*
|
||||
* 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>
|
||||
* Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_SVG_SURFACE_PRIVATE_H
|
||||
#define CAIRO_SVG_SURFACE_PRIVATE_H
|
||||
|
||||
#include "cairo-svg.h"
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
|
||||
typedef struct cairo_svg_document cairo_svg_document_t;
|
||||
|
||||
typedef struct cairo_svg_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_content_t content;
|
||||
|
||||
unsigned int id;
|
||||
|
||||
double width;
|
||||
double height;
|
||||
|
||||
cairo_svg_document_t *document;
|
||||
|
||||
cairo_output_stream_t *xml_node;
|
||||
cairo_array_t page_set;
|
||||
|
||||
unsigned int clip_level;
|
||||
unsigned int base_clip;
|
||||
cairo_bool_t is_base_clip_emitted;
|
||||
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
|
||||
cairo_bool_t force_fallbacks;
|
||||
} cairo_svg_surface_t;
|
||||
|
||||
#endif /* CAIRO_SVG_SURFACE_PRIVATE_H */
|
|
@ -40,15 +40,13 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-svg.h"
|
||||
#include "cairo-svg-test.h"
|
||||
#include "cairo-svg-surface-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-paginated-surface-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
typedef struct cairo_svg_document cairo_svg_document_t;
|
||||
typedef struct cairo_svg_surface cairo_svg_surface_t;
|
||||
typedef struct cairo_svg_page cairo_svg_page_t;
|
||||
|
||||
static const int invalid_pattern_id = -1;
|
||||
|
@ -59,7 +57,7 @@ static const cairo_svg_version_t _cairo_svg_versions[] =
|
|||
CAIRO_SVG_VERSION_1_2
|
||||
};
|
||||
|
||||
#define CAIRO_SVG_VERSION_LAST ((int)(sizeof (_cairo_svg_versions) / sizeof (_cairo_svg_versions[0])))
|
||||
#define CAIRO_SVG_VERSION_LAST ARRAY_LENGTH (_cairo_svg_versions)
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_svg_version_has_page_set_support (cairo_svg_version_t version)
|
||||
|
@ -81,7 +79,6 @@ static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST]
|
|||
|
||||
struct cairo_svg_page {
|
||||
unsigned int surface_id;
|
||||
unsigned int clip_id;
|
||||
unsigned int clip_level;
|
||||
cairo_output_stream_t *xml_node;
|
||||
};
|
||||
|
@ -115,27 +112,6 @@ struct cairo_svg_document {
|
|||
cairo_scaled_font_subsets_t *font_subsets;
|
||||
};
|
||||
|
||||
struct cairo_svg_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_content_t content;
|
||||
|
||||
unsigned int id;
|
||||
|
||||
double width;
|
||||
double height;
|
||||
|
||||
cairo_svg_document_t *document;
|
||||
|
||||
cairo_output_stream_t *xml_node;
|
||||
cairo_array_t page_set;
|
||||
|
||||
unsigned int clip_level;
|
||||
unsigned int base_clip;
|
||||
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
cairo_meta_surface_t *meta;
|
||||
|
@ -378,13 +354,7 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
|||
|
||||
surface->id = document->surface_id++;
|
||||
surface->base_clip = document->clip_id++;
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<clipPath id=\"clip%d\">\n"
|
||||
" <rect width=\"%f\" height=\"%f\"/>\n"
|
||||
"</clipPath>\n",
|
||||
surface->base_clip,
|
||||
width, height);
|
||||
surface->is_base_clip_emitted = FALSE;
|
||||
|
||||
surface->xml_node = _cairo_memory_stream_create ();
|
||||
_cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t));
|
||||
|
@ -398,6 +368,7 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
|||
}
|
||||
|
||||
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
|
||||
surface->force_fallbacks = FALSE;
|
||||
surface->content = content;
|
||||
|
||||
return _cairo_paginated_surface_create (&surface->base,
|
||||
|
@ -437,7 +408,6 @@ _cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
|
|||
cairo_svg_page_t page;
|
||||
|
||||
page.surface_id = surface->id;
|
||||
page.clip_id = surface->base_clip;
|
||||
page.clip_level = surface->clip_level;
|
||||
page.xml_node = surface->xml_node;
|
||||
|
||||
|
@ -447,7 +417,8 @@ _cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
|
|||
for (i = 0; i < page.clip_level; i++)
|
||||
_cairo_output_stream_printf (page.xml_node, "</g>\n");
|
||||
|
||||
_cairo_array_append (&surface->page_set, &page);
|
||||
if (_cairo_array_append (&surface->page_set, &page) != CAIRO_STATUS_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
|
||||
}
|
||||
|
@ -706,38 +677,27 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
|
||||
{
|
||||
_cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
|
||||
_cairo_svg_document_emit_font_subset,
|
||||
document);
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
|
||||
_cairo_svg_document_emit_font_subset,
|
||||
document);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_scaled_font_subsets_destroy (document->font_subsets);
|
||||
document->font_subsets = NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_bool_t cairo_svg_force_fallbacks = FALSE;
|
||||
|
||||
/**
|
||||
* _cairo_svg_test_force_fallbacks
|
||||
*
|
||||
* Force the SVG surface backend to use image fallbacks for every
|
||||
* operation.
|
||||
*
|
||||
* <note>
|
||||
* This function is <emphasis>only</emphasis> intended for internal
|
||||
* testing use within the cairo distribution. It is not installed in
|
||||
* any public header file.
|
||||
* </note>
|
||||
**/
|
||||
void
|
||||
_cairo_svg_test_force_fallbacks (void)
|
||||
{
|
||||
cairo_svg_force_fallbacks = TRUE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
__cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface,
|
||||
_cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
|
@ -758,7 +718,7 @@ _cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
if (__cairo_svg_surface_operation_supported (surface, op, pattern))
|
||||
if (_cairo_svg_surface_operation_supported (surface, op, pattern))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
else
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
@ -776,7 +736,7 @@ _cairo_svg_surface_create_similar (void *abstract_src,
|
|||
static cairo_status_t
|
||||
_cairo_svg_surface_finish (void *abstract_surface)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_status_t status, status2;
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_svg_page_t *page;
|
||||
|
@ -787,11 +747,15 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
else
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_output_stream_destroy (surface->xml_node);
|
||||
status2 = _cairo_output_stream_destroy (surface->xml_node);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
|
||||
for (i = 0; i < surface->page_set.num_elements; i++) {
|
||||
page = _cairo_array_index (&surface->page_set, i);
|
||||
_cairo_output_stream_destroy (page->xml_node);
|
||||
status2 = _cairo_output_stream_destroy (page->xml_node);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
}
|
||||
_cairo_array_fini (&surface->page_set);
|
||||
|
||||
|
@ -941,7 +905,9 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *outp
|
|||
return status;
|
||||
|
||||
p2u = pattern->base.matrix;
|
||||
cairo_matrix_invert (&p2u);
|
||||
status = cairo_matrix_invert (&p2u);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (pattern_id != invalid_pattern_id) {
|
||||
_cairo_output_stream_printf (output,
|
||||
|
@ -978,12 +944,14 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *outp
|
|||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
||||
cairo_meta_surface_t *surface)
|
||||
cairo_meta_surface_t *surface,
|
||||
int *id)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *paginated_surface;
|
||||
cairo_surface_t *svg_surface;
|
||||
cairo_svg_surface_t *svg_surface;
|
||||
cairo_meta_snapshot_t new_snapshot;
|
||||
cairo_array_t *page_set;
|
||||
|
||||
|
@ -991,7 +959,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
cairo_meta_surface_t *meta;
|
||||
cairo_meta_snapshot_t *snapshot;
|
||||
unsigned int num_elements;
|
||||
unsigned int i, id;
|
||||
unsigned int i;
|
||||
|
||||
/* search in already emitted meta snapshots */
|
||||
num_elements = document->meta_snapshots.num_elements;
|
||||
|
@ -1000,7 +968,8 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
meta = snapshot->meta;
|
||||
if (meta->commands.num_elements == surface->commands.num_elements &&
|
||||
_cairo_array_index (&meta->commands, 0) == _cairo_array_index (&surface->commands, 0)) {
|
||||
return snapshot->id;
|
||||
*id = snapshot->id;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1009,16 +978,41 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
meta->content,
|
||||
meta->width_pixels,
|
||||
meta->height_pixels);
|
||||
svg_surface = _cairo_paginated_surface_get_target (paginated_surface);
|
||||
svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface);
|
||||
cairo_surface_set_fallback_resolution (paginated_surface,
|
||||
document->owner->x_fallback_resolution,
|
||||
document->owner->y_fallback_resolution);
|
||||
_cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
|
||||
_cairo_surface_show_page (paginated_surface);
|
||||
|
||||
status = _cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
|
||||
if (status) {
|
||||
cairo_surface_destroy (&meta->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_surface_show_page (paginated_surface);
|
||||
if (status) {
|
||||
cairo_surface_destroy (&meta->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
new_snapshot.meta = meta;
|
||||
new_snapshot.id = ((cairo_svg_surface_t *) svg_surface)->id;
|
||||
_cairo_array_append (&document->meta_snapshots, &new_snapshot);
|
||||
new_snapshot.id = svg_surface->id;
|
||||
status = _cairo_array_append (&document->meta_snapshots, &new_snapshot);
|
||||
if (status) {
|
||||
cairo_surface_destroy (&meta->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!svg_surface->is_base_clip_emitted) {
|
||||
svg_surface->is_base_clip_emitted = TRUE;
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<clipPath id=\"clip%d\">\n"
|
||||
" <rect width=\"%f\" height=\"%f\"/>\n"
|
||||
"</clipPath>\n",
|
||||
svg_surface->base_clip,
|
||||
svg_surface->width,
|
||||
svg_surface->height);
|
||||
}
|
||||
|
||||
if (meta->content == CAIRO_CONTENT_ALPHA) {
|
||||
_cairo_svg_surface_emit_alpha_filter (document);
|
||||
|
@ -1026,21 +1020,21 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\" "
|
||||
"filter=\"url(#alpha)\">\n",
|
||||
((cairo_svg_surface_t *) svg_surface)->id,
|
||||
((cairo_svg_surface_t *) svg_surface)->base_clip);
|
||||
svg_surface->id,
|
||||
svg_surface->base_clip);
|
||||
} else {
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
((cairo_svg_surface_t *) svg_surface)->id,
|
||||
((cairo_svg_surface_t *) svg_surface)->base_clip);
|
||||
svg_surface->id,
|
||||
svg_surface->base_clip);
|
||||
}
|
||||
|
||||
contents = ((cairo_svg_surface_t *) svg_surface)->xml_node;
|
||||
page_set = &((cairo_svg_surface_t *) svg_surface)->page_set;
|
||||
contents = svg_surface->xml_node;
|
||||
page_set = &svg_surface->page_set;
|
||||
|
||||
if (_cairo_memory_stream_length (contents) > 0)
|
||||
_cairo_svg_surface_store_page ((cairo_svg_surface_t *) svg_surface);
|
||||
_cairo_svg_surface_store_page (svg_surface);
|
||||
|
||||
if (page_set->num_elements > 0) {
|
||||
cairo_svg_page_t *page;
|
||||
|
@ -1051,7 +1045,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
|
||||
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
|
||||
|
||||
id = new_snapshot.id;
|
||||
*id = new_snapshot.id;
|
||||
|
||||
cairo_surface_destroy (paginated_surface);
|
||||
|
||||
|
@ -1062,7 +1056,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
|
||||
/* cairo_surface_destroy (svg_surface); */
|
||||
|
||||
return id;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -1075,14 +1069,19 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
|
|||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_meta_surface_t *meta_surface;
|
||||
cairo_matrix_t p2u;
|
||||
cairo_status_t status;
|
||||
int id;
|
||||
|
||||
p2u = pattern->base.matrix;
|
||||
status = cairo_matrix_invert (&p2u);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
meta_surface = (cairo_meta_surface_t *) pattern->surface;
|
||||
|
||||
id = _cairo_svg_surface_emit_meta_surface (document, meta_surface);
|
||||
|
||||
p2u = pattern->base.matrix;
|
||||
cairo_matrix_invert (&p2u);
|
||||
status = _cairo_svg_surface_emit_meta_surface (document, meta_surface, &id);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (pattern_id != invalid_pattern_id) {
|
||||
_cairo_output_stream_printf (output,
|
||||
|
@ -1152,7 +1151,7 @@ _cairo_svg_surface_emit_operator (cairo_output_stream_t *output,
|
|||
_cairo_output_stream_printf (output, "comp-op: %s; ", op_str[op]);
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
|
||||
cairo_solid_pattern_t *pattern,
|
||||
cairo_output_stream_t *style,
|
||||
|
@ -1166,9 +1165,11 @@ _cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
|
|||
pattern->color.green * 100.0,
|
||||
pattern->color.blue * 100.0,
|
||||
pattern->color.alpha);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
cairo_output_stream_t *style,
|
||||
|
@ -1185,6 +1186,8 @@ _cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface,
|
|||
"%s: url(#pattern%d);",
|
||||
is_stroke ? "color" : "fill",
|
||||
pattern_id);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1366,7 +1369,7 @@ _cairo_svg_surface_emit_pattern_extend (cairo_output_stream_t *output,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
|
||||
cairo_linear_pattern_t *pattern,
|
||||
cairo_output_stream_t *style,
|
||||
|
@ -1375,6 +1378,12 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
|
|||
cairo_svg_document_t *document = surface->document;
|
||||
double x0, y0, x1, y1;
|
||||
cairo_matrix_t p2u;
|
||||
cairo_status_t status;
|
||||
|
||||
p2u = pattern->base.base.matrix;
|
||||
status = cairo_matrix_invert (&p2u);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
x0 = _cairo_fixed_to_double (pattern->gradient.p1.x);
|
||||
y0 = _cairo_fixed_to_double (pattern->gradient.p1.y);
|
||||
|
@ -1389,8 +1398,6 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
|
|||
x0, y0, x1, y1);
|
||||
|
||||
_cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base),
|
||||
p2u = pattern->base.base.matrix;
|
||||
cairo_matrix_invert (&p2u);
|
||||
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
|
||||
|
||||
_cairo_svg_surface_emit_pattern_stops (document->xml_node_defs ,&pattern->base, 0.0, FALSE, FALSE);
|
||||
|
@ -1404,9 +1411,11 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
|
|||
document->linear_pattern_id);
|
||||
|
||||
document->linear_pattern_id++;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
||||
cairo_radial_pattern_t *pattern,
|
||||
cairo_output_stream_t *style,
|
||||
|
@ -1418,6 +1427,7 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
|||
double x0, y0, x1, y1, r0, r1;
|
||||
double fx, fy;
|
||||
cairo_bool_t reverse_stops;
|
||||
cairo_status_t status;
|
||||
pixman_circle_t *c0, *c1;
|
||||
|
||||
extend = pattern->base.base.extend;
|
||||
|
@ -1440,7 +1450,9 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
|||
r1 = _cairo_fixed_to_double (c1->radius);
|
||||
|
||||
p2u = pattern->base.base.matrix;
|
||||
cairo_matrix_invert (&p2u);
|
||||
status = cairo_matrix_invert (&p2u);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (pattern->gradient.c1.radius == pattern->gradient.c2.radius) {
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
|
@ -1571,29 +1583,28 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
|||
document->radial_pattern_id);
|
||||
|
||||
document->radial_pattern_id++;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern,
|
||||
cairo_output_stream_t *output, cairo_bool_t is_stroke)
|
||||
{
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
_cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke);
|
||||
break;
|
||||
return _cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
_cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke);
|
||||
break;
|
||||
return _cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
_cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
|
||||
break;
|
||||
return _cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
_cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
|
||||
break;
|
||||
return _cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
|
||||
}
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
@ -1611,7 +1622,7 @@ _cairo_svg_surface_fill (void *abstract_surface,
|
|||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, source));
|
||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node,
|
||||
"<path style=\"stroke: none; "
|
||||
|
@ -1686,6 +1697,7 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
cairo_pattern_t *source)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
|
@ -1698,7 +1710,7 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
|||
* possible only because there is nothing between the fallback
|
||||
* images and the paper, nor is anything painted above. */
|
||||
/*
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, source));
|
||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||
*/
|
||||
|
||||
/* Emulation of clear and source operators, when no clipping region
|
||||
|
@ -1711,8 +1723,12 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
|||
* and an optimiszation in meta surface. */
|
||||
if (surface->clip_level == 0 &&
|
||||
(op == CAIRO_OPERATOR_CLEAR ||
|
||||
op == CAIRO_OPERATOR_SOURCE)) {
|
||||
_cairo_output_stream_destroy (surface->xml_node);
|
||||
op == CAIRO_OPERATOR_SOURCE))
|
||||
{
|
||||
status = _cairo_output_stream_destroy (surface->xml_node);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
surface->xml_node = _cairo_memory_stream_create ();
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
|
@ -1740,6 +1756,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
cairo_pattern_t *source,
|
||||
cairo_pattern_t *mask)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_output_stream_t *mask_stream;
|
||||
|
@ -1748,7 +1765,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, source));
|
||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||
|
||||
_cairo_svg_surface_emit_alpha_filter (document);
|
||||
|
||||
|
@ -1765,7 +1782,10 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
" </g>\n"
|
||||
"</mask>\n");
|
||||
_cairo_memory_stream_copy (mask_stream, document->xml_node_defs);
|
||||
_cairo_output_stream_destroy (mask_stream);
|
||||
|
||||
status = _cairo_output_stream_destroy (mask_stream);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d);\"",
|
||||
document->mask_id);
|
||||
|
@ -1795,7 +1815,7 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
|||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, source));
|
||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||
|
||||
switch (stroke_style->line_cap) {
|
||||
case CAIRO_LINE_CAP_BUTT:
|
||||
|
@ -1877,13 +1897,13 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_path_fixed_t path;
|
||||
cairo_status_t status;
|
||||
unsigned int font_id, subset_id, subset_glyph_index;
|
||||
cairo_scaled_font_subsets_glyph_t subset_glyph;
|
||||
int i;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, pattern);
|
||||
|
||||
assert (__cairo_svg_surface_operation_supported (surface, op, pattern));
|
||||
assert (_cairo_svg_surface_operation_supported (surface, op, pattern));
|
||||
|
||||
if (num_glyphs <= 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
@ -1901,7 +1921,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
for (i = 0; i < num_glyphs; i++) {
|
||||
status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets,
|
||||
scaled_font, glyphs[i].index,
|
||||
&font_id, &subset_id, &subset_glyph_index);
|
||||
&subset_glyph);
|
||||
if (status) {
|
||||
glyphs += i;
|
||||
num_glyphs -= i;
|
||||
|
@ -1911,7 +1931,8 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
_cairo_output_stream_printf (surface->xml_node,
|
||||
" <use xlink:href=\"#glyph%d-%d\" "
|
||||
"x=\"%f\" y=\"%f\"/>\n",
|
||||
font_id, subset_glyph_index,
|
||||
subset_glyph.font_id,
|
||||
subset_glyph.subset_glyph_index,
|
||||
glyphs[i].x, glyphs[i].y);
|
||||
}
|
||||
|
||||
|
@ -2034,7 +2055,7 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream,
|
|||
}
|
||||
|
||||
/* The use of defs for font glyphs imposes no per-subset limit. */
|
||||
document->font_subsets = _cairo_scaled_font_subsets_create (0, INT_MAX);
|
||||
document->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
|
||||
if (document->font_subsets == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
free (document);
|
||||
|
@ -2092,7 +2113,7 @@ _cairo_svg_document_destroy (cairo_svg_document_t *document)
|
|||
static cairo_status_t
|
||||
_cairo_svg_document_finish (cairo_svg_document_t *document)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_status_t status, status2;
|
||||
cairo_output_stream_t *output = document->output_stream;
|
||||
cairo_meta_snapshot_t *snapshot;
|
||||
cairo_svg_surface_t *surface;
|
||||
|
@ -2112,7 +2133,10 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
document->width, document->height,
|
||||
_cairo_svg_internal_version_strings [document->svg_version]);
|
||||
|
||||
_cairo_svg_document_emit_font_subsets (document);
|
||||
status = _cairo_svg_document_emit_font_subsets (document);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (_cairo_memory_stream_length (document->xml_node_glyphs) > 0 ||
|
||||
_cairo_memory_stream_length (document->xml_node_defs) > 0) {
|
||||
_cairo_output_stream_printf (output, "<defs>\n");
|
||||
|
@ -2136,10 +2160,8 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
page = _cairo_array_index (&surface->page_set, i);
|
||||
_cairo_output_stream_printf (output, "<page>\n");
|
||||
_cairo_output_stream_printf (output,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
page->surface_id,
|
||||
page->clip_id);
|
||||
"<g id=\"surface%d\">\n",
|
||||
page->surface_id);
|
||||
_cairo_memory_stream_copy (page->xml_node, output);
|
||||
_cairo_output_stream_printf (output, "</g>\n</page>\n");
|
||||
}
|
||||
|
@ -2147,20 +2169,23 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
} else if (surface->page_set.num_elements > 0) {
|
||||
page = _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
|
||||
_cairo_output_stream_printf (output,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
page->surface_id,
|
||||
page->clip_id);
|
||||
"<g id=\"surface%d\">\n",
|
||||
page->surface_id);
|
||||
_cairo_memory_stream_copy (page->xml_node, output);
|
||||
_cairo_output_stream_printf (output, "</g>\n");
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (output, "</svg>\n");
|
||||
|
||||
_cairo_output_stream_destroy (document->xml_node_glyphs);
|
||||
_cairo_output_stream_destroy (document->xml_node_defs);
|
||||
status = _cairo_output_stream_destroy (document->xml_node_glyphs);
|
||||
|
||||
status = _cairo_output_stream_destroy (output);
|
||||
status2 = _cairo_output_stream_destroy (document->xml_node_defs);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
|
||||
status2 = _cairo_output_stream_destroy (output);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
|
||||
for (i = 0; i < document->meta_snapshots.num_elements; i++) {
|
||||
snapshot = _cairo_array_index (&document->meta_snapshots, i);
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
static cairo_status_t
|
||||
_cairo_traps_grow (cairo_traps_t *traps);
|
||||
|
||||
static cairo_status_t
|
||||
static void
|
||||
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
cairo_line_t *left, cairo_line_t *right);
|
||||
|
||||
|
@ -57,10 +57,21 @@ _cairo_traps_init (cairo_traps_t *traps)
|
|||
|
||||
traps->num_traps = 0;
|
||||
|
||||
traps->traps_size = 0;
|
||||
traps->traps = NULL;
|
||||
traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
|
||||
traps->traps = traps->traps_embedded;
|
||||
traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
|
||||
traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
|
||||
|
||||
traps->has_limits = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_traps_limit (cairo_traps_t *traps,
|
||||
cairo_box_t *limits)
|
||||
{
|
||||
traps->has_limits = TRUE;
|
||||
|
||||
traps->limits = *limits;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -87,45 +98,104 @@ cairo_status_t
|
|||
_cairo_traps_init_box (cairo_traps_t *traps,
|
||||
cairo_box_t *box)
|
||||
{
|
||||
_cairo_traps_init (traps);
|
||||
_cairo_traps_init (traps);
|
||||
|
||||
assert (traps->traps_size >= 1);
|
||||
|
||||
traps->num_traps = 1;
|
||||
|
||||
traps->traps[0].top = box->p1.y;
|
||||
traps->traps[0].bottom = box->p2.y;
|
||||
traps->traps[0].left.p1 = box->p1;
|
||||
traps->traps[0].left.p2.x = box->p1.x;
|
||||
traps->traps[0].left.p2.y = box->p2.y;
|
||||
traps->traps[0].right.p1.x = box->p2.x;
|
||||
traps->traps[0].right.p1.y = box->p1.y;
|
||||
traps->traps[0].right.p2 = box->p2;
|
||||
|
||||
traps->extents = *box;
|
||||
|
||||
traps->status = _cairo_traps_grow (traps);
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
|
||||
traps->num_traps = 1;
|
||||
|
||||
traps->traps[0].top = box->p1.y;
|
||||
traps->traps[0].bottom = box->p2.y;
|
||||
traps->traps[0].left.p1 = box->p1;
|
||||
traps->traps[0].left.p2.x = box->p1.x;
|
||||
traps->traps[0].left.p2.y = box->p2.y;
|
||||
traps->traps[0].right.p1.x = box->p2.x;
|
||||
traps->traps[0].right.p1.y = box->p1.y;
|
||||
traps->traps[0].right.p2 = box->p2;
|
||||
|
||||
traps->extents = *box;
|
||||
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_status_t
|
||||
_cairo_traps_status (cairo_traps_t *traps)
|
||||
{
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
cairo_line_t *left, cairo_line_t *right)
|
||||
{
|
||||
cairo_trapezoid_t *trap;
|
||||
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
return;
|
||||
|
||||
if (top == bottom) {
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
/* Note: With the goofy trapezoid specification, (where an
|
||||
* arbitrary two points on the lines can specified for the left
|
||||
* and right edges), these limit checks would not work in
|
||||
* general. For example, one can imagine a trapezoid entirely
|
||||
* within the limits, but with two points used to specify the left
|
||||
* edge entirely to the right of the limits. Fortunately, for our
|
||||
* purposes, cairo will never generate such a crazy
|
||||
* trapezoid. Instead, cairo always uses for its points the
|
||||
* extreme positions of the edge that are visible on at least some
|
||||
* trapezoid. With this constraint, it's impossible for both
|
||||
* points to be outside the limits while the relevant edge is
|
||||
* entirely inside the limits.
|
||||
*/
|
||||
if (traps->has_limits) {
|
||||
/* Trivially reject if trapezoid is entirely to the right or
|
||||
* to the left of the limits. */
|
||||
if (left->p1.x >= traps->limits.p2.x &&
|
||||
left->p2.x >= traps->limits.p2.x)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (right->p1.x <= traps->limits.p1.x &&
|
||||
right->p2.x <= traps->limits.p1.x)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, clip the trapezoid to the limits. We only clip
|
||||
* where an edge is entirely outside the limits. If we wanted
|
||||
* to be more clever, we could handle cases where a trapezoid
|
||||
* edge intersects the edge of the limits, but that would
|
||||
* require slicing this trapezoid into multiple trapezoids,
|
||||
* and I'm not sure the effort would be worth it. */
|
||||
if (top < traps->limits.p1.y)
|
||||
top = traps->limits.p1.y;
|
||||
|
||||
if (bottom > traps->limits.p2.y)
|
||||
bottom = traps->limits.p2.y;
|
||||
|
||||
if (left->p1.x < traps->limits.p1.x &&
|
||||
left->p2.x < traps->limits.p1.x)
|
||||
{
|
||||
left->p1.x = traps->limits.p1.x;
|
||||
left->p2.x = traps->limits.p1.x;
|
||||
}
|
||||
|
||||
if (right->p1.x > traps->limits.p2.x &&
|
||||
right->p2.x > traps->limits.p2.x)
|
||||
{
|
||||
right->p1.x = traps->limits.p2.x;
|
||||
right->p2.x = traps->limits.p2.x;
|
||||
}
|
||||
}
|
||||
|
||||
if (top >= bottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (traps->num_traps >= traps->traps_size) {
|
||||
traps->status = _cairo_traps_grow (traps);
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
return;
|
||||
}
|
||||
|
||||
trap = &traps->traps[traps->num_traps];
|
||||
|
@ -157,11 +227,9 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
|
|||
traps->extents.p2.x = right->p2.x;
|
||||
|
||||
traps->num_traps++;
|
||||
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
|
||||
cairo_point_t left_p1, cairo_point_t left_p2,
|
||||
cairo_point_t right_p1, cairo_point_t right_p2)
|
||||
|
@ -170,7 +238,7 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair
|
|||
cairo_line_t right;
|
||||
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
return;
|
||||
|
||||
left.p1 = left_p1;
|
||||
left.p2 = left_p2;
|
||||
|
@ -178,7 +246,7 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair
|
|||
right.p1 = right_p1;
|
||||
right.p2 = right_p2;
|
||||
|
||||
return _cairo_traps_add_trap (traps, top, bottom, &left, &right);
|
||||
_cairo_traps_add_trap (traps, top, bottom, &left, &right);
|
||||
}
|
||||
|
||||
/* make room for at least one more trap */
|
||||
|
@ -186,19 +254,7 @@ static cairo_status_t
|
|||
_cairo_traps_grow (cairo_traps_t *traps)
|
||||
{
|
||||
cairo_trapezoid_t *new_traps;
|
||||
int old_size = traps->traps_size;
|
||||
int embedded_size = sizeof (traps->traps_embedded) / sizeof (traps->traps_embedded[0]);
|
||||
int new_size = 2 * MAX (old_size, 16);
|
||||
|
||||
/* we have a local buffer at traps->traps_embedded. try to fulfill the request
|
||||
* from there. */
|
||||
if (old_size < embedded_size) {
|
||||
traps->traps = traps->traps_embedded;
|
||||
traps->traps_size = embedded_size;
|
||||
return traps->status;
|
||||
}
|
||||
|
||||
assert (traps->num_traps <= traps->traps_size);
|
||||
int new_size = 2 * MAX (traps->traps_size, 16);
|
||||
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
|
@ -206,7 +262,7 @@ _cairo_traps_grow (cairo_traps_t *traps)
|
|||
if (traps->traps == traps->traps_embedded) {
|
||||
new_traps = malloc (new_size * sizeof (cairo_trapezoid_t));
|
||||
if (new_traps)
|
||||
memcpy (new_traps, traps->traps, old_size * sizeof (cairo_trapezoid_t));
|
||||
memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
|
||||
} else {
|
||||
new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t));
|
||||
}
|
||||
|
@ -219,7 +275,7 @@ _cairo_traps_grow (cairo_traps_t *traps)
|
|||
traps->traps = new_traps;
|
||||
traps->traps_size = new_size;
|
||||
|
||||
return traps->status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -534,21 +590,18 @@ _cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
|
|||
* Determines if a set of trapezoids are exactly representable as a
|
||||
* pixman region, and if so creates such a region.
|
||||
*
|
||||
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
|
||||
* Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
|
||||
* or %CAIRO_STATUS_NO_MEMORY
|
||||
**/
|
||||
cairo_status_t
|
||||
_cairo_traps_extract_region (cairo_traps_t *traps,
|
||||
pixman_region16_t **region)
|
||||
cairo_int_status_t
|
||||
_cairo_traps_extract_region (cairo_traps_t *traps,
|
||||
pixman_region16_t *region)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Bail early if we have lots of traps, until we fix the code
|
||||
* below to not use Union()
|
||||
*/
|
||||
if (traps->num_traps > 200) {
|
||||
*region = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
#define NUM_STATIC_BOXES 16
|
||||
pixman_box16_t static_boxes[NUM_STATIC_BOXES];
|
||||
pixman_box16_t *boxes;
|
||||
int i, box_count;
|
||||
pixman_region_status_t status;
|
||||
|
||||
for (i = 0; i < traps->num_traps; i++)
|
||||
if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
|
||||
|
@ -557,30 +610,49 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
|
|||
&& _cairo_fixed_is_integer(traps->traps[i].bottom)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].left.p1.x)
|
||||
&& _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) {
|
||||
*region = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
*region = pixman_region_create ();
|
||||
if (traps->num_traps <= NUM_STATIC_BOXES) {
|
||||
boxes = static_boxes;
|
||||
} else {
|
||||
/*boxes = _cairo_malloc2 (traps->num_traps, sizeof(pixman_box16_t));*/
|
||||
boxes = malloc (traps->num_traps * sizeof(pixman_box16_t));
|
||||
|
||||
if (boxes == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
box_count = 0;
|
||||
|
||||
for (i = 0; i < traps->num_traps; i++) {
|
||||
int x = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
|
||||
int y = _cairo_fixed_integer_part(traps->traps[i].top);
|
||||
int width = _cairo_fixed_integer_part(traps->traps[i].right.p1.x) - x;
|
||||
int height = _cairo_fixed_integer_part(traps->traps[i].bottom) - y;
|
||||
int x1 = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
|
||||
int y1 = _cairo_fixed_integer_part(traps->traps[i].top);
|
||||
int x2 = _cairo_fixed_integer_part(traps->traps[i].right.p1.x);
|
||||
int y2 = _cairo_fixed_integer_part(traps->traps[i].bottom);
|
||||
|
||||
/* XXX: Sometimes we get degenerate trapezoids from the tesellator,
|
||||
* if we call pixman_region_union_rect(), it bizarrly fails on such
|
||||
* an empty rectangle, so skip them.
|
||||
/* XXX: Sometimes we get degenerate trapezoids from the tesellator;
|
||||
* skip these.
|
||||
*/
|
||||
if (width == 0 || height == 0)
|
||||
continue;
|
||||
if (x1 == x2 || y1 == y2)
|
||||
continue;
|
||||
|
||||
if (pixman_region_union_rect (*region, *region,
|
||||
x, y, width, height) != PIXMAN_REGION_STATUS_SUCCESS) {
|
||||
pixman_region_destroy (*region);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
boxes[box_count].x1 = (short) x1;
|
||||
boxes[box_count].y1 = (short) y1;
|
||||
boxes[box_count].x2 = (short) x2;
|
||||
boxes[box_count].y2 = (short) y2;
|
||||
|
||||
box_count++;
|
||||
}
|
||||
|
||||
status = pixman_region_init_rects (region, boxes, box_count);
|
||||
|
||||
if (boxes != static_boxes)
|
||||
free (boxes);
|
||||
|
||||
if (status != PIXMAN_REGION_STATUS_SUCCESS) {
|
||||
pixman_region_fini (region);
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
* Adrian Johnson <ajohnson@redneon.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
#include "cairo-truetype-subset-private.h"
|
||||
|
||||
|
@ -75,8 +75,6 @@ typedef struct _cairo_truetype_font {
|
|||
static int
|
||||
cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph);
|
||||
|
||||
#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
|
||||
|
||||
#define SFNT_VERSION 0x00010000
|
||||
#define SFNT_STRING_MAX_LENGTH 65535
|
||||
|
||||
|
@ -84,7 +82,7 @@ static cairo_status_t
|
|||
_cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
||||
cairo_truetype_font_t **font_return)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
|
||||
cairo_status_t status;
|
||||
cairo_truetype_font_t *font;
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
tt_head_t head;
|
||||
|
@ -131,16 +129,22 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
TT_TAG_name, 0, NULL,
|
||||
&size) != CAIRO_STATUS_SUCCESS)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
name = malloc(size);
|
||||
if (name == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
backend->load_truetype_table (scaled_font_subset->scaled_font,
|
||||
TT_TAG_name, 0, (unsigned char *) name,
|
||||
&size);
|
||||
|
||||
status = backend->load_truetype_table (scaled_font_subset->scaled_font,
|
||||
TT_TAG_name, 0, (unsigned char *) name,
|
||||
&size);
|
||||
if (status)
|
||||
goto fail0;
|
||||
|
||||
font = malloc (sizeof (cairo_truetype_font_t));
|
||||
if (font == NULL)
|
||||
if (font == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail0;
|
||||
}
|
||||
|
||||
font->backend = backend;
|
||||
font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs);
|
||||
|
@ -149,15 +153,21 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
font->last_offset = 0;
|
||||
font->last_boundary = 0;
|
||||
_cairo_array_init (&font->output, sizeof (char));
|
||||
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
|
||||
status = _cairo_array_grow_by (&font->output, 4096);
|
||||
if (status)
|
||||
goto fail1;
|
||||
|
||||
font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t));
|
||||
if (font->glyphs == NULL)
|
||||
goto fail2;
|
||||
if (font->glyphs == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int));
|
||||
if (font->parent_to_subset == NULL)
|
||||
goto fail3;
|
||||
if (font->parent_to_subset == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
font->base.num_glyphs = 0;
|
||||
font->base.x_min = (int16_t) be16_to_cpu (head.x_min);
|
||||
|
@ -198,8 +208,11 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
|
||||
if (font->base.base_font == NULL) {
|
||||
font->base.base_font = malloc (30);
|
||||
if (font->base.base_font == NULL)
|
||||
goto fail4;
|
||||
if (font->base.base_font == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
snprintf(font->base.base_font, 30, "CairoFont-%u-%u",
|
||||
scaled_font_subset->font_id,
|
||||
scaled_font_subset->subset_id);
|
||||
|
@ -213,12 +226,15 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
font->base.base_font[i] = '\0';
|
||||
|
||||
font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int));
|
||||
if (font->base.widths == NULL)
|
||||
goto fail5;
|
||||
if (font->base.widths == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
_cairo_array_init (&font->string_offsets, sizeof (unsigned long));
|
||||
if (_cairo_array_grow_by (&font->string_offsets, 10) != CAIRO_STATUS_SUCCESS)
|
||||
goto fail6;
|
||||
status = _cairo_array_grow_by (&font->string_offsets, 10);
|
||||
if (status)
|
||||
goto fail5;
|
||||
|
||||
font->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
@ -226,21 +242,22 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail6:
|
||||
free (font->base.widths);
|
||||
fail5:
|
||||
free (font->base.base_font);
|
||||
_cairo_array_fini (&font->string_offsets);
|
||||
free (font->base.widths);
|
||||
fail4:
|
||||
free (font->parent_to_subset);
|
||||
free (font->base.base_font);
|
||||
fail3:
|
||||
free (font->glyphs);
|
||||
free (font->parent_to_subset);
|
||||
fail2:
|
||||
_cairo_array_fini (&font->output);
|
||||
free (font->glyphs);
|
||||
fail1:
|
||||
_cairo_array_fini (&font->output);
|
||||
free (font);
|
||||
fail0:
|
||||
if (name)
|
||||
free (name);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -322,19 +339,27 @@ cairo_truetype_font_align_output (cairo_truetype_font_t *font)
|
|||
return aligned;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_check_boundary (cairo_truetype_font_t *font,
|
||||
unsigned long boundary)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (boundary - font->last_offset > SFNT_STRING_MAX_LENGTH)
|
||||
{
|
||||
_cairo_array_append(&font->string_offsets, &font->last_boundary);
|
||||
status = _cairo_array_append (&font->string_offsets,
|
||||
&font->last_boundary);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
font->last_offset = font->last_boundary;
|
||||
}
|
||||
font->last_boundary = boundary;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
|
||||
unsigned long tag)
|
||||
{
|
||||
|
@ -360,12 +385,12 @@ cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
|
|||
cairo_truetype_font_write_be16 (font, 4); /* searchrange */
|
||||
cairo_truetype_font_write_be16 (font, 1); /* entry selector */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* rangeshift */
|
||||
cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 2); /* end count[0] */
|
||||
cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 1); /* end count[0] */
|
||||
cairo_truetype_font_write_be16 (font, 0xffff); /* end count[1] */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* reserved */
|
||||
cairo_truetype_font_write_be16 (font, 0xf000); /* startCode[0] */
|
||||
cairo_truetype_font_write_be16 (font, 0xffff); /* startCode[1] */
|
||||
cairo_truetype_font_write_be16 (font, 0x1001); /* delta[0] */
|
||||
cairo_truetype_font_write_be16 (font, 0x1000); /* delta[0] */
|
||||
cairo_truetype_font_write_be16 (font, 1); /* delta[1] */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[0] */
|
||||
cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[1] */
|
||||
|
@ -373,17 +398,17 @@ cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
|
|||
/* Output a format 6 encoding table. */
|
||||
|
||||
cairo_truetype_font_write_be16 (font, 6);
|
||||
cairo_truetype_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1));
|
||||
cairo_truetype_font_write_be16 (font, 10 + 2 * font->base.num_glyphs);
|
||||
cairo_truetype_font_write_be16 (font, 0);
|
||||
cairo_truetype_font_write_be16 (font, 0); /* First character */
|
||||
cairo_truetype_font_write_be16 (font, font->base.num_glyphs);
|
||||
for (i = 0; i < font->base.num_glyphs; i++)
|
||||
cairo_truetype_font_write_be16 (font, i + 1);
|
||||
cairo_truetype_font_write_be16 (font, i);
|
||||
|
||||
return font->status;
|
||||
}
|
||||
|
||||
static int
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font,
|
||||
unsigned long tag)
|
||||
{
|
||||
|
@ -397,11 +422,17 @@ cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font,
|
|||
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
return font->status;
|
||||
}
|
||||
|
||||
status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
|
||||
/* XXX: Need to check status here. */
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
tag, 0, buffer, &size);
|
||||
return 0;
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
tag, 0, buffer, &size);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -438,11 +469,10 @@ cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
|
|||
} while (has_more_components);
|
||||
}
|
||||
|
||||
static int
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
|
||||
unsigned long tag)
|
||||
{
|
||||
cairo_status_t status;
|
||||
unsigned long start_offset, index, size, next;
|
||||
tt_head_t header;
|
||||
unsigned long begin, end;
|
||||
|
@ -455,8 +485,11 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
|
|||
} u;
|
||||
|
||||
size = sizeof (tt_head_t);
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_head, 0, (unsigned char*) &header, &size);
|
||||
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_head, 0,
|
||||
(unsigned char*) &header, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
if (be16_to_cpu (header.index_to_loc_format) == 0)
|
||||
size = sizeof (int16_t) * (font->num_glyphs_in_face + 1);
|
||||
|
@ -468,6 +501,7 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
|
|||
font->status = CAIRO_STATUS_NO_MEMORY;
|
||||
return font->status;
|
||||
}
|
||||
|
||||
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_loca, 0, u.bytes, &size) != CAIRO_STATUS_SUCCESS) {
|
||||
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
@ -489,15 +523,23 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
|
|||
size = end - begin;
|
||||
|
||||
next = cairo_truetype_font_align_output (font);
|
||||
cairo_truetype_font_check_boundary (font, next);
|
||||
|
||||
font->status = cairo_truetype_font_check_boundary (font, next);
|
||||
if (font->status)
|
||||
break;
|
||||
|
||||
font->glyphs[i].location = next - start_offset;
|
||||
|
||||
status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
|
||||
if (status)
|
||||
font->status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
|
||||
if (font->status)
|
||||
break;
|
||||
|
||||
if (size != 0) {
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_glyf, begin, buffer, &size);
|
||||
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_glyf, begin, buffer, &size);
|
||||
if (font->status)
|
||||
break;
|
||||
|
||||
cairo_truetype_font_remap_composite_glyph (font, buffer);
|
||||
}
|
||||
}
|
||||
|
@ -510,7 +552,7 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
|
|||
return font->status;
|
||||
}
|
||||
|
||||
static int
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
|
||||
unsigned long tag)
|
||||
{
|
||||
|
@ -518,36 +560,52 @@ cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
|
|||
unsigned long size;
|
||||
|
||||
size = 0;
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
tag, 0, NULL, &size);
|
||||
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
tag, 0, NULL, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
font->checksum_index = _cairo_array_num_elements (&font->output) + 8;
|
||||
font->status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
|
||||
font->backend->load_truetype_table( font->scaled_font_subset->scaled_font,
|
||||
tag, 0, buffer, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
font->status = font->backend->load_truetype_table( font->scaled_font_subset->scaled_font,
|
||||
tag, 0, buffer, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
/* set checkSumAdjustment to 0 for table checksum calcualtion */
|
||||
*(uint32_t *)(buffer + 8) = 0;
|
||||
|
||||
return font->status;
|
||||
}
|
||||
|
||||
static int cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag)
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag)
|
||||
{
|
||||
tt_hhea_t *hhea;
|
||||
unsigned long size;
|
||||
|
||||
size = sizeof (tt_hhea_t);
|
||||
font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &hhea);
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
tag, 0, (unsigned char *) hhea, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
tag, 0, (unsigned char *) hhea, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs));
|
||||
|
||||
return font->status;
|
||||
}
|
||||
|
||||
static int
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
|
||||
unsigned long tag)
|
||||
{
|
||||
cairo_status_t status;
|
||||
unsigned long size;
|
||||
unsigned long long_entry_size;
|
||||
unsigned long short_entry_size;
|
||||
|
@ -557,15 +615,22 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
|
|||
int num_hmetrics;
|
||||
|
||||
size = sizeof (tt_hhea_t);
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_hhea, 0, (unsigned char*) &hhea, &size);
|
||||
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_hhea, 0,
|
||||
(unsigned char*) &hhea, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
num_hmetrics = be16_to_cpu(hhea.num_hmetrics);
|
||||
|
||||
for (i = 0; i < font->base.num_glyphs; i++) {
|
||||
long_entry_size = 2 * sizeof (int16_t);
|
||||
short_entry_size = sizeof (int16_t);
|
||||
status = cairo_truetype_font_allocate_write_buffer (font, long_entry_size,
|
||||
(unsigned char **) &p);
|
||||
font->status = cairo_truetype_font_allocate_write_buffer (font, long_entry_size,
|
||||
(unsigned char **) &p);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
if (font->glyphs[i].parent_index < num_hmetrics) {
|
||||
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_hmtx,
|
||||
|
@ -584,11 +649,13 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
|
|||
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
return font->status;
|
||||
}
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_hmtx,
|
||||
num_hmetrics * long_entry_size +
|
||||
(font->glyphs[i].parent_index - num_hmetrics) * short_entry_size,
|
||||
(unsigned char *) (p + 1), &short_entry_size);
|
||||
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_hmtx,
|
||||
num_hmetrics * long_entry_size +
|
||||
(font->glyphs[i].parent_index - num_hmetrics) * short_entry_size,
|
||||
(unsigned char *) (p + 1), &short_entry_size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
}
|
||||
font->base.widths[i] = be16_to_cpu (p[0]);
|
||||
}
|
||||
|
@ -596,7 +663,7 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
|
|||
return font->status;
|
||||
}
|
||||
|
||||
static int
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
|
||||
unsigned long tag)
|
||||
{
|
||||
|
@ -605,8 +672,11 @@ cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
|
|||
unsigned long size;
|
||||
|
||||
size = sizeof(tt_head_t);
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_head, 0, (unsigned char*) &header, &size);
|
||||
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
TT_TAG_head, 0,
|
||||
(unsigned char*) &header, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
if (be16_to_cpu (header.index_to_loc_format) == 0)
|
||||
{
|
||||
|
@ -620,7 +690,7 @@ cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
|
|||
return font->status;
|
||||
}
|
||||
|
||||
static int
|
||||
static cairo_status_t
|
||||
cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
|
||||
unsigned long tag)
|
||||
{
|
||||
|
@ -629,39 +699,15 @@ cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
|
|||
|
||||
size = sizeof (tt_maxp_t);
|
||||
font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp);
|
||||
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
tag, 0, (unsigned char *) maxp, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
tag, 0, (unsigned char *) maxp, &size);
|
||||
if (font->status)
|
||||
return font->status;
|
||||
|
||||
maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs);
|
||||
return font->status;
|
||||
}
|
||||
|
||||
static int
|
||||
cairo_truetype_font_write_post_table (cairo_truetype_font_t *font,
|
||||
unsigned long tag)
|
||||
{
|
||||
char buf[10];
|
||||
int n;
|
||||
unsigned i;
|
||||
|
||||
cairo_truetype_font_write_be32 (font, 0x00020000);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be16 (font, 0);
|
||||
cairo_truetype_font_write_be16 (font, 1);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be32 (font, 0);
|
||||
cairo_truetype_font_write_be16 (font, font->base.num_glyphs);
|
||||
cairo_truetype_font_write_be16 (font, 0);
|
||||
for (i = 1; i < font->base.num_glyphs; i++)
|
||||
cairo_truetype_font_write_be16 (font, i + 257);
|
||||
|
||||
for (i = 1; i < font->base.num_glyphs; i++) {
|
||||
n = snprintf(buf + 1, 9, "g%d", i - 1);
|
||||
buf[0] = n;
|
||||
cairo_truetype_font_write (font, buf, n + 1);
|
||||
}
|
||||
|
||||
return font->status;
|
||||
}
|
||||
|
@ -669,7 +715,7 @@ cairo_truetype_font_write_post_table (cairo_truetype_font_t *font,
|
|||
typedef struct table table_t;
|
||||
struct table {
|
||||
unsigned long tag;
|
||||
int (*write) (cairo_truetype_font_t *font, unsigned long tag);
|
||||
cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag);
|
||||
int pos; /* position in the font directory */
|
||||
};
|
||||
|
||||
|
@ -692,8 +738,7 @@ static const table_t truetype_tables[] = {
|
|||
{ TT_TAG_loca, cairo_truetype_font_write_loca_table, 7 },
|
||||
{ TT_TAG_maxp, cairo_truetype_font_write_maxp_table, 8 },
|
||||
{ TT_TAG_name, cairo_truetype_font_write_generic_table, 9 },
|
||||
{ TT_TAG_post, cairo_truetype_font_write_post_table, 10 },
|
||||
{ TT_TAG_prep, cairo_truetype_font_write_generic_table, 11 },
|
||||
{ TT_TAG_prep, cairo_truetype_font_write_generic_table, 10 },
|
||||
};
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -776,6 +821,7 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font,
|
|||
const unsigned long **string_offsets,
|
||||
unsigned long *num_strings)
|
||||
{
|
||||
cairo_status_t status;
|
||||
unsigned long start, end, next;
|
||||
uint32_t checksum, *checksum_location;
|
||||
unsigned int i;
|
||||
|
@ -795,7 +841,12 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font,
|
|||
next = cairo_truetype_font_align_output (font);
|
||||
cairo_truetype_font_update_entry (font, truetype_tables[i].pos, truetype_tables[i].tag,
|
||||
start, end);
|
||||
cairo_truetype_font_check_boundary (font, next);
|
||||
status = cairo_truetype_font_check_boundary (font, next);
|
||||
if (status) {
|
||||
font->status = status;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
start = next;
|
||||
}
|
||||
|
||||
|
@ -832,7 +883,7 @@ cairo_status_t
|
|||
_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
||||
cairo_scaled_font_subset_t *font_subset)
|
||||
{
|
||||
cairo_truetype_font_t *font;
|
||||
cairo_truetype_font_t *font = NULL;
|
||||
cairo_status_t status;
|
||||
const char *data = NULL; /* squelch bogus compiler warning */
|
||||
unsigned long length = 0; /* squelch bogus compiler warning */
|
||||
|
@ -845,10 +896,6 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
/* Add the notdef glyph. This is required at glyph index 0
|
||||
* in the subsetted font. */
|
||||
cairo_truetype_font_use_glyph (font, 0);
|
||||
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
parent_glyph = font->scaled_font_subset->glyphs[i];
|
||||
cairo_truetype_font_use_glyph (font, parent_glyph);
|
||||
|
@ -860,19 +907,22 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
|||
goto fail1;
|
||||
|
||||
truetype_subset->base_font = strdup (font->base.base_font);
|
||||
if (truetype_subset->base_font == NULL)
|
||||
if (truetype_subset->base_font == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
/* The widths array returned must contain only widths for
|
||||
* the glyphs in font_subset. The notdef glyph at index 0
|
||||
* and any subglyphs appended after font_subset->num_glyphs
|
||||
* are omitted. */
|
||||
/* The widths array returned must contain only widths for the
|
||||
* glyphs in font_subset. Any subglyphs appended after
|
||||
* font_subset->num_glyphs are omitted. */
|
||||
truetype_subset->widths = calloc (sizeof (double),
|
||||
font->scaled_font_subset->num_glyphs);
|
||||
if (truetype_subset->widths == NULL)
|
||||
if (truetype_subset->widths == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail2;
|
||||
}
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
|
||||
truetype_subset->widths[i] = (double)font->base.widths[i + 1]/font->base.units_per_em;
|
||||
truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em;
|
||||
|
||||
truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em;
|
||||
truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em;
|
||||
|
@ -882,19 +932,28 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
|
|||
truetype_subset->descent = (double)font->base.descent/font->base.units_per_em;
|
||||
|
||||
truetype_subset->data = malloc (length);
|
||||
if (truetype_subset->data == NULL)
|
||||
if (truetype_subset->data == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
memcpy (truetype_subset->data, data, length);
|
||||
truetype_subset->data_length = length;
|
||||
|
||||
offsets_length = num_strings * sizeof (unsigned long);
|
||||
truetype_subset->string_offsets = malloc (offsets_length);
|
||||
if (truetype_subset->string_offsets == NULL)
|
||||
goto fail4;
|
||||
if (num_strings) {
|
||||
offsets_length = num_strings * sizeof (unsigned long);
|
||||
truetype_subset->string_offsets = malloc (offsets_length);
|
||||
if (truetype_subset->string_offsets == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
|
||||
truetype_subset->num_string_offsets = num_strings;
|
||||
memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
|
||||
truetype_subset->num_string_offsets = num_strings;
|
||||
} else {
|
||||
truetype_subset->string_offsets = NULL;
|
||||
truetype_subset->num_string_offsets = 0;
|
||||
}
|
||||
|
||||
cairo_truetype_font_destroy (font);
|
||||
|
||||
|
|
|
@ -39,6 +39,11 @@
|
|||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
|
||||
typedef enum {
|
||||
CAIRO_CHARSTRING_TYPE1,
|
||||
CAIRO_CHARSTRING_TYPE2,
|
||||
} cairo_charstring_type_t;
|
||||
|
||||
typedef struct _cairo_type1_font {
|
||||
int *widths;
|
||||
|
||||
|
@ -90,7 +95,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
|
||||
font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
|
||||
|
||||
cairo_matrix_init_scale (&font_matrix, 1000, 1000);
|
||||
cairo_matrix_init_scale (&font_matrix, 1000, -1000);
|
||||
cairo_matrix_init_identity (&ctm);
|
||||
|
||||
_cairo_font_options_init_default (&font_options);
|
||||
|
@ -101,7 +106,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
|
|||
&font_matrix,
|
||||
&ctm,
|
||||
&font_options);
|
||||
if (font->type1_scaled_font == NULL)
|
||||
if (font->type1_scaled_font->status)
|
||||
goto fail;
|
||||
|
||||
_cairo_array_init (&font->contents, sizeof (unsigned char));
|
||||
|
@ -156,7 +161,9 @@ charstring_encode_command (cairo_array_t *data, int command)
|
|||
* bytes that will be used is 5.
|
||||
*/
|
||||
static void
|
||||
charstring_encode_integer (cairo_array_t *data, int i)
|
||||
charstring_encode_integer (cairo_array_t *data,
|
||||
int i,
|
||||
cairo_charstring_type_t type)
|
||||
{
|
||||
cairo_status_t status;
|
||||
int orig_size;
|
||||
|
@ -174,11 +181,19 @@ charstring_encode_integer (cairo_array_t *data, int i)
|
|||
*p++ = (i >> 8)+ 251;
|
||||
*p++ = i & 0xff;
|
||||
} else {
|
||||
*p++ = 0xff;
|
||||
*p++ = i >> 24;
|
||||
*p++ = (i >> 16) & 0xff;
|
||||
*p++ = (i >> 8) & 0xff;
|
||||
*p++ = i & 0xff;
|
||||
if (type == CAIRO_CHARSTRING_TYPE1) {
|
||||
*p++ = 0xff;
|
||||
*p++ = i >> 24;
|
||||
*p++ = (i >> 16) & 0xff;
|
||||
*p++ = (i >> 8) & 0xff;
|
||||
*p++ = i & 0xff;
|
||||
} else {
|
||||
*p++ = 0xff;
|
||||
*p++ = (i >> 8) & 0xff;
|
||||
*p++ = i & 0xff;
|
||||
*p++ = 0;
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure the array doesn't grow, which allows this function to
|
||||
|
@ -193,6 +208,7 @@ charstring_encode_integer (cairo_array_t *data, int i)
|
|||
typedef struct _ps_path_info {
|
||||
cairo_array_t *data;
|
||||
int current_x, current_y;
|
||||
cairo_charstring_type_t type;
|
||||
} t1_path_info_t;
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -209,8 +225,8 @@ _charstring_move_to (void *closure,
|
|||
|
||||
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
|
||||
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
|
||||
charstring_encode_integer (path_info->data, dx);
|
||||
charstring_encode_integer (path_info->data, dy);
|
||||
charstring_encode_integer (path_info->data, dx, path_info->type);
|
||||
charstring_encode_integer (path_info->data, dy, path_info->type);
|
||||
path_info->current_x += dx;
|
||||
path_info->current_y += dy;
|
||||
|
||||
|
@ -233,8 +249,8 @@ _charstring_line_to (void *closure,
|
|||
|
||||
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
|
||||
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
|
||||
charstring_encode_integer (path_info->data, dx);
|
||||
charstring_encode_integer (path_info->data, dy);
|
||||
charstring_encode_integer (path_info->data, dx, path_info->type);
|
||||
charstring_encode_integer (path_info->data, dy, path_info->type);
|
||||
path_info->current_x += dx;
|
||||
path_info->current_y += dy;
|
||||
|
||||
|
@ -263,12 +279,12 @@ _charstring_curve_to (void *closure,
|
|||
dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1;
|
||||
dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2;
|
||||
dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2;
|
||||
charstring_encode_integer (path_info->data, dx1);
|
||||
charstring_encode_integer (path_info->data, dy1);
|
||||
charstring_encode_integer (path_info->data, dx2);
|
||||
charstring_encode_integer (path_info->data, dy2);
|
||||
charstring_encode_integer (path_info->data, dx3);
|
||||
charstring_encode_integer (path_info->data, dy3);
|
||||
charstring_encode_integer (path_info->data, dx1, path_info->type);
|
||||
charstring_encode_integer (path_info->data, dy1, path_info->type);
|
||||
charstring_encode_integer (path_info->data, dx2, path_info->type);
|
||||
charstring_encode_integer (path_info->data, dy2, path_info->type);
|
||||
charstring_encode_integer (path_info->data, dx3, path_info->type);
|
||||
charstring_encode_integer (path_info->data, dy3, path_info->type);
|
||||
path_info->current_x += dx1 + dx2 + dx3;
|
||||
path_info->current_y += dy1 + dy2 + dy3;
|
||||
charstring_encode_command (path_info->data, CHARSTRING_rcurveto);
|
||||
|
@ -282,6 +298,9 @@ _charstring_close_path (void *closure)
|
|||
cairo_status_t status;
|
||||
t1_path_info_t *path_info = (t1_path_info_t *) closure;
|
||||
|
||||
if (path_info->type == CAIRO_CHARSTRING_TYPE2)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_array_grow_by (path_info->data, 2);
|
||||
if (status)
|
||||
return status;
|
||||
|
@ -309,7 +328,7 @@ charstring_encrypt (cairo_array_t *data)
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
create_notdef_charstring (cairo_array_t *data)
|
||||
create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
|
@ -320,13 +339,15 @@ create_notdef_charstring (cairo_array_t *data)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
charstring_encode_integer (data, 0);
|
||||
charstring_encode_integer (data, 0);
|
||||
if (type == CAIRO_CHARSTRING_TYPE1) {
|
||||
charstring_encode_integer (data, 0, type);
|
||||
charstring_encode_integer (data, 0, type);
|
||||
|
||||
/* The width and height is arbitrary. */
|
||||
charstring_encode_integer (data, 500);
|
||||
charstring_encode_integer (data, 500);
|
||||
charstring_encode_command (data, CHARSTRING_sbw);
|
||||
/* The width and height is arbitrary. */
|
||||
charstring_encode_integer (data, 500, type);
|
||||
charstring_encode_integer (data, 500, type);
|
||||
charstring_encode_command (data, CHARSTRING_sbw);
|
||||
}
|
||||
|
||||
charstring_encode_command (data, CHARSTRING_endchar);
|
||||
|
||||
|
@ -334,10 +355,11 @@ create_notdef_charstring (cairo_array_t *data)
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
cairo_type1_font_create_charstring (cairo_type1_font_t *font,
|
||||
int subset_index,
|
||||
int glyph_index,
|
||||
cairo_array_t *data)
|
||||
cairo_type1_font_create_charstring (cairo_type1_font_t *font,
|
||||
int subset_index,
|
||||
int glyph_index,
|
||||
cairo_charstring_type_t type,
|
||||
cairo_array_t *data)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
|
@ -369,21 +391,29 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
|
|||
if (metrics->y_bearing + metrics->height > font->y_max)
|
||||
font->y_max = metrics->y_bearing + metrics->height;
|
||||
}
|
||||
font->widths[subset_index] = metrics->width;
|
||||
font->widths[subset_index] = metrics->x_advance;
|
||||
|
||||
status = _cairo_array_grow_by (data, 30);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing);
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing);
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.width);
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.height);
|
||||
charstring_encode_command (data, CHARSTRING_sbw);
|
||||
if (type == CAIRO_CHARSTRING_TYPE1) {
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing, type);
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing, type);
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.height, type);
|
||||
charstring_encode_command (data, CHARSTRING_sbw);
|
||||
|
||||
path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
|
||||
path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
|
||||
} else {
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
|
||||
|
||||
path_info.current_x = 0;
|
||||
path_info.current_y = 0;
|
||||
}
|
||||
path_info.data = data;
|
||||
path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
|
||||
path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
|
||||
path_info.type = type;
|
||||
status = _cairo_path_fixed_interpret (scaled_glyph->path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_charstring_move_to,
|
||||
|
@ -421,7 +451,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
|
|||
"2 index /CharStrings %d dict dup begin\n",
|
||||
font->scaled_font_subset->num_glyphs + 1);
|
||||
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
_cairo_array_truncate (&data, 0);
|
||||
/* four "random" bytes required by encryption algorithm */
|
||||
status = _cairo_array_append_multiple (&data, zeros, 4);
|
||||
|
@ -429,6 +459,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
|
|||
goto fail;
|
||||
status = cairo_type1_font_create_charstring (font, i,
|
||||
font->scaled_font_subset->glyphs[i],
|
||||
CAIRO_CHARSTRING_TYPE1,
|
||||
&data);
|
||||
if (status)
|
||||
goto fail;
|
||||
|
@ -448,7 +479,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
|
|||
status = _cairo_array_append_multiple (&data, zeros, 4);
|
||||
if (status)
|
||||
goto fail;
|
||||
status = create_notdef_charstring (&data);
|
||||
status = create_notdef_charstring (&data, CAIRO_CHARSTRING_TYPE1);
|
||||
if (status)
|
||||
goto fail;
|
||||
charstring_encrypt (&data);
|
||||
|
@ -468,28 +499,18 @@ static void
|
|||
cairo_type1_font_write_header (cairo_type1_font_t *font,
|
||||
const char *name)
|
||||
{
|
||||
cairo_matrix_t matrix;
|
||||
unsigned int i;
|
||||
const char spaces[50] = " ";
|
||||
|
||||
matrix = font->type1_scaled_font->scale;
|
||||
matrix.xy = -matrix.xy;
|
||||
matrix.yy = -matrix.yy;
|
||||
cairo_matrix_invert (&matrix);
|
||||
|
||||
_cairo_output_stream_printf (font->output,
|
||||
"%%!FontType1-1.1 %s 1.0\n"
|
||||
"11 dict begin\n"
|
||||
"/FontName /%s def\n"
|
||||
"/PaintType 0 def\n"
|
||||
"/FontType 1 def\n"
|
||||
"/FontMatrix [%f %f %f %f 0 0] readonly def\n",
|
||||
"/FontMatrix [0.001 0 0 0.001 0 0] readonly def\n",
|
||||
name,
|
||||
name,
|
||||
matrix.xx,
|
||||
matrix.yx,
|
||||
matrix.xy,
|
||||
matrix.yy);
|
||||
name);
|
||||
|
||||
/* We don't know the bbox values until after the charstrings have
|
||||
* been generated. Reserve some space and fill in the bbox
|
||||
|
@ -558,6 +579,7 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
|
|||
const char *name)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
cairo_status_t status2;
|
||||
cairo_output_stream_t *encrypted_output;
|
||||
|
||||
font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
|
||||
|
@ -597,10 +619,10 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
|
|||
"dup /FontName get exch definefont pop\n"
|
||||
"mark currentfile closefile\n");
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = _cairo_output_stream_get_status (encrypted_output);
|
||||
fail:
|
||||
_cairo_output_stream_destroy (encrypted_output);
|
||||
status2 = _cairo_output_stream_destroy (encrypted_output);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -672,14 +694,18 @@ cairo_type1_font_generate (cairo_type1_font_t *font, const char *name)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
static cairo_status_t
|
||||
cairo_type1_font_destroy (cairo_type1_font_t *font)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
free (font->widths);
|
||||
cairo_scaled_font_destroy (font->type1_scaled_font);
|
||||
_cairo_array_fini (&font->contents);
|
||||
_cairo_output_stream_destroy (font->output);
|
||||
status = _cairo_output_stream_destroy (font->output);
|
||||
free (font);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
@ -745,14 +771,14 @@ _cairo_type1_fallback_init_internal (cairo_type1_subset_t *type1_subset,
|
|||
type1_subset->data_length = font->data_size;
|
||||
type1_subset->trailer_length = font->trailer_size;
|
||||
|
||||
cairo_type1_font_destroy (font);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return cairo_type1_font_destroy (font);
|
||||
|
||||
fail3:
|
||||
free (type1_subset->widths);
|
||||
fail2:
|
||||
free (type1_subset->base_font);
|
||||
fail1:
|
||||
/* status is already set, ignore further errors */
|
||||
cairo_type1_font_destroy (font);
|
||||
|
||||
return status;
|
||||
|
@ -785,3 +811,83 @@ _cairo_type1_fallback_fini (cairo_type1_subset_t *subset)
|
|||
free (subset->widths);
|
||||
free (subset->data);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
|
||||
cairo_scaled_font_subset_t *scaled_font_subset)
|
||||
{
|
||||
cairo_type1_font_t *font;
|
||||
cairo_status_t status;
|
||||
unsigned int i;
|
||||
cairo_array_t charstring;
|
||||
|
||||
status = cairo_type1_font_create (scaled_font_subset, &font, FALSE);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_array_init (&type2_subset->charstrings, sizeof (cairo_array_t));
|
||||
|
||||
type2_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
|
||||
if (type2_subset->widths == NULL) {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
|
||||
_cairo_array_init (&charstring, sizeof (unsigned char));
|
||||
status = _cairo_array_grow_by (&charstring, 32);
|
||||
if (status)
|
||||
goto fail2;
|
||||
|
||||
if (i == 0) {
|
||||
status = create_notdef_charstring (&charstring, CAIRO_CHARSTRING_TYPE2);
|
||||
} else {
|
||||
status = cairo_type1_font_create_charstring (font, i,
|
||||
font->scaled_font_subset->glyphs[i],
|
||||
CAIRO_CHARSTRING_TYPE2,
|
||||
&charstring);
|
||||
}
|
||||
if (status)
|
||||
goto fail2;
|
||||
|
||||
status = _cairo_array_append (&type2_subset->charstrings, &charstring);
|
||||
if (status)
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
|
||||
type2_subset->widths[i] = font->widths[i];
|
||||
|
||||
type2_subset->x_min = (int) font->x_min;
|
||||
type2_subset->y_min = (int) font->y_min;
|
||||
type2_subset->x_max = (int) font->x_max;
|
||||
type2_subset->y_max = (int) font->y_max;
|
||||
type2_subset->ascent = (int) font->y_max;
|
||||
type2_subset->descent = (int) font->y_min;
|
||||
|
||||
cairo_type1_font_destroy (font);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
fail2:
|
||||
_cairo_array_fini (&charstring);
|
||||
_cairo_type2_charstrings_fini (type2_subset);
|
||||
fail1:
|
||||
cairo_type1_font_destroy (font);
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *type2_subset)
|
||||
{
|
||||
unsigned int i, num_charstrings;
|
||||
cairo_array_t *charstring;
|
||||
|
||||
num_charstrings = _cairo_array_num_elements (&type2_subset->charstrings);
|
||||
for (i = 0; i < num_charstrings; i++) {
|
||||
charstring = _cairo_array_index (&type2_subset->charstrings, i);
|
||||
_cairo_array_fini (charstring);
|
||||
}
|
||||
_cairo_array_fini (&type2_subset->charstrings);
|
||||
|
||||
free (type2_subset->widths);
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include FT_OUTLINE_H
|
||||
#include FT_TYPE1_TABLES_H
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
typedef struct _cairo_type1_font_subset {
|
||||
|
||||
cairo_scaled_font_subset_t *scaled_font_subset;
|
||||
|
@ -1133,9 +1135,6 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
|
|||
cairo_type1_font_subset_use_glyph (font, parent_glyph);
|
||||
}
|
||||
|
||||
/* Pull in the .notdef glyph */
|
||||
cairo_type1_font_subset_use_glyph (font, 0);
|
||||
|
||||
status = cairo_type1_font_subset_generate (font, name);
|
||||
if (status)
|
||||
goto fail1;
|
||||
|
@ -1195,3 +1194,30 @@ _cairo_type1_subset_fini (cairo_type1_subset_t *subset)
|
|||
free (subset->widths);
|
||||
free (subset->data);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_ft_unscaled_font_t *unscaled;
|
||||
FT_Face face;
|
||||
PS_FontInfoRec font_info;
|
||||
cairo_bool_t is_type1 = FALSE;
|
||||
|
||||
unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
|
||||
face = _cairo_ft_unscaled_font_lock_face (unscaled);
|
||||
if (!face)
|
||||
return FALSE;
|
||||
|
||||
if (FT_Get_PS_Font_Info(face, &font_info) == 0)
|
||||
is_type1 = TRUE;
|
||||
|
||||
/* OpenType/CFF fonts also have a PS_FontInfoRec */
|
||||
#if HAVE_FT_LOAD_SFNT_TABLE
|
||||
if (FT_IS_SFNT (face))
|
||||
is_type1 = FALSE;
|
||||
#endif
|
||||
|
||||
_cairo_ft_unscaled_font_unlock_face (unscaled);
|
||||
|
||||
return is_type1;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* 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):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_TYPES_PRIVATE_H
|
||||
#define CAIRO_TYPES_PRIVATE_H
|
||||
|
||||
typedef struct _cairo_array cairo_array_t;
|
||||
struct _cairo_array {
|
||||
unsigned int size;
|
||||
unsigned int num_elements;
|
||||
unsigned int element_size;
|
||||
char **elements;
|
||||
|
||||
cairo_bool_t is_snapshot;
|
||||
};
|
||||
|
||||
typedef cairo_array_t cairo_user_data_array_t;
|
||||
|
||||
struct _cairo_font_options {
|
||||
cairo_antialias_t antialias;
|
||||
cairo_subpixel_order_t subpixel_order;
|
||||
cairo_hint_style_t hint_style;
|
||||
cairo_hint_metrics_t hint_metrics;
|
||||
};
|
||||
|
||||
typedef struct _cairo_hash_table cairo_hash_table_t;
|
||||
|
||||
typedef struct _cairo_cache {
|
||||
cairo_hash_table_t *hash_table;
|
||||
|
||||
cairo_destroy_func_t entry_destroy;
|
||||
|
||||
unsigned long max_size;
|
||||
unsigned long size;
|
||||
|
||||
int freeze_count;
|
||||
} cairo_cache_t;
|
||||
|
||||
/**
|
||||
* cairo_hash_entry_t:
|
||||
*
|
||||
* A #cairo_hash_entry_t contains both a key and a value for
|
||||
* cairo_hash_table_t. User-derived types for cairo_hash_entry_t must
|
||||
* be type-compatible with this structure (eg. they must have an
|
||||
* unsigned long as the first parameter. The easiest way to get this
|
||||
* is to use:
|
||||
*
|
||||
* typedef _my_entry {
|
||||
* cairo_hash_entry_t base;
|
||||
* ... Remainder of key and value fields here ..
|
||||
* } my_entry_t;
|
||||
*
|
||||
* which then allows a pointer to my_entry_t to be passed to any of
|
||||
* the cairo_hash_table functions as follows without requiring a cast:
|
||||
*
|
||||
* _cairo_hash_table_insert (hash_table, &my_entry->base);
|
||||
*
|
||||
* IMPORTANT: The caller is reponsible for initializing
|
||||
* my_entry->base.hash with a hash code derived from the key. The
|
||||
* essential property of the hash code is that keys_equal must never
|
||||
* return TRUE for two keys that have different hashes. The best hash
|
||||
* code will reduce the frequency of two keys with the same code for
|
||||
* which keys_equal returns FALSE.
|
||||
*
|
||||
* Which parts of the entry make up the "key" and which part make up
|
||||
* the value are entirely up to the caller, (as determined by the
|
||||
* computation going into base.hash as well as the keys_equal
|
||||
* function). A few of the cairo_hash_table functions accept an entry
|
||||
* which will be used exclusively as a "key", (indicated by a
|
||||
* parameter name of key). In these cases, the value-related fields of
|
||||
* the entry need not be initialized if so desired.
|
||||
**/
|
||||
typedef struct _cairo_hash_entry {
|
||||
unsigned long hash;
|
||||
} cairo_hash_entry_t;
|
||||
|
||||
|
||||
typedef struct _cairo_surface_backend cairo_surface_backend_t;
|
||||
typedef struct _cairo_clip cairo_clip_t;
|
||||
typedef struct _cairo_output_stream cairo_output_stream_t;
|
||||
typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
|
||||
typedef struct _cairo_paginated_surface_backend cairo_paginated_surface_backend_t;
|
||||
typedef struct _cairo_scaled_font_backend cairo_scaled_font_backend_t;
|
||||
typedef struct _cairo_font_face_backend cairo_font_face_backend_t;
|
||||
|
||||
|
||||
typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t;
|
||||
|
||||
typedef enum {
|
||||
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
|
||||
CAIRO_PAGINATED_MODE_RENDER /* render page contents */
|
||||
} cairo_paginated_mode_t;
|
||||
|
||||
#endif /* CAIRO_TYPES_PRIVATE_H */
|
|
@ -40,9 +40,7 @@
|
|||
* Owen Taylor <otaylor@redhat.com>
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <cairoint.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#define UTF8_COMPUTE(Char, Mask, Len) \
|
||||
if (Char < 128) \
|
||||
|
|
|
@ -64,6 +64,12 @@
|
|||
# ifndef UINT16_MAX
|
||||
# define UINT16_MAX (65535)
|
||||
# endif
|
||||
# ifndef INT32_MIN
|
||||
# define INT32_MIN (-2147483647-1)
|
||||
# endif
|
||||
# ifndef INT32_MAX
|
||||
# define INT32_MAX (2147483647)
|
||||
# endif
|
||||
#else
|
||||
#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
|
||||
#endif
|
||||
|
|
|
@ -32,9 +32,8 @@
|
|||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-win32-private.h"
|
||||
|
||||
#ifndef SPI_GETFONTSMOOTHINGTYPE
|
||||
|
@ -227,15 +226,9 @@ _get_system_quality (void)
|
|||
}
|
||||
}
|
||||
|
||||
/* If face_hfont is non-NULL then font_matrix must be a simple scale by some
|
||||
* factor S, ctm must be the identity, logfont->lfHeight must be -S,
|
||||
* logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
|
||||
* all be 0, and face_hfont is the result of calling CreateFontIndirectW on
|
||||
* logfont.
|
||||
*/
|
||||
static cairo_scaled_font_t *
|
||||
_win32_scaled_font_create (LOGFONTW *logfont,
|
||||
HFONT face_hfont,
|
||||
HFONT hfont,
|
||||
cairo_font_face_t *font_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
const cairo_matrix_t *ctm,
|
||||
|
@ -245,8 +238,6 @@ _win32_scaled_font_create (LOGFONTW *logfont,
|
|||
cairo_matrix_t scale;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_win32_initialize ();
|
||||
|
||||
f = malloc (sizeof(cairo_win32_scaled_font_t));
|
||||
if (f == NULL)
|
||||
return NULL;
|
||||
|
@ -283,29 +274,22 @@ _win32_scaled_font_create (LOGFONTW *logfont,
|
|||
}
|
||||
|
||||
f->em_square = 0;
|
||||
f->scaled_hfont = NULL;
|
||||
f->scaled_hfont = hfont;
|
||||
f->unscaled_hfont = NULL;
|
||||
if (f->quality == logfont->lfQuality ||
|
||||
(logfont->lfQuality == DEFAULT_QUALITY &&
|
||||
options->antialias == CAIRO_ANTIALIAS_DEFAULT)) {
|
||||
/* If face_hfont is non-NULL, then we can use it to avoid creating our
|
||||
* own --- because the constraints on face_hfont mentioned above
|
||||
* guarantee it was created in exactly the same way that
|
||||
* _win32_scaled_font_get_scaled_hfont would create it.
|
||||
*/
|
||||
f->scaled_hfont = face_hfont;
|
||||
}
|
||||
/* don't delete the hfont if we're using the one passed in to us */
|
||||
f->delete_scaled_hfont = !f->scaled_hfont;
|
||||
|
||||
/* don't delete the hfont if it was passed in to us */
|
||||
f->delete_scaled_hfont = !hfont;
|
||||
|
||||
cairo_matrix_multiply (&scale, font_matrix, ctm);
|
||||
_compute_transform (f, &scale);
|
||||
|
||||
_cairo_scaled_font_init (&f->base, font_face,
|
||||
font_matrix, ctm, options,
|
||||
&cairo_win32_scaled_font_backend);
|
||||
status = _cairo_scaled_font_init (&f->base, font_face,
|
||||
font_matrix, ctm, options,
|
||||
&cairo_win32_scaled_font_backend);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = _cairo_win32_scaled_font_set_metrics (f);
|
||||
|
||||
status = _cairo_win32_scaled_font_set_metrics (f);
|
||||
if (status) {
|
||||
cairo_scaled_font_destroy (&f->base);
|
||||
return NULL;
|
||||
|
@ -487,8 +471,6 @@ _cairo_win32_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
|
|||
int face_name_len;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_win32_initialize ();
|
||||
|
||||
status = _cairo_utf8_to_utf16 (toy_face->family, -1,
|
||||
&face_name, &face_name_len);
|
||||
if (status)
|
||||
|
@ -1471,16 +1453,14 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
|
|||
}
|
||||
free(buffer);
|
||||
|
||||
CLEANUP_FONT:
|
||||
|
||||
_cairo_scaled_glyph_set_path (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
path);
|
||||
|
||||
CLEANUP_FONT:
|
||||
cairo_win32_scaled_font_done_font (&scaled_font->base);
|
||||
|
||||
CLEANUP_PATH:
|
||||
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
_cairo_path_fixed_destroy (path);
|
||||
|
||||
|
@ -1503,11 +1483,6 @@ const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
|
|||
|
||||
typedef struct _cairo_win32_font_face cairo_win32_font_face_t;
|
||||
|
||||
/* If hfont is non-NULL then logfont->lfHeight must be -S for some S,
|
||||
* logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
|
||||
* all be 0, and hfont is the result of calling CreateFontIndirectW on
|
||||
* logfont.
|
||||
*/
|
||||
struct _cairo_win32_font_face {
|
||||
cairo_font_face_t base;
|
||||
LOGFONTW logfont;
|
||||
|
@ -1521,14 +1496,6 @@ _cairo_win32_font_face_destroy (void *abstract_face)
|
|||
{
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_is_scale (const cairo_matrix_t *matrix, double scale)
|
||||
{
|
||||
return matrix->xx == scale && matrix->yy == scale &&
|
||||
matrix->xy == 0. && matrix->yx == 0. &&
|
||||
matrix->x0 == 0. && matrix->y0 == 0.;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_font_face_scaled_font_create (void *abstract_face,
|
||||
const cairo_matrix_t *font_matrix,
|
||||
|
@ -1536,22 +1503,10 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face,
|
|||
const cairo_font_options_t *options,
|
||||
cairo_scaled_font_t **font)
|
||||
{
|
||||
HFONT hfont = NULL;
|
||||
|
||||
cairo_win32_font_face_t *font_face = abstract_face;
|
||||
|
||||
_cairo_win32_initialize ();
|
||||
|
||||
if (font_face->hfont) {
|
||||
/* Check whether it's OK to go ahead and use the font-face's HFONT. */
|
||||
if (_is_scale (ctm, 1.) &&
|
||||
_is_scale (font_matrix, -font_face->logfont.lfHeight)) {
|
||||
hfont = font_face->hfont;
|
||||
}
|
||||
}
|
||||
|
||||
*font = _win32_scaled_font_create (&font_face->logfont,
|
||||
hfont,
|
||||
font_face->hfont,
|
||||
&font_face->base,
|
||||
font_matrix, ctm, options);
|
||||
if (*font)
|
||||
|
@ -1566,46 +1521,6 @@ static const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
|
|||
_cairo_win32_font_face_scaled_font_create
|
||||
};
|
||||
|
||||
/**
|
||||
* cairo_win32_font_face_create_for_logfontw_hfont:
|
||||
* @logfont: A #LOGFONTW structure specifying the font to use.
|
||||
* If hfont is null then the lfHeight, lfWidth, lfOrientation and lfEscapement
|
||||
* fields of this structure are ignored. Otherwise lfWidth, lfOrientation and
|
||||
* lfEscapement must be zero.
|
||||
* @font: An #HFONT that can be used when the font matrix is a scale by
|
||||
* -lfHeight and the CTM is identity.
|
||||
*
|
||||
* Creates a new font for the Win32 font backend based on a
|
||||
* #LOGFONT. This font can then be used with
|
||||
* cairo_set_font_face() or cairo_scaled_font_create().
|
||||
* The #cairo_scaled_font_t
|
||||
* returned from cairo_scaled_font_create() is also for the Win32 backend
|
||||
* and can be used with functions such as cairo_win32_scaled_font_select_font().
|
||||
*
|
||||
* Return value: a newly created #cairo_font_face_t. Free with
|
||||
* cairo_font_face_destroy() when you are done using it.
|
||||
**/
|
||||
cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
|
||||
{
|
||||
cairo_win32_font_face_t *font_face;
|
||||
|
||||
_cairo_win32_initialize ();
|
||||
|
||||
font_face = malloc (sizeof (cairo_win32_font_face_t));
|
||||
if (!font_face) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
font_face->logfont = *logfont;
|
||||
font_face->hfont = font;
|
||||
|
||||
_cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
|
||||
|
||||
return &font_face->base;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_win32_font_face_create_for_logfontw:
|
||||
* @logfont: A #LOGFONTW structure specifying the font to use.
|
||||
|
@ -1625,7 +1540,20 @@ cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
|
|||
cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
|
||||
{
|
||||
return cairo_win32_font_face_create_for_logfontw_hfont (logfont, NULL);
|
||||
cairo_win32_font_face_t *font_face;
|
||||
|
||||
font_face = malloc (sizeof (cairo_win32_font_face_t));
|
||||
if (!font_face) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
font_face->logfont = *logfont;
|
||||
font_face->hfont = NULL;
|
||||
|
||||
_cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
|
||||
|
||||
return &font_face->base;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1645,17 +1573,19 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
|
|||
cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_hfont (HFONT font)
|
||||
{
|
||||
LOGFONTW logfont;
|
||||
GetObject (font, sizeof(logfont), &logfont);
|
||||
cairo_win32_font_face_t *font_face;
|
||||
|
||||
if (logfont.lfEscapement != 0 || logfont.lfOrientation != 0 ||
|
||||
logfont.lfWidth != 0) {
|
||||
/* We can't use this font because that optimization requires that
|
||||
* lfEscapement, lfOrientation and lfWidth be zero. */
|
||||
font = NULL;
|
||||
font_face = malloc (sizeof (cairo_win32_font_face_t));
|
||||
if (!font_face) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_font_face_t *)&_cairo_font_face_nil;
|
||||
}
|
||||
|
||||
return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font);
|
||||
font_face->hfont = font;
|
||||
|
||||
_cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
|
||||
|
||||
return &font_face->base;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,11 +46,7 @@
|
|||
#define SB_NONE 0
|
||||
#endif
|
||||
|
||||
#if MOZILLA_CAIRO_NOT_DEFINED
|
||||
#define WIN32_FONT_LOGICAL_SCALE 32
|
||||
#else
|
||||
#define WIN32_FONT_LOGICAL_SCALE 1
|
||||
#endif
|
||||
|
||||
typedef struct _cairo_win32_surface {
|
||||
cairo_surface_t base;
|
||||
|
@ -109,7 +105,4 @@ _cairo_win32_print_gdi_error (const char *context);
|
|||
cairo_bool_t
|
||||
_cairo_surface_is_win32 (cairo_surface_t *surface);
|
||||
|
||||
void
|
||||
_cairo_win32_initialize (void);
|
||||
|
||||
#endif /* CAIRO_WIN32_PRIVATE_H */
|
||||
|
|
|
@ -44,13 +44,18 @@
|
|||
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
|
||||
# define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-win32-private.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(__MINGW32__) && !defined(ETO_PDY)
|
||||
# define ETO_PDY 0x2000
|
||||
#endif
|
||||
|
||||
#undef DEBUG_COMPOSITE
|
||||
|
||||
/* for older SDKs */
|
||||
|
@ -327,8 +332,6 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
|
|||
char *bits;
|
||||
int rowstride;
|
||||
|
||||
_cairo_win32_initialize ();
|
||||
|
||||
surface = malloc (sizeof (cairo_win32_surface_t));
|
||||
if (surface == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
@ -473,12 +476,7 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
|
|||
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* Check for SURFACE_IS_DISPLAY here, because there are a lot
|
||||
* of printer drivers that lie and say they can BitBlt, but
|
||||
* just spit out black instead.
|
||||
*/
|
||||
if ((local->flags & CAIRO_WIN32_SURFACE_IS_DISPLAY) &&
|
||||
(local->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
|
||||
if ((local->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
|
||||
BitBlt (local->dc,
|
||||
0, 0,
|
||||
width, height,
|
||||
|
@ -1640,8 +1638,6 @@ cairo_win32_surface_create (HDC hdc)
|
|||
int depth;
|
||||
cairo_format_t format;
|
||||
|
||||
_cairo_win32_initialize ();
|
||||
|
||||
/* Try to figure out the drawing bounds for the Device context
|
||||
*/
|
||||
if (GetClipBox (hdc, &rect) == ERROR) {
|
||||
|
@ -1859,6 +1855,30 @@ cairo_win32_surface_get_image (cairo_surface_t *surface)
|
|||
return ((cairo_win32_surface_t*)surface)->image;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_win32_surface_is_similar (void *surface_a,
|
||||
void *surface_b,
|
||||
cairo_content_t content)
|
||||
{
|
||||
cairo_win32_surface_t *a = surface_a;
|
||||
cairo_win32_surface_t *b = surface_b;
|
||||
|
||||
return a->dc == b->dc;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_surface_reset (void *abstract_surface)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_win32_surface_set_clip_region (surface, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_WIN32,
|
||||
_cairo_win32_surface_create_similar,
|
||||
|
@ -1889,70 +1909,12 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
|||
NULL, /* fill */
|
||||
_cairo_win32_surface_show_glyphs,
|
||||
|
||||
NULL /* snapshot */
|
||||
NULL, /* snapshot */
|
||||
_cairo_win32_surface_is_similar,
|
||||
|
||||
_cairo_win32_surface_reset
|
||||
};
|
||||
|
||||
/*
|
||||
* Without pthread, on win32 we need to initialize all the 'mutex'es
|
||||
* before use. It is guaranteed that DllMain will get called single
|
||||
* threaded before any other function.
|
||||
* Initializing more than finally needed should not matter much.
|
||||
*/
|
||||
#if !defined(HAVE_PTHREAD_H)
|
||||
|
||||
CRITICAL_SECTION _cairo_scaled_font_map_mutex;
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
CRITICAL_SECTION _cairo_ft_unscaled_font_map_mutex;
|
||||
#endif
|
||||
CRITICAL_SECTION _cairo_font_face_mutex;
|
||||
|
||||
static int _cairo_win32_initialized = 0;
|
||||
|
||||
void
|
||||
_cairo_win32_initialize (void) {
|
||||
if (_cairo_win32_initialized)
|
||||
return;
|
||||
|
||||
/* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */
|
||||
InitializeCriticalSection (&_cairo_scaled_font_map_mutex);
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
InitializeCriticalSection (&_cairo_ft_unscaled_font_map_mutex);
|
||||
#endif
|
||||
InitializeCriticalSection (&_cairo_font_face_mutex);
|
||||
|
||||
_cairo_win32_initialized = 1;
|
||||
}
|
||||
|
||||
#if !defined(CAIRO_WIN32_STATIC_BUILD)
|
||||
BOOL WINAPI
|
||||
DllMain (HINSTANCE hinstDLL,
|
||||
DWORD fdwReason,
|
||||
LPVOID lpvReserved)
|
||||
{
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
_cairo_win32_initialize();
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
DeleteCriticalSection (&_cairo_scaled_font_map_mutex);
|
||||
#ifdef CAIRO_HAS_FT_FONT
|
||||
DeleteCriticalSection (&_cairo_ft_unscaled_font_map_mutex);
|
||||
#endif
|
||||
DeleteCriticalSection (&_cairo_font_face_mutex);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
/* Need a function definition here too since it's called outside of ifdefs */
|
||||
void
|
||||
_cairo_win32_initialize (void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Notes:
|
||||
*
|
||||
* Win32 alpha-understanding functions
|
||||
|
@ -1966,3 +1928,33 @@ _cairo_win32_initialize (void)
|
|||
* it will still copy over the src alpha, because the SCA value (255) will be
|
||||
* multiplied by all the src components.
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(CAIRO_WIN32_STATIC_BUILD)
|
||||
|
||||
/* declare to avoid "no previous prototype for 'DllMain'" warning */
|
||||
BOOL WINAPI
|
||||
DllMain (HINSTANCE hinstDLL,
|
||||
DWORD fdwReason,
|
||||
LPVOID lpvReserved);
|
||||
|
||||
BOOL WINAPI
|
||||
DllMain (HINSTANCE hinstDLL,
|
||||
DWORD fdwReason,
|
||||
LPVOID lpvReserved)
|
||||
{
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
CAIRO_MUTEX_INITIALIZE ();
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
CAIRO_MUTEX_FINALIZE ();
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -70,9 +70,6 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
|
|||
cairo_public cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_hfont (HFONT font);
|
||||
|
||||
cairo_public cairo_font_face_t *
|
||||
cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
|
||||
HDC hdc);
|
||||
|
|
|
@ -1577,6 +1577,39 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
|||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_xcb_surface_is_similar (void *surface_a,
|
||||
void *surface_b,
|
||||
cairo_content_t content)
|
||||
{
|
||||
cairo_xcb_surface_t *a = surface_a;
|
||||
cairo_xcb_surface_t *b = surface_b;
|
||||
xcb_render_pictforminfo_t *xrender_format;
|
||||
|
||||
if (! _cairo_xcb_surface_same_screen (a, b))
|
||||
return FALSE;
|
||||
|
||||
/* now check that the target is a similar format */
|
||||
xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (b->dpy,
|
||||
_cairo_format_from_content (content));
|
||||
|
||||
return a->xrender_format.id == xrender_format->id;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xcb_surface_reset (void *abstract_surface)
|
||||
{
|
||||
cairo_xcb_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_xcb_surface_set_clip_region (surface, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* XXX: move this to the bottom of the file, XCB and Xlib */
|
||||
|
||||
static const cairo_surface_backend_t cairo_xcb_surface_backend = {
|
||||
|
@ -1608,7 +1641,11 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
|
|||
NULL, /* stroke */
|
||||
NULL, /* fill */
|
||||
_cairo_xcb_surface_show_glyphs,
|
||||
NULL /* snapshot */
|
||||
NULL, /* snapshot */
|
||||
|
||||
_cairo_xcb_surface_is_similar,
|
||||
|
||||
_cairo_xcb_surface_reset
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2344,7 +2381,8 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
|||
* so PictOpClear was never used with CompositeText before.
|
||||
*/
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
|
||||
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
src_pattern = &solid_pattern.base;
|
||||
op = CAIRO_OPERATOR_DEST_OUT;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,453 @@
|
|||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2007 Chris Wilson
|
||||
*
|
||||
* 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 Chris Wilson.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-xlib-private.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
typedef int (*cairo_xlib_error_func_t) (Display *display,
|
||||
XErrorEvent *event);
|
||||
|
||||
struct _cairo_xlib_job {
|
||||
cairo_xlib_job_t *next;
|
||||
enum {
|
||||
RESOURCE,
|
||||
WORK
|
||||
} type;
|
||||
union {
|
||||
struct {
|
||||
cairo_xlib_notify_resource_func notify;
|
||||
XID xid;
|
||||
} resource;
|
||||
struct {
|
||||
cairo_xlib_notify_func notify;
|
||||
void *data;
|
||||
void (*destroy) (void *);
|
||||
} work;
|
||||
} func;
|
||||
};
|
||||
|
||||
static cairo_xlib_display_t *_cairo_xlib_display_list;
|
||||
|
||||
static void
|
||||
_cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display)
|
||||
{
|
||||
cairo_xlib_screen_info_t *screen;
|
||||
cairo_xlib_hook_t *hooks, *list;
|
||||
|
||||
/* call all registered shutdown routines */
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
|
||||
for (screen = display->screens; screen != NULL; screen = screen->next)
|
||||
_cairo_xlib_screen_info_close_display (screen);
|
||||
|
||||
hooks = display->close_display_hooks;
|
||||
while (hooks != NULL) {
|
||||
display->close_display_hooks = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
list = hooks;
|
||||
do {
|
||||
cairo_xlib_hook_t *hook = list;
|
||||
list = hook->next;
|
||||
|
||||
hook->func (display->display, hook->data);
|
||||
} while (list != NULL);
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
do {
|
||||
cairo_xlib_hook_t *hook = hooks;
|
||||
hooks = hook->next;
|
||||
|
||||
_cairo_freelist_free (&display->hook_freelist, hook);
|
||||
} while (hooks != NULL);
|
||||
|
||||
hooks = display->close_display_hooks;
|
||||
}
|
||||
display->closed = TRUE;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xlib_display_discard_screens (cairo_xlib_display_t *display)
|
||||
{
|
||||
cairo_xlib_screen_info_t *screens;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
screens = display->screens;
|
||||
display->screens = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
while (screens != NULL) {
|
||||
cairo_xlib_screen_info_t *screen = screens;
|
||||
screens = screen->next;
|
||||
|
||||
_cairo_xlib_screen_info_destroy (screen);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_xlib_display_t *
|
||||
_cairo_xlib_display_reference (cairo_xlib_display_t *display)
|
||||
{
|
||||
if (display == NULL)
|
||||
return NULL;
|
||||
|
||||
/* use our mutex until we get a real atomic inc */
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
|
||||
assert (display->ref_count > 0);
|
||||
display->ref_count++;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_display_destroy (cairo_xlib_display_t *display)
|
||||
{
|
||||
if (display == NULL)
|
||||
return;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
assert (display->ref_count > 0);
|
||||
if (--display->ref_count == 0) {
|
||||
/* destroy all outstanding notifies */
|
||||
while (display->workqueue != NULL) {
|
||||
cairo_xlib_job_t *job = display->workqueue;
|
||||
display->workqueue = job->next;
|
||||
|
||||
if (job->type == WORK && job->func.work.destroy != NULL)
|
||||
job->func.work.destroy (job->func.work.data);
|
||||
|
||||
_cairo_freelist_free (&display->wq_freelist, job);
|
||||
}
|
||||
_cairo_freelist_fini (&display->wq_freelist);
|
||||
_cairo_freelist_fini (&display->hook_freelist);
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
free (display);
|
||||
} else
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
}
|
||||
|
||||
static int
|
||||
_noop_error_handler (Display *display,
|
||||
XErrorEvent *event)
|
||||
{
|
||||
return False; /* return value is ignored */
|
||||
}
|
||||
static int
|
||||
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
|
||||
{
|
||||
cairo_xlib_display_t *display, **prev, *next;
|
||||
|
||||
/*
|
||||
* Unhook from the global list
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
|
||||
prev = &_cairo_xlib_display_list;
|
||||
for (display = _cairo_xlib_display_list; display; display = next) {
|
||||
next = display->next;
|
||||
if (display->display == dpy) {
|
||||
cairo_xlib_error_func_t old_handler;
|
||||
|
||||
/* drop the list mutex whilst triggering the hooks */
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
|
||||
|
||||
/* protect the notifies from triggering XErrors */
|
||||
XSync (dpy, False);
|
||||
old_handler = XSetErrorHandler (_noop_error_handler);
|
||||
|
||||
_cairo_xlib_display_notify (display);
|
||||
_cairo_xlib_call_close_display_hooks (display);
|
||||
_cairo_xlib_display_discard_screens (display);
|
||||
|
||||
/* catch any that arrived before marking the display as closed */
|
||||
_cairo_xlib_display_notify (display);
|
||||
|
||||
XSync (dpy, False);
|
||||
XSetErrorHandler (old_handler);
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
|
||||
_cairo_xlib_display_destroy (display);
|
||||
*prev = next;
|
||||
break;
|
||||
} else
|
||||
prev = &display->next;
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
|
||||
|
||||
/* Return value in accordance with requirements of
|
||||
* XESetCloseDisplay */
|
||||
return 0;
|
||||
}
|
||||
|
||||
cairo_xlib_display_t *
|
||||
_cairo_xlib_display_get (Display *dpy)
|
||||
{
|
||||
cairo_xlib_display_t *display;
|
||||
cairo_xlib_display_t **prev;
|
||||
XExtCodes *codes;
|
||||
|
||||
/* There is an apparent deadlock between this mutex and the
|
||||
* mutex for the display, but it's actually safe. For the
|
||||
* app to call XCloseDisplay() while any other thread is
|
||||
* inside this function would be an error in the logic
|
||||
* app, and the CloseDisplay hook is the only other place we
|
||||
* acquire this mutex.
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
|
||||
|
||||
for (prev = &_cairo_xlib_display_list; (display = *prev); prev = &(*prev)->next)
|
||||
{
|
||||
if (display->display == dpy) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
if (prev != &_cairo_xlib_display_list) {
|
||||
*prev = display->next;
|
||||
display->next = _cairo_xlib_display_list;
|
||||
_cairo_xlib_display_list = display;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (display != NULL) {
|
||||
display = _cairo_xlib_display_reference (display);
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
display = malloc (sizeof (cairo_xlib_display_t));
|
||||
if (display == NULL)
|
||||
goto UNLOCK;
|
||||
|
||||
codes = XAddExtension (dpy);
|
||||
if (codes == NULL) {
|
||||
free (display);
|
||||
display = NULL;
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
|
||||
|
||||
_cairo_freelist_init (&display->wq_freelist, sizeof (cairo_xlib_job_t));
|
||||
_cairo_freelist_init (&display->hook_freelist, sizeof (cairo_xlib_hook_t));
|
||||
|
||||
display->ref_count = 2; /* add one for the CloseDisplay */
|
||||
CAIRO_MUTEX_INIT (display->mutex);
|
||||
display->display = dpy;
|
||||
display->screens = NULL;
|
||||
display->workqueue = NULL;
|
||||
display->close_display_hooks = NULL;
|
||||
display->closed = FALSE;
|
||||
|
||||
display->next = _cairo_xlib_display_list;
|
||||
_cairo_xlib_display_list = display;
|
||||
|
||||
UNLOCK:
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
|
||||
return display;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, const void *key)
|
||||
{
|
||||
cairo_xlib_display_t *display;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_bool_t ret = FALSE;
|
||||
|
||||
display = _cairo_xlib_display_get (dpy);
|
||||
if (display == NULL)
|
||||
return FALSE;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
if (display->closed == FALSE) {
|
||||
hook = _cairo_freelist_alloc (&display->hook_freelist);
|
||||
if (hook != NULL) {
|
||||
hook->func = func;
|
||||
hook->data = data;
|
||||
hook->key = key;
|
||||
|
||||
hook->next = display->close_display_hooks;
|
||||
display->close_display_hooks = hook;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
_cairo_xlib_display_destroy (display);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_remove_close_display_hooks (Display *dpy, const void *key)
|
||||
{
|
||||
cairo_xlib_display_t *display;
|
||||
cairo_xlib_hook_t *hook, *next, **prev;
|
||||
|
||||
display = _cairo_xlib_display_get (dpy);
|
||||
if (display == NULL)
|
||||
return;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
prev = &display->close_display_hooks;
|
||||
for (hook = display->close_display_hooks; hook != NULL; hook = next) {
|
||||
next = hook->next;
|
||||
if (hook->key == key) {
|
||||
*prev = hook->next;
|
||||
_cairo_freelist_free (&display->hook_freelist, hook);
|
||||
} else
|
||||
prev = &hook->next;
|
||||
}
|
||||
*prev = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
_cairo_xlib_display_destroy (display);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_xlib_display_queue_resource (cairo_xlib_display_t *display,
|
||||
cairo_xlib_notify_resource_func notify,
|
||||
XID xid)
|
||||
{
|
||||
cairo_xlib_job_t *job;
|
||||
cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
if (display->closed == FALSE) {
|
||||
job = _cairo_freelist_alloc (&display->wq_freelist);
|
||||
if (job != NULL) {
|
||||
job->type = RESOURCE;
|
||||
job->func.resource.xid = xid;
|
||||
job->func.resource.notify = notify;
|
||||
|
||||
job->next = display->workqueue;
|
||||
display->workqueue = job;
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_xlib_display_queue_work (cairo_xlib_display_t *display,
|
||||
cairo_xlib_notify_func notify,
|
||||
void *data,
|
||||
void (*destroy) (void *))
|
||||
{
|
||||
cairo_xlib_job_t *job;
|
||||
cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
if (display->closed == FALSE) {
|
||||
job = _cairo_freelist_alloc (&display->wq_freelist);
|
||||
if (job != NULL) {
|
||||
job->type = WORK;
|
||||
job->func.work.data = data;
|
||||
job->func.work.notify = notify;
|
||||
job->func.work.destroy = destroy;
|
||||
|
||||
job->next = display->workqueue;
|
||||
display->workqueue = job;
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_display_notify (cairo_xlib_display_t *display)
|
||||
{
|
||||
cairo_xlib_job_t *jobs, *job, *freelist;
|
||||
Display *dpy = display->display;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
jobs = display->workqueue;
|
||||
while (jobs != NULL) {
|
||||
display->workqueue = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
/* reverse the list to obtain FIFO order */
|
||||
job = NULL;
|
||||
do {
|
||||
cairo_xlib_job_t *next = jobs->next;
|
||||
jobs->next = job;
|
||||
job = jobs;
|
||||
jobs = next;
|
||||
} while (jobs != NULL);
|
||||
freelist = jobs = job;
|
||||
|
||||
do {
|
||||
job = jobs;
|
||||
jobs = job->next;
|
||||
|
||||
switch (job->type){
|
||||
case WORK:
|
||||
job->func.work.notify (dpy, job->func.work.data);
|
||||
if (job->func.work.destroy != NULL)
|
||||
job->func.work.destroy (job->func.work.data);
|
||||
break;
|
||||
|
||||
case RESOURCE:
|
||||
job->func.resource.notify (dpy, job->func.resource.xid);
|
||||
break;
|
||||
}
|
||||
} while (jobs != NULL);
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
do {
|
||||
job = freelist;
|
||||
freelist = job->next;
|
||||
_cairo_freelist_free (&display->wq_freelist, job);
|
||||
} while (freelist != NULL);
|
||||
|
||||
jobs = display->workqueue;
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
}
|
|
@ -35,43 +35,97 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-xlib.h"
|
||||
#include "cairo-freelist-private.h"
|
||||
|
||||
typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t;
|
||||
typedef struct _cairo_xlib_display cairo_xlib_display_t;
|
||||
typedef struct _cairo_xlib_hook cairo_xlib_hook_t;
|
||||
typedef struct _cairo_xlib_job cairo_xlib_job_t;
|
||||
typedef void (*cairo_xlib_notify_func) (Display *, void *);
|
||||
typedef void (*cairo_xlib_notify_resource_func) (Display *, XID);
|
||||
|
||||
struct _cairo_xlib_hook {
|
||||
cairo_xlib_hook_t *next;
|
||||
void (*func) (Display *display, void *data);
|
||||
void *data;
|
||||
void *key;
|
||||
const void *key;
|
||||
};
|
||||
|
||||
struct _cairo_xlib_display {
|
||||
cairo_xlib_display_t *next;
|
||||
unsigned int ref_count;
|
||||
cairo_mutex_t mutex;
|
||||
|
||||
Display *display;
|
||||
cairo_xlib_screen_info_t *screens;
|
||||
|
||||
cairo_xlib_job_t *workqueue;
|
||||
cairo_freelist_t wq_freelist;
|
||||
|
||||
cairo_freelist_t hook_freelist;
|
||||
cairo_xlib_hook_t *close_display_hooks;
|
||||
unsigned int closed :1;
|
||||
};
|
||||
|
||||
struct _cairo_xlib_screen_info {
|
||||
cairo_xlib_screen_info_t *next;
|
||||
unsigned int ref_count;
|
||||
|
||||
Display *display;
|
||||
cairo_xlib_display_t *display;
|
||||
Screen *screen;
|
||||
cairo_bool_t has_render;
|
||||
|
||||
cairo_font_options_t font_options;
|
||||
|
||||
cairo_xlib_hook_t *close_display_hooks;
|
||||
GC gc[9];
|
||||
unsigned int gc_needs_clip_reset;
|
||||
};
|
||||
|
||||
cairo_private cairo_xlib_display_t *
|
||||
_cairo_xlib_display_get (Display *display);
|
||||
|
||||
cairo_private cairo_xlib_display_t *
|
||||
_cairo_xlib_display_reference (cairo_xlib_display_t *info);
|
||||
cairo_private void
|
||||
_cairo_xlib_display_destroy (cairo_xlib_display_t *info);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, const void *key);
|
||||
cairo_private void
|
||||
_cairo_xlib_remove_close_display_hooks (Display *display, const void *key);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_xlib_display_queue_work (cairo_xlib_display_t *display,
|
||||
cairo_xlib_notify_func notify,
|
||||
void *data,
|
||||
void (*destroy)(void *));
|
||||
cairo_private cairo_status_t
|
||||
_cairo_xlib_display_queue_resource (cairo_xlib_display_t *display,
|
||||
cairo_xlib_notify_resource_func notify,
|
||||
XID resource);
|
||||
cairo_private void
|
||||
_cairo_xlib_display_notify (cairo_xlib_display_t *display);
|
||||
|
||||
cairo_private cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get (Display *display, Screen *screen);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, void *key);
|
||||
cairo_private cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info);
|
||||
cairo_private void
|
||||
_cairo_xlib_remove_close_display_hook (Display *display, void *key);
|
||||
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info);
|
||||
|
||||
cairo_private void
|
||||
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info);
|
||||
|
||||
cairo_private GC
|
||||
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth);
|
||||
cairo_private cairo_status_t
|
||||
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip);
|
||||
|
||||
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
|
||||
#include "cairo-xlib-xrender.h"
|
||||
#ifdef MOZILLA_CAIRO_NOT_DEFINED
|
||||
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CAIRO_XLIB_PRIVATE_H */
|
||||
|
|
|
@ -51,14 +51,13 @@
|
|||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-xlib-private.h"
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
static int
|
||||
|
@ -133,7 +132,7 @@ get_integer_default (Display *dpy,
|
|||
#endif
|
||||
|
||||
static void
|
||||
_cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
|
||||
_cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
cairo_bool_t xft_hinting;
|
||||
cairo_bool_t xft_antialias;
|
||||
|
@ -143,23 +142,23 @@ _cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
|
|||
cairo_subpixel_order_t subpixel_order;
|
||||
cairo_hint_style_t hint_style;
|
||||
|
||||
if (!get_boolean_default (info->display, "antialias", &xft_antialias))
|
||||
if (!get_boolean_default (dpy, "antialias", &xft_antialias))
|
||||
xft_antialias = TRUE;
|
||||
|
||||
if (!get_boolean_default (info->display, "hinting", &xft_hinting))
|
||||
if (!get_boolean_default (dpy, "hinting", &xft_hinting))
|
||||
xft_hinting = TRUE;
|
||||
|
||||
if (!get_integer_default (info->display, "hintstyle", &xft_hintstyle))
|
||||
if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
|
||||
xft_hintstyle = FC_HINT_FULL;
|
||||
|
||||
if (!get_integer_default (info->display, "rgba", &xft_rgba))
|
||||
if (!get_integer_default (dpy, "rgba", &xft_rgba))
|
||||
{
|
||||
xft_rgba = FC_RGBA_UNKNOWN;
|
||||
|
||||
#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
|
||||
if (info->has_render)
|
||||
{
|
||||
int render_order = XRenderQuerySubpixelOrder (info->display,
|
||||
int render_order = XRenderQuerySubpixelOrder (dpy,
|
||||
XScreenNumberOfScreen (info->screen));
|
||||
|
||||
switch (render_order)
|
||||
|
@ -237,235 +236,183 @@ _cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
|
|||
antialias = CAIRO_ANTIALIAS_NONE;
|
||||
}
|
||||
|
||||
_cairo_font_options_init_default (&info->font_options);
|
||||
cairo_font_options_set_hint_style (&info->font_options, hint_style);
|
||||
cairo_font_options_set_antialias (&info->font_options, antialias);
|
||||
cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
|
||||
cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_DECLARE(_xlib_screen_mutex);
|
||||
|
||||
static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
|
||||
|
||||
static int
|
||||
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
|
||||
cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info, **prev, *next;
|
||||
|
||||
/*
|
||||
* Unhook from the global list
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
|
||||
prev = &_cairo_xlib_screen_list;
|
||||
for (info = _cairo_xlib_screen_list; info; info = next) {
|
||||
next = info->next;
|
||||
if (info->display == dpy) {
|
||||
*prev = next;
|
||||
/* call all registered shutdown routines */
|
||||
while (info->close_display_hooks) {
|
||||
cairo_xlib_hook_t *hook = info->close_display_hooks;
|
||||
info->close_display_hooks = hook->next;
|
||||
|
||||
hook->func (dpy, hook->data);
|
||||
|
||||
free (hook);
|
||||
}
|
||||
free (info);
|
||||
} else {
|
||||
prev = &info->next;
|
||||
}
|
||||
}
|
||||
*prev = NULL;
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
|
||||
/* Return value in accordance with requirements of
|
||||
* XESetCloseDisplay */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xlib_screen_info_reset (void)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info, *next;
|
||||
|
||||
/*
|
||||
* Delete everything in the list.
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
|
||||
for (info = _cairo_xlib_screen_list; info; info = next) {
|
||||
next = info->next;
|
||||
while (info->close_display_hooks) {
|
||||
cairo_xlib_hook_t *hook = info->close_display_hooks;
|
||||
info->close_display_hooks = hook->next;
|
||||
free (hook);
|
||||
}
|
||||
free (info);
|
||||
}
|
||||
|
||||
_cairo_xlib_screen_list = NULL;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
|
||||
}
|
||||
|
||||
static cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get_unlocked (Display *dpy, Screen *screen)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_screen_info_t **prev;
|
||||
int event_base, error_base;
|
||||
XExtCodes *codes;
|
||||
cairo_bool_t seen_display = FALSE;
|
||||
|
||||
for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next)
|
||||
{
|
||||
if (info->display == dpy) {
|
||||
seen_display = TRUE;
|
||||
if (info->screen == screen || screen == NULL) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
if (prev != &_cairo_xlib_screen_list) {
|
||||
*prev = info->next;
|
||||
info->next = _cairo_xlib_screen_list;
|
||||
_cairo_xlib_screen_list = info;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info)
|
||||
return info;
|
||||
|
||||
if (screen == NULL)
|
||||
return NULL;
|
||||
|
||||
info = malloc (sizeof (cairo_xlib_screen_info_t));
|
||||
if (!info)
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
if (!seen_display) {
|
||||
codes = XAddExtension (dpy);
|
||||
if (!codes) {
|
||||
free (info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
|
||||
}
|
||||
|
||||
info->display = dpy;
|
||||
info->screen = screen;
|
||||
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
|
||||
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
|
||||
|
||||
info->close_display_hooks = NULL;
|
||||
|
||||
_cairo_xlib_init_screen_font_options (info);
|
||||
|
||||
info->next = _cairo_xlib_screen_list;
|
||||
_cairo_xlib_screen_list = info;
|
||||
assert (info->ref_count > 0);
|
||||
info->ref_count++;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
|
||||
if (info->gc[i] != NULL) {
|
||||
XFreeGC (info->display->display, info->gc[i]);
|
||||
info->gc[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
cairo_xlib_screen_info_t **prev;
|
||||
cairo_xlib_screen_info_t *list;
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
assert (info->ref_count > 0);
|
||||
if (--info->ref_count)
|
||||
return;
|
||||
|
||||
CAIRO_MUTEX_LOCK (info->display->mutex);
|
||||
for (prev = &info->display->screens; (list = *prev); prev = &list->next) {
|
||||
if (list == info) {
|
||||
*prev = info->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (info->display->mutex);
|
||||
|
||||
_cairo_xlib_screen_info_close_display (info);
|
||||
|
||||
_cairo_xlib_display_destroy (info->display);
|
||||
|
||||
free (info);
|
||||
}
|
||||
|
||||
cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_display_t *display;
|
||||
cairo_xlib_screen_info_t *info = NULL, **prev;
|
||||
|
||||
/* There is an apparent deadlock between this mutex and the
|
||||
* mutex for the display, but it's actually safe. For the
|
||||
* app to call XCloseDisplay() while any other thread is
|
||||
* inside this function would be an error in the logic
|
||||
* app, and the CloseDisplay hook is the only other place we
|
||||
* acquire this mutex.
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
display = _cairo_xlib_display_get (dpy);
|
||||
if (display == NULL)
|
||||
return NULL;
|
||||
|
||||
info = _cairo_xlib_screen_info_get_unlocked (dpy, screen);
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
if (display->closed) {
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, void *key)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_xlib_hook_t **prev;
|
||||
cairo_bool_t success = FALSE;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
|
||||
info = _cairo_xlib_screen_info_get_unlocked (dpy, NULL);
|
||||
if (!info)
|
||||
goto unlock;
|
||||
|
||||
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
|
||||
{
|
||||
if (hook->key == key) {
|
||||
for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
|
||||
if (info->screen == screen) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
if (prev != &info->close_display_hooks) {
|
||||
*prev = hook->next;
|
||||
hook->next = info->close_display_hooks;
|
||||
info->close_display_hooks = hook;
|
||||
if (prev != &display->screens) {
|
||||
*prev = info->next;
|
||||
info->next = display->screens;
|
||||
display->screens = info;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
if (!hook) {
|
||||
hook = malloc (sizeof (cairo_xlib_hook_t));
|
||||
if (!hook)
|
||||
goto unlock;
|
||||
hook->func = func;
|
||||
hook->data = data;
|
||||
hook->key = key;
|
||||
hook->next = info->close_display_hooks;
|
||||
info->close_display_hooks = hook;
|
||||
}
|
||||
if (info != NULL) {
|
||||
info = _cairo_xlib_screen_info_reference (info);
|
||||
} else {
|
||||
info = malloc (sizeof (cairo_xlib_screen_info_t));
|
||||
if (info != NULL) {
|
||||
info->ref_count = 2; /* Add one for display cache */
|
||||
info->display = _cairo_xlib_display_reference (display);
|
||||
info->screen = screen;
|
||||
info->has_render = FALSE;
|
||||
_cairo_font_options_init_default (&info->font_options);
|
||||
memset (info->gc, 0, sizeof (info->gc));
|
||||
info->gc_needs_clip_reset = 0;
|
||||
|
||||
success = TRUE;
|
||||
unlock:
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
return success;
|
||||
}
|
||||
if (screen) {
|
||||
int event_base, error_base;
|
||||
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
|
||||
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
|
||||
_cairo_xlib_init_screen_font_options (dpy, info);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_remove_close_display_hook (Display *dpy, void *key)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_xlib_hook_t **prev;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
|
||||
info = _cairo_xlib_screen_info_get_unlocked (dpy, NULL);
|
||||
if (!info)
|
||||
goto unlock;
|
||||
|
||||
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
|
||||
{
|
||||
if (hook->key == key) {
|
||||
*prev = hook->next;
|
||||
free (hook);
|
||||
break;
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
info->next = display->screens;
|
||||
display->screens = info;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
unlock:
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
DONE:
|
||||
_cairo_xlib_display_destroy (display);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_screen_reset_static_data (void)
|
||||
static int
|
||||
depth_to_index (int depth)
|
||||
{
|
||||
_cairo_xlib_screen_info_reset ();
|
||||
switch(depth){
|
||||
case 1: return 1;
|
||||
case 8: return 2;
|
||||
case 12: return 3;
|
||||
case 15: return 4;
|
||||
case 16: return 5;
|
||||
case 24: return 6;
|
||||
case 30: return 7;
|
||||
case 32: return 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GC
|
||||
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
|
||||
{
|
||||
GC gc;
|
||||
|
||||
depth = depth_to_index (depth);
|
||||
|
||||
gc = info->gc[depth];
|
||||
info->gc[depth] = NULL;
|
||||
|
||||
if (info->gc_needs_clip_reset & (1 << depth)) {
|
||||
XSetClipMask(info->display->display, gc, None);
|
||||
info->gc_needs_clip_reset &= ~(1 << depth);
|
||||
}
|
||||
|
||||
return gc;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
depth = depth_to_index (depth);
|
||||
|
||||
if (info->gc[depth] != NULL) {
|
||||
status = _cairo_xlib_display_queue_work (info->display,
|
||||
(cairo_xlib_notify_func) XFreeGC,
|
||||
info->gc[depth],
|
||||
NULL);
|
||||
}
|
||||
|
||||
info->gc[depth] = gc;
|
||||
if (reset_clip)
|
||||
info->gc_needs_clip_reset |= 1 << depth;
|
||||
else
|
||||
info->gc_needs_clip_reset &= ~(1 << depth);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/* Cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* 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 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_XLIB_SURFACE_PRIVATE_H
|
||||
#define CAIRO_XLIB_SURFACE_PRIVATE_H
|
||||
|
||||
#include "cairo-xlib.h"
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
|
||||
typedef struct _cairo_xlib_surface cairo_xlib_surface_t;
|
||||
|
||||
struct _cairo_xlib_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
Display *dpy;
|
||||
cairo_xlib_screen_info_t *screen_info;
|
||||
|
||||
GC gc;
|
||||
Drawable drawable;
|
||||
Screen *screen;
|
||||
cairo_bool_t owns_pixmap;
|
||||
Visual *visual;
|
||||
|
||||
int use_pixmap;
|
||||
|
||||
int render_major;
|
||||
int render_minor;
|
||||
|
||||
/* TRUE if the server has a bug with repeating pictures
|
||||
*
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=3566
|
||||
*
|
||||
* We can't test for this because it depends on whether the
|
||||
* picture is in video memory or not.
|
||||
*
|
||||
* We also use this variable as a guard against a second
|
||||
* independent bug with transformed repeating pictures:
|
||||
*
|
||||
* http://lists.freedesktop.org/archives/cairo/2004-September/001839.html
|
||||
*
|
||||
* Both are fixed in xorg >= 6.9 and hopefully in > 6.8.2, so
|
||||
* we can reuse the test for now.
|
||||
*/
|
||||
cairo_bool_t buggy_repeat;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
|
||||
Picture dst_picture, src_picture;
|
||||
|
||||
unsigned int clip_dirty;
|
||||
cairo_bool_t have_clip_rects;
|
||||
XRectangle embedded_clip_rects[4];
|
||||
XRectangle *clip_rects;
|
||||
int num_clip_rects;
|
||||
|
||||
XRenderPictFormat *xrender_format;
|
||||
cairo_filter_t filter;
|
||||
int repeat;
|
||||
XTransform xtransform;
|
||||
};
|
||||
|
||||
enum {
|
||||
CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC = 0x01,
|
||||
CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE = 0x02,
|
||||
CAIRO_XLIB_SURFACE_CLIP_DIRTY_ALL = 0x03
|
||||
};
|
||||
|
||||
#endif /* CAIRO_XLIB_SURFACE_PRIVATE_H */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -41,6 +41,7 @@
|
|||
|
||||
#if CAIRO_HAS_XLIB_SURFACE
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -895,7 +895,7 @@ typedef enum _cairo_subpixel_order {
|
|||
/**
|
||||
* cairo_hint_style_t:
|
||||
* @CAIRO_HINT_STYLE_DEFAULT: Use the default hint style for
|
||||
* for font backend and target device
|
||||
* font backend and target device
|
||||
* @CAIRO_HINT_STYLE_NONE: Do not hint outlines
|
||||
* @CAIRO_HINT_STYLE_SLIGHT: Hint outlines slightly to improve
|
||||
* contrast while retaining good fidelity to the original
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -16,5 +16,4 @@ BEGIN { state = "public"; }
|
|||
|
||||
# catch some one-off things
|
||||
END {
|
||||
print "#define _cairo_image_surface_nil_invalid_format __moz__cairo_image_surface_nil_invalid_format";
|
||||
}
|
||||
|
|
|
@ -51,10 +51,10 @@
|
|||
* there.
|
||||
*/
|
||||
|
||||
#include "test-fallback-surface.h"
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "test-fallback-surface.h"
|
||||
|
||||
typedef struct _test_fallback_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
|
@ -80,6 +80,7 @@ _cairo_test_fallback_surface_create (cairo_content_t content,
|
|||
|
||||
surface = malloc (sizeof (test_fallback_surface_t));
|
||||
if (surface == NULL) {
|
||||
cairo_surface_destroy (backing);
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
@ -169,6 +170,26 @@ _test_fallback_surface_release_dest_image (void *abstract_surface,
|
|||
image_extra);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_test_fallback_surface_clone_similar (void *abstract_surface,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int width,
|
||||
int height,
|
||||
cairo_surface_t **clone_out)
|
||||
{
|
||||
test_fallback_surface_t *surface = abstract_surface;
|
||||
|
||||
if (src->backend == surface->base.backend) {
|
||||
*clone_out = cairo_surface_reference (src);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_fallback_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int16_t *rectangle)
|
||||
|
@ -186,7 +207,7 @@ const cairo_surface_backend_t test_fallback_surface_backend = {
|
|||
_test_fallback_surface_release_source_image,
|
||||
_test_fallback_surface_acquire_dest_image,
|
||||
_test_fallback_surface_release_dest_image,
|
||||
NULL, /* clone_similar */
|
||||
_test_fallback_surface_clone_similar,
|
||||
NULL, /* composite */
|
||||
NULL, /* fill_rectangles */
|
||||
NULL, /* composite_trapezoids */
|
||||
|
|
|
@ -45,9 +45,10 @@
|
|||
* backend.
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "test-meta-surface.h"
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
|
||||
typedef struct _test_meta_surface {
|
||||
|
@ -143,11 +144,14 @@ static cairo_int_status_t
|
|||
_test_meta_surface_show_page (void *abstract_surface)
|
||||
{
|
||||
test_meta_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->image_reflects_meta)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_meta_surface_replay (surface->meta, surface->image);
|
||||
status = _cairo_meta_surface_replay (surface->meta, surface->image);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
surface->image_reflects_meta = TRUE;
|
||||
|
||||
|
@ -279,6 +283,7 @@ static cairo_surface_t *
|
|||
_test_meta_surface_snapshot (void *abstract_other)
|
||||
{
|
||||
test_meta_surface_t *other = abstract_other;
|
||||
cairo_status_t status;
|
||||
|
||||
/* XXX: Just making a snapshot of other->meta is what we really
|
||||
* want. But this currently triggers a bug somewhere (the "mask"
|
||||
|
@ -298,14 +303,20 @@ _test_meta_surface_snapshot (void *abstract_other)
|
|||
cairo_rectangle_int16_t extents;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
_cairo_surface_get_extents (other->image, &extents);
|
||||
status = _cairo_surface_get_extents (other->image, &extents);
|
||||
if (status)
|
||||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
|
||||
surface = cairo_surface_create_similar (other->image,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
extents.width,
|
||||
extents.height);
|
||||
|
||||
_cairo_meta_surface_replay (other->meta, surface);
|
||||
status = _cairo_meta_surface_replay (other->meta, surface);
|
||||
if (status) {
|
||||
cairo_surface_destroy (surface);
|
||||
surface = (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
return surface;
|
||||
#endif
|
||||
|
|
|
@ -45,11 +45,11 @@
|
|||
* backend.
|
||||
*/
|
||||
|
||||
#include "test-paginated-surface.h"
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-paginated-surface-private.h"
|
||||
#include "test-paginated-surface.h"
|
||||
|
||||
#include "cairo-paginated-private.h"
|
||||
|
||||
typedef struct _test_paginated_surface {
|
||||
cairo_surface_t base;
|
||||
|
|
|
@ -23,14 +23,11 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "pixmanint.h"
|
||||
|
||||
#include "pixman-xserver-compat.h"
|
||||
#include "fbpict.h"
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
#include "fbmmx.h"
|
||||
#endif /* MOZCAIRO */
|
||||
|
||||
#ifdef RENDER
|
||||
|
||||
|
@ -1744,7 +1741,7 @@ fbCombineSaturateU (CARD32 *dest, const CARD32 *src, int width)
|
|||
#define CombineXor (CombineAOut|CombineBOut)
|
||||
|
||||
/* portion covered by a but not b */
|
||||
static INLINE CARD8
|
||||
static inline CARD8
|
||||
fbCombineDisjointOutPart (CARD8 a, CARD8 b)
|
||||
{
|
||||
/* min (1, (1-b) / a) */
|
||||
|
@ -1756,7 +1753,7 @@ fbCombineDisjointOutPart (CARD8 a, CARD8 b)
|
|||
}
|
||||
|
||||
/* portion covered by both a and b */
|
||||
static INLINE CARD8
|
||||
static inline CARD8
|
||||
fbCombineDisjointInPart (CARD8 a, CARD8 b)
|
||||
{
|
||||
/* max (1-(1-b)/a,0) */
|
||||
|
@ -1884,7 +1881,7 @@ fbCombineDisjointXorU (CARD32 *dest, const CARD32 *src, int width)
|
|||
}
|
||||
|
||||
/* portion covered by a but not b */
|
||||
static INLINE CARD8
|
||||
static inline CARD8
|
||||
fbCombineConjointOutPart (CARD8 a, CARD8 b)
|
||||
{
|
||||
/* max (1-b/a,0) */
|
||||
|
@ -1898,7 +1895,7 @@ fbCombineConjointOutPart (CARD8 a, CARD8 b)
|
|||
}
|
||||
|
||||
/* portion covered by both a and b */
|
||||
static INLINE CARD8
|
||||
static inline CARD8
|
||||
fbCombineConjointInPart (CARD8 a, CARD8 b)
|
||||
{
|
||||
/* min (1,b/a) */
|
||||
|
@ -2059,89 +2056,80 @@ static CombineFuncU fbCombineFuncU[] = {
|
|||
fbCombineConjointXorU,
|
||||
};
|
||||
|
||||
static FASTCALL void
|
||||
fbCombineMaskC (CARD32 *src, CARD32 *mask, int width)
|
||||
static inline void
|
||||
fbCombineMaskC (CARD32 *src, CARD32 *mask)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 a = mask[i];
|
||||
CARD32 a = *mask;
|
||||
|
||||
CARD32 x;
|
||||
CARD16 xa;
|
||||
CARD32 x;
|
||||
CARD16 xa;
|
||||
|
||||
if (!a)
|
||||
{
|
||||
src[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
x = src[i];
|
||||
if (a == 0xffffffff)
|
||||
{
|
||||
x = x >> 24;
|
||||
x |= x << 8;
|
||||
x |= x << 16;
|
||||
mask[i] = x;
|
||||
continue;
|
||||
}
|
||||
|
||||
xa = x >> 24;
|
||||
FbByteMulC(x, a);
|
||||
src[i] = x;
|
||||
FbByteMul(a, xa);
|
||||
mask[i] = a;
|
||||
if (!a)
|
||||
{
|
||||
*src = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
x = *src;
|
||||
if (a == 0xffffffff)
|
||||
{
|
||||
x = x >> 24;
|
||||
x |= x << 8;
|
||||
x |= x << 16;
|
||||
*mask = x;
|
||||
return;
|
||||
}
|
||||
|
||||
xa = x >> 24;
|
||||
FbByteMulC(x, a);
|
||||
*src = x;
|
||||
FbByteMul(a, xa);
|
||||
*mask = a;
|
||||
}
|
||||
|
||||
static FASTCALL void
|
||||
fbCombineMaskValueC (CARD32 *src, const CARD32 *mask, int width)
|
||||
static inline void
|
||||
fbCombineMaskValueC (CARD32 *src, const CARD32 *mask)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 a = mask[i];
|
||||
CARD32 x;
|
||||
CARD32 a = *mask;
|
||||
CARD32 x;
|
||||
|
||||
if (!a)
|
||||
{
|
||||
src[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a == 0xffffffff)
|
||||
continue;
|
||||
|
||||
x = src[i];
|
||||
FbByteMulC(x, a);
|
||||
src[i] = x;
|
||||
if (!a)
|
||||
{
|
||||
*src = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (a == 0xffffffff)
|
||||
return;
|
||||
|
||||
x = *src;
|
||||
FbByteMulC(x, a);
|
||||
*src = x;
|
||||
}
|
||||
|
||||
static FASTCALL void
|
||||
fbCombineMaskAlphaC (const CARD32 *src, CARD32 *mask, int width)
|
||||
static inline void
|
||||
fbCombineMaskAlphaC (const CARD32 *src, CARD32 *mask)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 a = mask[i];
|
||||
CARD32 x;
|
||||
CARD32 a = *mask;
|
||||
CARD32 x;
|
||||
|
||||
if (!a)
|
||||
continue;
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
x = src[i] >> 24;
|
||||
if (x == 0xff)
|
||||
continue;
|
||||
if (a == 0xffffffff)
|
||||
{
|
||||
x = x >> 24;
|
||||
x |= x << 8;
|
||||
x |= x << 16;
|
||||
mask[i] = x;
|
||||
continue;
|
||||
}
|
||||
|
||||
FbByteMul(a, x);
|
||||
mask[i] = a;
|
||||
x = *src >> 24;
|
||||
if (x == 0xff)
|
||||
return;
|
||||
if (a == 0xffffffff)
|
||||
{
|
||||
x = x >> 24;
|
||||
x |= x << 8;
|
||||
x |= x << 16;
|
||||
*mask = x;
|
||||
return;
|
||||
}
|
||||
|
||||
FbByteMul(a, x);
|
||||
*mask = a;
|
||||
}
|
||||
|
||||
static FASTCALL void
|
||||
|
@ -2153,19 +2141,31 @@ fbCombineClearC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
|||
static FASTCALL void
|
||||
fbCombineSrcC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
fbCombineMaskValueC(src, mask, width);
|
||||
memcpy(dest, src, width*sizeof(CARD32));
|
||||
int i;
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 s = src[i];
|
||||
CARD32 m = mask[i];
|
||||
|
||||
fbCombineMaskValueC (&s, &m);
|
||||
|
||||
*dest = s;
|
||||
}
|
||||
}
|
||||
|
||||
static FASTCALL void
|
||||
fbCombineOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskC(src, mask, width);
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 s = src[i];
|
||||
CARD32 a = ~mask[i];
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 s = src[i];
|
||||
CARD32 m = mask[i];
|
||||
CARD32 a;
|
||||
|
||||
fbCombineMaskC (&s, &m);
|
||||
|
||||
a = ~m;
|
||||
if (a != 0xffffffff)
|
||||
{
|
||||
if (a)
|
||||
|
@ -2183,7 +2183,7 @@ static FASTCALL void
|
|||
fbCombineOverReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskValueC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 d = dest[i];
|
||||
CARD32 a = ~d >> 24;
|
||||
|
@ -2191,6 +2191,10 @@ fbCombineOverReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
|||
if (a)
|
||||
{
|
||||
CARD32 s = src[i];
|
||||
CARD32 m = mask[i];
|
||||
|
||||
fbCombineMaskValueC (&s, &m);
|
||||
|
||||
if (a != 0xff)
|
||||
{
|
||||
FbByteMulAdd(s, a, d);
|
||||
|
@ -2204,14 +2208,17 @@ static FASTCALL void
|
|||
fbCombineInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskValueC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 d = dest[i];
|
||||
CARD16 a = d >> 24;
|
||||
CARD32 s = 0;
|
||||
if (a)
|
||||
{
|
||||
s = src[i];
|
||||
CARD32 m = mask[i];
|
||||
|
||||
s = src[i];
|
||||
fbCombineMaskValueC (&s, &m);
|
||||
if (a != 0xff)
|
||||
{
|
||||
FbByteMul(s, a);
|
||||
|
@ -2225,10 +2232,15 @@ static FASTCALL void
|
|||
fbCombineInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskAlphaC(src, mask, width);
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 a = mask[i];
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 s = src[i];
|
||||
CARD32 m = mask[i];
|
||||
CARD32 a;
|
||||
|
||||
fbCombineMaskAlphaC (&s, &m);
|
||||
|
||||
a = m;
|
||||
if (a != 0xffffffff)
|
||||
{
|
||||
CARD32 d = 0;
|
||||
|
@ -2246,14 +2258,18 @@ static FASTCALL void
|
|||
fbCombineOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskValueC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 d = dest[i];
|
||||
CARD16 a = ~d >> 24;
|
||||
CARD32 s = 0;
|
||||
if (a)
|
||||
{
|
||||
s = src[i];
|
||||
CARD32 m = mask[i];
|
||||
|
||||
s = src[i];
|
||||
fbCombineMaskValueC (&s, &m);
|
||||
|
||||
if (a != 0xff)
|
||||
{
|
||||
FbByteMul(s, a);
|
||||
|
@ -2267,10 +2283,15 @@ static FASTCALL void
|
|||
fbCombineOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskAlphaC(src, mask, width);
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 a = ~mask[i];
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 s = src[i];
|
||||
CARD32 m = mask[i];
|
||||
CARD32 a;
|
||||
|
||||
fbCombineMaskAlphaC (&s, &m);
|
||||
|
||||
a = ~m;
|
||||
if (a != 0xffffffff)
|
||||
{
|
||||
CARD32 d = 0;
|
||||
|
@ -2288,12 +2309,18 @@ static FASTCALL void
|
|||
fbCombineAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 d = dest[i];
|
||||
CARD32 s = src[i];
|
||||
CARD32 ad = ~mask[i];
|
||||
CARD32 m = mask[i];
|
||||
CARD32 ad;
|
||||
CARD16 as = d >> 24;
|
||||
|
||||
fbCombineMaskC (&s, &m);
|
||||
|
||||
ad = ~m;
|
||||
|
||||
FbByteAddMulC(d, ad, s, as);
|
||||
dest[i] = d;
|
||||
}
|
||||
|
@ -2303,13 +2330,19 @@ static FASTCALL void
|
|||
fbCombineAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
|
||||
CARD32 d = dest[i];
|
||||
CARD32 s = src[i];
|
||||
CARD32 ad = mask[i];
|
||||
CARD32 m = mask[i];
|
||||
CARD32 ad;
|
||||
CARD16 as = ~d >> 24;
|
||||
|
||||
fbCombineMaskC (&s, &m);
|
||||
|
||||
ad = m;
|
||||
|
||||
FbByteAddMulC(d, ad, s, as);
|
||||
dest[i] = d;
|
||||
}
|
||||
|
@ -2319,12 +2352,18 @@ static FASTCALL void
|
|||
fbCombineXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 d = dest[i];
|
||||
CARD32 s = src[i];
|
||||
CARD32 ad = ~mask[i];
|
||||
CARD32 m = mask[i];
|
||||
CARD32 ad;
|
||||
CARD16 as = ~d >> 24;
|
||||
|
||||
fbCombineMaskC (&s, &m);
|
||||
|
||||
ad = ~m;
|
||||
|
||||
FbByteAddMulC(d, ad, s, as);
|
||||
dest[i] = d;
|
||||
}
|
||||
|
@ -2334,10 +2373,14 @@ static FASTCALL void
|
|||
fbCombineAddC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskValueC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 s = src[i];
|
||||
CARD32 m = mask[i];
|
||||
CARD32 d = dest[i];
|
||||
|
||||
fbCombineMaskValueC (&s, &m);
|
||||
|
||||
FbByteAdd(d, s);
|
||||
dest[i] = d;
|
||||
}
|
||||
|
@ -2347,7 +2390,7 @@ static FASTCALL void
|
|||
fbCombineSaturateC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 s, d;
|
||||
CARD16 sa, sr, sg, sb, da;
|
||||
|
@ -2356,10 +2399,14 @@ fbCombineSaturateC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
|
|||
|
||||
d = dest[i];
|
||||
s = src[i];
|
||||
sa = (mask[i] >> 24);
|
||||
sr = (mask[i] >> 16) & 0xff;
|
||||
sg = (mask[i] >> 8) & 0xff;
|
||||
sb = (mask[i] ) & 0xff;
|
||||
m = mask[i];
|
||||
|
||||
fbCombineMaskC (&s, &m);
|
||||
|
||||
sa = (m >> 24);
|
||||
sr = (m >> 16) & 0xff;
|
||||
sg = (m >> 8) & 0xff;
|
||||
sb = (m ) & 0xff;
|
||||
da = ~d >> 24;
|
||||
|
||||
if (sb <= da)
|
||||
|
@ -2390,7 +2437,7 @@ static FASTCALL void
|
|||
fbCombineDisjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, CARD8 combine)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 s, d;
|
||||
CARD32 m,n,o,p;
|
||||
|
@ -2400,10 +2447,14 @@ fbCombineDisjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, C
|
|||
CARD8 da;
|
||||
|
||||
s = src[i];
|
||||
sa = mask[i];
|
||||
m = mask[i];
|
||||
d = dest[i];
|
||||
da = d >> 24;
|
||||
|
||||
fbCombineMaskC (&s, &m);
|
||||
|
||||
sa = m;
|
||||
|
||||
switch (combine & CombineA) {
|
||||
default:
|
||||
Fa = 0;
|
||||
|
@ -2510,7 +2561,7 @@ static FASTCALL void
|
|||
fbCombineConjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, CARD8 combine)
|
||||
{
|
||||
int i;
|
||||
fbCombineMaskC(src, mask, width);
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
CARD32 s, d;
|
||||
CARD32 m,n,o,p;
|
||||
|
@ -2520,10 +2571,14 @@ fbCombineConjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, C
|
|||
CARD8 da;
|
||||
|
||||
s = src[i];
|
||||
sa = mask[i];
|
||||
m = mask[i];
|
||||
d = dest[i];
|
||||
da = d >> 24;
|
||||
|
||||
fbCombineMaskC (&s, &m);
|
||||
|
||||
sa = m;
|
||||
|
||||
switch (combine & CombineA) {
|
||||
default:
|
||||
Fa = 0;
|
||||
|
@ -3375,8 +3430,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
if (pict->filter == PIXMAN_FILTER_NEAREST || pict->filter == PIXMAN_FILTER_FAST)
|
||||
{
|
||||
if (pict->repeat == RepeatNormal) {
|
||||
if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) {
|
||||
box = pict->pSourceClip->extents;
|
||||
if (PIXREGION_NUM_RECTS(&pict->sourceClip) == 1) {
|
||||
box = pict->sourceClip.extents;
|
||||
for (i = 0; i < width; ++i) {
|
||||
if (!mask || mask[i] & maskBits)
|
||||
{
|
||||
|
@ -3411,7 +3466,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
y = MOD(v.vector[1]>>16, pict->pDrawable->height);
|
||||
x = MOD(v.vector[0]>>16, pict->pDrawable->width);
|
||||
}
|
||||
if (pixman_region_contains_point (pict->pSourceClip, x, y, &box))
|
||||
if (pixman_region_contains_point (&pict->sourceClip, x, y, &box))
|
||||
buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
|
||||
else
|
||||
buffer[i] = 0;
|
||||
|
@ -3423,8 +3478,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) {
|
||||
box = pict->pSourceClip->extents;
|
||||
if (PIXREGION_NUM_RECTS(&pict->sourceClip) == 1) {
|
||||
box = pict->sourceClip.extents;
|
||||
for (i = 0; i < width; ++i) {
|
||||
if (!mask || mask[i] & maskBits)
|
||||
{
|
||||
|
@ -3458,7 +3513,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
y = v.vector[1]>>16;
|
||||
x = v.vector[0]>>16;
|
||||
}
|
||||
if (pixman_region_contains_point (pict->pSourceClip, x, y, &box))
|
||||
if (pixman_region_contains_point (&pict->sourceClip, x, y, &box))
|
||||
buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed);
|
||||
else
|
||||
buffer[i] = 0;
|
||||
|
@ -3477,8 +3532,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
unit.vector[1] -= unit.vector[2]/2;
|
||||
|
||||
if (pict->repeat == RepeatNormal) {
|
||||
if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) {
|
||||
box = pict->pSourceClip->extents;
|
||||
if (PIXREGION_NUM_RECTS(&pict->sourceClip) == 1) {
|
||||
box = pict->sourceClip.extents;
|
||||
for (i = 0; i < width; ++i) {
|
||||
if (!mask || mask[i] & maskBits)
|
||||
{
|
||||
|
@ -3581,14 +3636,14 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
|
||||
b = bits + (y1 + pict->pDrawable->y)*stride;
|
||||
|
||||
tl = pixman_region_contains_point(pict->pSourceClip, x1, y1, &box)
|
||||
tl = pixman_region_contains_point(&pict->sourceClip, x1, y1, &box)
|
||||
? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
|
||||
tr = pixman_region_contains_point(pict->pSourceClip, x2, y1, &box)
|
||||
tr = pixman_region_contains_point(&pict->sourceClip, x2, y1, &box)
|
||||
? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
|
||||
b = bits + (y2 + pict->pDrawable->y)*stride;
|
||||
bl = pixman_region_contains_point(pict->pSourceClip, x1, y2, &box)
|
||||
bl = pixman_region_contains_point(&pict->sourceClip, x1, y2, &box)
|
||||
? fetch(b, x1 + pict->pDrawable->x, indexed) : 0;
|
||||
br = pixman_region_contains_point(pict->pSourceClip, x2, y2, &box)
|
||||
br = pixman_region_contains_point(&pict->sourceClip, x2, y2, &box)
|
||||
? fetch(b, x2 + pict->pDrawable->x, indexed) : 0;
|
||||
|
||||
ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
|
||||
|
@ -3612,8 +3667,8 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (PIXREGION_NUM_RECTS(pict->pSourceClip) == 1) {
|
||||
box = pict->pSourceClip->extents;
|
||||
if (PIXREGION_NUM_RECTS(&pict->sourceClip) == 1) {
|
||||
box = pict->sourceClip.extents;
|
||||
for (i = 0; i < width; ++i) {
|
||||
if (!mask || mask[i] & maskBits)
|
||||
{
|
||||
|
@ -3714,14 +3769,14 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
b = bits + (y1 + pict->pDrawable->y)*stride;
|
||||
x_off = x1 + pict->pDrawable->x;
|
||||
|
||||
tl = pixman_region_contains_point(pict->pSourceClip, x1, y1, &box)
|
||||
tl = pixman_region_contains_point(&pict->sourceClip, x1, y1, &box)
|
||||
? fetch(b, x_off, indexed) : 0;
|
||||
tr = pixman_region_contains_point(pict->pSourceClip, x2, y1, &box)
|
||||
tr = pixman_region_contains_point(&pict->sourceClip, x2, y1, &box)
|
||||
? fetch(b, x_off + 1, indexed) : 0;
|
||||
b += stride;
|
||||
bl = pixman_region_contains_point(pict->pSourceClip, x1, y2, &box)
|
||||
bl = pixman_region_contains_point(&pict->sourceClip, x1, y2, &box)
|
||||
? fetch(b, x_off, indexed) : 0;
|
||||
br = pixman_region_contains_point(pict->pSourceClip, x2, y2, &box)
|
||||
br = pixman_region_contains_point(&pict->sourceClip, x2, y2, &box)
|
||||
? fetch(b, x_off + 1, indexed) : 0;
|
||||
|
||||
ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
|
||||
|
@ -3783,7 +3838,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32
|
|||
for (x = x1; x < x2; x++) {
|
||||
if (*p) {
|
||||
int tx = (pict->repeat == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x;
|
||||
if (pixman_region_contains_point (pict->pSourceClip, tx, ty, &box)) {
|
||||
if (pixman_region_contains_point (&pict->sourceClip, tx, ty, &box)) {
|
||||
FbBits *b = bits + (ty + pict->pDrawable->y)*stride;
|
||||
CARD32 c = fetch(b, tx + pict->pDrawable->x, indexed);
|
||||
|
||||
|
@ -4038,26 +4093,6 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
|
|||
if (!compose)
|
||||
return;
|
||||
|
||||
#ifndef MOZILLA_CAIRO_NOT_DEFINED
|
||||
/* XXX: The non-MMX version of some of the fbCompose functions
|
||||
* overwrite the source or mask data (ones that use
|
||||
* fbCombineMaskC, fbCombineMaskAlphaC, or fbCombineMaskValueC
|
||||
* as helpers). This causes problems with the optimization in
|
||||
* this function that only fetches the source or mask once if
|
||||
* possible. If we're on a non-MMX machine, disable this
|
||||
* optimization as a bandaid fix.
|
||||
*
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=5777
|
||||
*/
|
||||
#ifdef USE_MMX
|
||||
if (!fbHaveMMX())
|
||||
#endif
|
||||
{
|
||||
srcClass = SourcePictClassUnknown;
|
||||
maskClass = SourcePictClassUnknown;
|
||||
}
|
||||
#endif /* MOZCAIRO */
|
||||
|
||||
for (i = 0; i < data->height; ++i) {
|
||||
/* fill first half of scanline with source */
|
||||
if (fetchSrc)
|
||||
|
@ -4219,7 +4254,7 @@ pixman_compositeGeneral (pixman_operator_t op,
|
|||
CARD16 width,
|
||||
CARD16 height)
|
||||
{
|
||||
pixman_region16_t *region;
|
||||
pixman_region16_t region;
|
||||
int n;
|
||||
BoxPtr pbox;
|
||||
Bool srcRepeat = FALSE;
|
||||
|
@ -4240,22 +4275,11 @@ pixman_compositeGeneral (pixman_operator_t op,
|
|||
if (op == PIXMAN_OPERATOR_OVER && !pMask && !pSrc->transform && !PICT_FORMAT_A(pSrc->format_code) && !pSrc->alphaMap)
|
||||
op = PIXMAN_OPERATOR_SRC;
|
||||
|
||||
region = pixman_region_create();
|
||||
pixman_region_union_rect (region, region, xDst, yDst, width, height);
|
||||
pixman_region_init_rect (®ion, xDst, yDst, width, height);
|
||||
|
||||
if (!FbComputeCompositeRegion (region,
|
||||
pSrc,
|
||||
pMask,
|
||||
pDst,
|
||||
xSrc,
|
||||
ySrc,
|
||||
xMask,
|
||||
yMask,
|
||||
xDst,
|
||||
yDst,
|
||||
width,
|
||||
height))
|
||||
return;
|
||||
if (!FbComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, ySrc,
|
||||
xMask, yMask, xDst, yDst, width, height))
|
||||
goto CLEANUP_REGION;
|
||||
|
||||
compose_data.op = op;
|
||||
compose_data.src = pSrc;
|
||||
|
@ -4264,8 +4288,8 @@ pixman_compositeGeneral (pixman_operator_t op,
|
|||
if (width > SCANLINE_BUFFER_LENGTH)
|
||||
scanline_buffer = (CARD32 *) malloc(width * 3 * sizeof(CARD32));
|
||||
|
||||
n = pixman_region_num_rects (region);
|
||||
pbox = pixman_region_rects (region);
|
||||
n = pixman_region_num_rects (®ion);
|
||||
pbox = pixman_region_rects (®ion);
|
||||
while (n--)
|
||||
{
|
||||
h = pbox->y2 - pbox->y1;
|
||||
|
@ -4319,10 +4343,12 @@ pixman_compositeGeneral (pixman_operator_t op,
|
|||
}
|
||||
pbox++;
|
||||
}
|
||||
pixman_region_destroy (region);
|
||||
|
||||
if (scanline_buffer != _scanline_buffer)
|
||||
free(scanline_buffer);
|
||||
|
||||
CLEANUP_REGION:
|
||||
pixman_region_fini (®ion);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "pixmanint.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "pixman-xserver-compat.h"
|
||||
|
||||
|
@ -77,14 +79,14 @@
|
|||
* 8 bit alpha
|
||||
*/
|
||||
|
||||
static INLINE CARD8
|
||||
static inline CARD8
|
||||
clip255 (int x)
|
||||
{
|
||||
if (x > 255) return 255;
|
||||
return x;
|
||||
}
|
||||
|
||||
static INLINE void
|
||||
static inline void
|
||||
add_saturate_8 (CARD8 *buf, int value, int length)
|
||||
{
|
||||
while (length--)
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
* Based on work by Owen Taylor
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "pixmanint.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "fbpict.h"
|
||||
|
@ -147,7 +145,8 @@ static const MMXData c =
|
|||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __inline__ __forceinline
|
||||
#undef inline
|
||||
#define inline __forceinline
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -162,7 +161,7 @@ static const MMXData c =
|
|||
*/
|
||||
#define M64(x) (*(__m64*)(void*)(&x))
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
shift (__m64 v, int s)
|
||||
{
|
||||
if (s > 0)
|
||||
|
@ -173,13 +172,13 @@ shift (__m64 v, int s)
|
|||
return v;
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
negate (__m64 mask)
|
||||
{
|
||||
return _mm_xor_si64 (mask, MC(4x00ff));
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
pix_multiply (__m64 a, __m64 b)
|
||||
{
|
||||
__m64 res;
|
||||
|
@ -192,7 +191,7 @@ pix_multiply (__m64 a, __m64 b)
|
|||
return res;
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
pix_add (__m64 a, __m64 b)
|
||||
{
|
||||
return _mm_adds_pu8 (a, b);
|
||||
|
@ -200,19 +199,19 @@ pix_add (__m64 a, __m64 b)
|
|||
|
||||
#ifdef USE_SSE
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
expand_alpha (__m64 pixel)
|
||||
{
|
||||
return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
expand_alpha_rev (__m64 pixel)
|
||||
{
|
||||
return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
invert_colors (__m64 pixel)
|
||||
{
|
||||
return _mm_shuffle_pi16 (pixel, _MM_SHUFFLE(3, 0, 1, 2));
|
||||
|
@ -220,7 +219,7 @@ invert_colors (__m64 pixel)
|
|||
|
||||
#else
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
expand_alpha (__m64 pixel)
|
||||
{
|
||||
__m64 t1, t2;
|
||||
|
@ -234,7 +233,7 @@ expand_alpha (__m64 pixel)
|
|||
return t1;
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
expand_alpha_rev (__m64 pixel)
|
||||
{
|
||||
__m64 t1, t2;
|
||||
|
@ -251,7 +250,7 @@ expand_alpha_rev (__m64 pixel)
|
|||
return t1;
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
invert_colors (__m64 pixel)
|
||||
{
|
||||
__m64 x, y, z;
|
||||
|
@ -273,13 +272,13 @@ invert_colors (__m64 pixel)
|
|||
|
||||
#endif
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
over (__m64 src, __m64 srca, __m64 dest)
|
||||
{
|
||||
return _mm_adds_pu8 (src, pix_multiply(dest, negate(srca)));
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
over_rev_non_pre (__m64 src, __m64 dest)
|
||||
{
|
||||
__m64 srca = expand_alpha (src);
|
||||
|
@ -288,7 +287,7 @@ over_rev_non_pre (__m64 src, __m64 dest)
|
|||
return over(pix_multiply(invert_colors(src), srcfaaa), srca, dest);
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
in (__m64 src,
|
||||
__m64 mask)
|
||||
{
|
||||
|
@ -296,7 +295,7 @@ in (__m64 src,
|
|||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
in_over (__m64 src,
|
||||
__m64 srca,
|
||||
__m64 mask,
|
||||
|
@ -308,19 +307,19 @@ in_over (__m64 src,
|
|||
#define in_over(src, srca, mask, dest) over(in(src, mask), pix_multiply(srca, mask), dest)
|
||||
#endif
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
load8888 (CARD32 v)
|
||||
{
|
||||
return _mm_unpacklo_pi8 (_mm_cvtsi32_si64 (v), _mm_setzero_si64());
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
pack8888 (__m64 lo, __m64 hi)
|
||||
{
|
||||
return _mm_packs_pu16 (lo, hi);
|
||||
}
|
||||
|
||||
static __inline__ CARD32
|
||||
static inline CARD32
|
||||
store8888 (__m64 v)
|
||||
{
|
||||
return _mm_cvtsi64_si32(pack8888(v, _mm_setzero_si64()));
|
||||
|
@ -340,7 +339,7 @@ store8888 (__m64 v)
|
|||
* Note the trick here - the top word is shifted by another nibble to
|
||||
* avoid it bumping into the middle word
|
||||
*/
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
expand565 (__m64 pixel, int pos)
|
||||
{
|
||||
__m64 p = pixel;
|
||||
|
@ -360,7 +359,7 @@ expand565 (__m64 pixel, int pos)
|
|||
return _mm_srli_pi16 (pixel, 8);
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
expand8888 (__m64 in, int pos)
|
||||
{
|
||||
if (pos == 0)
|
||||
|
@ -369,7 +368,7 @@ expand8888 (__m64 in, int pos)
|
|||
return _mm_unpackhi_pi8 (in, _mm_setzero_si64());
|
||||
}
|
||||
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
pack565 (__m64 pixel, __m64 target, int pos)
|
||||
{
|
||||
__m64 p = pixel;
|
||||
|
@ -400,7 +399,7 @@ pack565 (__m64 pixel, __m64 target, int pos)
|
|||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
static __inline__ __m64
|
||||
static inline __m64
|
||||
pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b)
|
||||
{
|
||||
x = _mm_mullo_pi16 (x, a);
|
||||
|
@ -1195,10 +1194,9 @@ fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op,
|
|||
{
|
||||
CARD32 *dstLine, *dst;
|
||||
CARD32 *srcLine, *src;
|
||||
CARD8 *maskLine;
|
||||
CARD32 mask;
|
||||
__m64 vmask;
|
||||
FbStride dstStride, srcStride, maskStride;
|
||||
FbStride dstStride, srcStride;
|
||||
CARD16 w;
|
||||
__m64 srca;
|
||||
|
||||
|
@ -1206,9 +1204,9 @@ fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op,
|
|||
|
||||
fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
|
||||
fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
|
||||
fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
|
||||
|
||||
mask = *maskLine << 24 | *maskLine << 16 | *maskLine << 8 | *maskLine;
|
||||
fbComposeGetSolid (pMask, pDst, mask);
|
||||
mask = mask | mask >> 8 | mask >> 16 | mask >> 24;
|
||||
vmask = load8888 (mask);
|
||||
srca = MC(4x00ff);
|
||||
|
||||
|
@ -1225,7 +1223,7 @@ fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op,
|
|||
__m64 s = load8888 (*src);
|
||||
__m64 d = load8888 (*dst);
|
||||
|
||||
*dst = store8888 (over (s, expand_alpha (s), d));
|
||||
*dst = store8888 (in_over (s, expand_alpha (s), vmask, d));
|
||||
|
||||
w--;
|
||||
dst++;
|
||||
|
@ -1234,8 +1232,8 @@ fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op,
|
|||
|
||||
while (w >= 2)
|
||||
{
|
||||
__m64 vs = *(__m64 *)dst;
|
||||
__m64 vd = *(__m64 *)src;
|
||||
__m64 vs = *(__m64 *)src;
|
||||
__m64 vd = *(__m64 *)dst;
|
||||
__m64 vsrc0 = expand8888 (vs, 0);
|
||||
__m64 vsrc1 = expand8888 (vs, 1);
|
||||
|
||||
|
@ -1280,10 +1278,9 @@ fbCompositeSrc_x888x8x8888mmx (pixman_operator_t op,
|
|||
{
|
||||
CARD32 *dstLine, *dst;
|
||||
CARD32 *srcLine, *src;
|
||||
CARD8 *maskLine;
|
||||
CARD32 mask;
|
||||
__m64 vmask;
|
||||
FbStride dstStride, srcStride, maskStride;
|
||||
FbStride dstStride, srcStride;
|
||||
CARD16 w;
|
||||
__m64 srca;
|
||||
|
||||
|
@ -1291,9 +1288,9 @@ fbCompositeSrc_x888x8x8888mmx (pixman_operator_t op,
|
|||
|
||||
fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
|
||||
fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
|
||||
fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
|
||||
fbComposeGetSolid (pMask, pDst, mask);
|
||||
|
||||
mask = *maskLine << 24 | *maskLine << 16 | *maskLine << 8 | *maskLine;
|
||||
mask = mask | mask >> 8 | mask >> 16 | mask >> 24;
|
||||
vmask = load8888 (mask);
|
||||
srca = MC(4x00ff);
|
||||
|
||||
|
@ -1657,6 +1654,102 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
|
|||
_mm_empty();
|
||||
}
|
||||
|
||||
static void
|
||||
fbSolidFillmmx (FbPixels *pDraw,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
FbBits xor)
|
||||
{
|
||||
FbStride stride;
|
||||
int bpp;
|
||||
ullong fill;
|
||||
__m64 vfill;
|
||||
CARD32 byte_width;
|
||||
CARD8 *byte_line;
|
||||
FbBits *bits;
|
||||
int xoff, yoff;
|
||||
|
||||
CHECKPOINT();
|
||||
|
||||
fbGetDrawable(pDraw, bits, stride, bpp, xoff, yoff);
|
||||
|
||||
assert (bpp == 32 || (xor >> 16 == (xor & 0xffff)));
|
||||
assert (bpp == 16 || bpp == 32);
|
||||
|
||||
if (bpp == 16)
|
||||
{
|
||||
stride = stride * sizeof (FbBits) / 2;
|
||||
byte_line = (CARD8 *)(((CARD16 *)bits) + stride * (y + yoff) + (x + xoff));
|
||||
byte_width = 2 * width;
|
||||
stride *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
stride = stride * sizeof (FbBits) / 4;
|
||||
byte_line = (CARD8 *)(((CARD32 *)bits) + stride * (y + yoff) + (x + xoff));
|
||||
byte_width = 4 * width;
|
||||
stride *= 4;
|
||||
}
|
||||
|
||||
fill = ((ullong)xor << 32) | xor;
|
||||
vfill = M64(fill);
|
||||
|
||||
while (height--)
|
||||
{
|
||||
unsigned int w;
|
||||
CARD8 *d = byte_line;
|
||||
byte_line += stride;
|
||||
w = byte_width;
|
||||
|
||||
while (w >= 2 && ((unsigned long)d & 3))
|
||||
{
|
||||
*(CARD16 *)d = xor;
|
||||
w -= 2;
|
||||
d += 2;
|
||||
}
|
||||
|
||||
while (w >= 4 && ((unsigned long)d & 7))
|
||||
{
|
||||
*(CARD32 *)d = xor;
|
||||
|
||||
w -= 4;
|
||||
d += 4;
|
||||
}
|
||||
|
||||
while (w >= 64)
|
||||
{
|
||||
*(__m64*) (d + 0) = vfill;
|
||||
*(__m64*) (d + 8) = vfill;
|
||||
*(__m64*) (d + 16) = vfill;
|
||||
*(__m64*) (d + 24) = vfill;
|
||||
*(__m64*) (d + 32) = vfill;
|
||||
*(__m64*) (d + 40) = vfill;
|
||||
*(__m64*) (d + 48) = vfill;
|
||||
*(__m64*) (d + 56) = vfill;
|
||||
|
||||
w -= 64;
|
||||
d += 64;
|
||||
}
|
||||
while (w >= 4)
|
||||
{
|
||||
*(CARD32 *)d = xor;
|
||||
|
||||
w -= 4;
|
||||
d += 4;
|
||||
}
|
||||
if (w >= 2)
|
||||
{
|
||||
*(CARD16 *)d = xor;
|
||||
w -= 2;
|
||||
d += 2;
|
||||
}
|
||||
}
|
||||
|
||||
_mm_empty();
|
||||
}
|
||||
|
||||
void
|
||||
fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
|
||||
PicturePtr pSrc,
|
||||
|
@ -1686,8 +1779,8 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
|
|||
srca = src >> 24;
|
||||
if (srca == 0)
|
||||
{
|
||||
if (fbSolidFillmmx (pDst->pDrawable, xDst, yDst, width, height, 0))
|
||||
return;
|
||||
fbSolidFillmmx (pDst->pDrawable, xDst, yDst, width, height, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
srcsrc = (ullong)src << 32 | src;
|
||||
|
@ -2591,107 +2684,7 @@ fbCompositeSrcAdd_8888x8888mmx (pixman_operator_t op,
|
|||
_mm_empty();
|
||||
}
|
||||
|
||||
Bool
|
||||
fbSolidFillmmx (FbPixels *pDraw,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
FbBits xor)
|
||||
{
|
||||
FbStride stride;
|
||||
int bpp;
|
||||
ullong fill;
|
||||
__m64 vfill;
|
||||
CARD32 byte_width;
|
||||
CARD8 *byte_line;
|
||||
FbBits *bits;
|
||||
int xoff, yoff;
|
||||
|
||||
CHECKPOINT();
|
||||
|
||||
fbGetDrawable(pDraw, bits, stride, bpp, xoff, yoff);
|
||||
|
||||
if (bpp == 16 && (xor >> 16 != (xor & 0xffff)))
|
||||
return FALSE;
|
||||
|
||||
if (bpp != 16 && bpp != 32)
|
||||
return FALSE;
|
||||
|
||||
if (bpp == 16)
|
||||
{
|
||||
stride = stride * sizeof (FbBits) / 2;
|
||||
byte_line = (CARD8 *)(((CARD16 *)bits) + stride * (y + yoff) + (x + xoff));
|
||||
byte_width = 2 * width;
|
||||
stride *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
stride = stride * sizeof (FbBits) / 4;
|
||||
byte_line = (CARD8 *)(((CARD32 *)bits) + stride * (y + yoff) + (x + xoff));
|
||||
byte_width = 4 * width;
|
||||
stride *= 4;
|
||||
}
|
||||
|
||||
fill = ((ullong)xor << 32) | xor;
|
||||
vfill = M64(fill);
|
||||
|
||||
while (height--)
|
||||
{
|
||||
unsigned int w;
|
||||
CARD8 *d = byte_line;
|
||||
byte_line += stride;
|
||||
w = byte_width;
|
||||
|
||||
while (w >= 2 && ((unsigned long)d & 3))
|
||||
{
|
||||
*(CARD16 *)d = xor;
|
||||
w -= 2;
|
||||
d += 2;
|
||||
}
|
||||
|
||||
while (w >= 4 && ((unsigned long)d & 7))
|
||||
{
|
||||
*(CARD32 *)d = xor;
|
||||
|
||||
w -= 4;
|
||||
d += 4;
|
||||
}
|
||||
|
||||
while (w >= 64)
|
||||
{
|
||||
*(__m64*) (d + 0) = vfill;
|
||||
*(__m64*) (d + 8) = vfill;
|
||||
*(__m64*) (d + 16) = vfill;
|
||||
*(__m64*) (d + 24) = vfill;
|
||||
*(__m64*) (d + 32) = vfill;
|
||||
*(__m64*) (d + 40) = vfill;
|
||||
*(__m64*) (d + 48) = vfill;
|
||||
*(__m64*) (d + 56) = vfill;
|
||||
|
||||
w -= 64;
|
||||
d += 64;
|
||||
}
|
||||
while (w >= 4)
|
||||
{
|
||||
*(CARD32 *)d = xor;
|
||||
|
||||
w -= 4;
|
||||
d += 4;
|
||||
}
|
||||
if (w >= 2)
|
||||
{
|
||||
*(CARD16 *)d = xor;
|
||||
w -= 2;
|
||||
d += 2;
|
||||
}
|
||||
}
|
||||
|
||||
_mm_empty();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
static void
|
||||
fbCopyAreammx (FbPixels *pSrc,
|
||||
FbPixels *pDst,
|
||||
int src_x,
|
||||
|
@ -2720,16 +2713,8 @@ fbCopyAreammx (FbPixels *pSrc,
|
|||
fbGetDrawable(pSrc, src_bits, src_stride, src_bpp, src_xoff, src_yoff);
|
||||
fbGetDrawable(pDst, dst_bits, dst_stride, dst_bpp, dst_xoff, dst_yoff);
|
||||
|
||||
if (src_bpp != 16 && src_bpp != 32)
|
||||
return FALSE;
|
||||
|
||||
if (dst_bpp != 16 && dst_bpp != 32)
|
||||
return FALSE;
|
||||
|
||||
if (src_bpp != dst_bpp)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
assert (src_bpp == dst_bpp);
|
||||
assert (src_bpp == 16 || src_bpp == 32);
|
||||
|
||||
if (src_bpp == 16)
|
||||
{
|
||||
|
@ -2810,7 +2795,6 @@ fbCopyAreammx (FbPixels *pSrc,
|
|||
}
|
||||
|
||||
_mm_empty();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче