b=383960: Upgrade cairo to 1.4.10: Cairo 1.4.10

This commit is contained in:
vladimir@pobox.com 2007-06-30 00:45:16 -07:00
Родитель 4f1e29c742
Коммит 7f76b858fe
124 изменённых файлов: 10556 добавлений и 5304 удалений

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

@ -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, &region);
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, &region) ==
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,
&region) ||
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 (&region);
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 (&region, xDst, yDst, width, height);
if (!FbComputeCompositeRegion (region,
pSrc,
pMask,
pDst,
xSrc,
ySrc,
xMask,
yMask,
xDst,
yDst,
width,
height))
return;
if (!FbComputeCompositeRegion (&region, 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 (&region);
pbox = pixman_region_rects (&region);
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 (&region);
}
#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

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше