backing out cairo update, again

This commit is contained in:
vladimir%pobox.com 2007-07-24 19:24:28 +00:00
Родитель eb55e7a193
Коммит ae59053b45
129 изменённых файлов: 6279 добавлений и 9882 удалений

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

@ -7,8 +7,7 @@ http://www.cairographics.org/.
VERSIONS:
cairo (1.5.x - c0a7d33ac6c81dd74ee2a9daaa3749a346ef4897)
pixman (0.9.3 - 0c80a0cd84f30616563cef5910df9deb4f8ed687)
cairo (1.4.2)
glitz 0.5.2 (cvs - 2006-01-10)
***** NOTE FOR VISUAL C++ 6.0 *****
@ -17,22 +16,18 @@ VC6 is not supported. Please upgrade to VC8.
==== Patches ====
All patches in the cairo tree are surrounded by "MOZILLA_CAIRO_NOT_DEFINED"
(which should obviously not be defined).
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
fbcompose-bandaid.patch: Disable "optimized" code in non-MMX case due to bugs
quartz-glyph-rounding.patch: Round glyph positions, not advances, to float
win32-scaled-font-size.patch: Add cairo_win32_font_face_create_for_logfontw_hfont,
allow win32 scaled_fonts to rescale themselves properly to the required CTM
and only use the font_face's hfont if we're sure it's appropriate
win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1
win32-no-printer-bitblt.patch: If we need to BitBlt from a DC (to do
fallback), only bother trying if the IS_DISPLAY flag is set -- many
printers lie about their support for BitBlt, and we end up getting
black instead of what we want.
nonfatal-assertions.patch: Make assertions non-fatal

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

@ -81,7 +81,7 @@ CSRCS = \
cairo-debug.c \
cairo-deflate-stream.c \
cairo-fixed.c \
cairo-font-face.c \
cairo-font.c \
cairo-font-options.c \
cairo-freelist.c \
cairo-gstate.c \
@ -91,7 +91,6 @@ 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 \
@ -166,8 +165,7 @@ endif
ifdef MOZ_X11
CSRCS += cairo-xlib-surface.c \
cairo-xlib-screen.c \
cairo-xlib-display.c
cairo-xlib-screen.c
EXPORTS += cairo-xlib.h cairo-xlib-xrender.h
endif
@ -198,7 +196,3 @@ DEFINES += -DPACKAGE_VERSION="\"moz\"" -DPACKAGE_BUGREPORT="\"http://bugzilla.mo
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
DEFINES += -DCAIRO_WIN32_STATIC_BUILD
endif
ifdef MOZ_TREE_CAIRO
DEFINES += -DMOZ_TREE_CAIRO
endif

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

@ -1,4 +1,5 @@
/*
/* $Id: cairo-analysis-surface-private.h,v 1.10 2007-07-24 19:24:27 vladimir%pobox.com Exp $
*
* Copyright © 2005 Keith Packard
*
* This library is free software; you can redistribute it and/or
@ -42,10 +43,10 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
int width,
int height);
cairo_private cairo_region_t *
cairo_private pixman_region16_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *surface);
cairo_private cairo_region_t *
cairo_private pixman_region16_t *
_cairo_analysis_surface_get_unsupported (cairo_surface_t *unsupported);
cairo_private cairo_bool_t

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

@ -35,7 +35,7 @@
#include "cairoint.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-paginated-private.h"
#include "cairo-paginated-surface-private.h"
typedef struct {
cairo_surface_t base;
@ -49,7 +49,7 @@ typedef struct {
static cairo_int_status_t
_cairo_analysis_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_analysis_surface_t *surface = abstract_surface;
@ -234,14 +234,14 @@ FAIL:
return NULL;
}
cairo_private cairo_region_t *
cairo_private pixman_region16_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
{
/* XXX */
return NULL;
}
cairo_private cairo_region_t *
cairo_private pixman_region16_t *
_cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface)
{
/* XXX */

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

@ -34,8 +34,6 @@
* 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:
@ -87,7 +85,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 = ARRAY_LENGTH (table);
int table_size = (sizeof (table) / sizeof (table[0]));
for (i = 0; i < table_size; i++)
if (table[i].error < tolerance)

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

@ -34,10 +34,11 @@
* Calum Robinson <calumr@mac.com>
*/
#include "cairoint.h"
#include "cairo.h"
#include <stdlib.h>
#include <math.h>
#include "cairo-atsui.h"
#include "cairoint.h"
#include "cairo.h"
#include "cairo-quartz-private.h"
/*
@ -116,7 +117,8 @@ _cairo_atsui_font_face_scaled_font_create (void *abstract_face,
ATSUStyle style;
err = ATSUCreateStyle (&style);
err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
err = ATSUSetAttributes(style,
sizeof(styleTags) / sizeof(styleTags[0]),
styleTags, styleSizes, styleValues);
return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
@ -129,19 +131,6 @@ 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)
{
@ -160,6 +149,14 @@ 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,
@ -235,13 +232,8 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
if (font == NULL)
return CAIRO_STATUS_NO_MEMORY;
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_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
&cairo_atsui_scaled_font_backend);
_cairo_matrix_compute_scale_factors (&font->base.scale,
&xscale, &yscale, 1);
@ -382,7 +374,8 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
ByteCount styleSizes[] =
{ sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
err = ATSUSetAttributes(style,
sizeof(styleTags) / sizeof(styleTags[0]),
styleTags, styleSizes, styleValues);
}
@ -404,6 +397,50 @@ _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);
@ -417,10 +454,16 @@ _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;
OSStatus err, callback_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,
@ -446,15 +489,41 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
extents.x_advance = metricsH.deviceAdvance.x * xscale;
extents.y_advance = 0;
extents.x_bearing = metricsH.topLeft.x * xscale;
extents.y_bearing = -metricsH.topLeft.y * yscale;
extents.width = metricsH.width * xscale;
extents.height = metricsH.height * yscale;
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;
_cairo_scaled_glyph_set_metrics (scaled_glyph,
&scaled_font->base,
&extents);
CGPathRelease (path);
return CAIRO_STATUS_SUCCESS;
}
@ -598,7 +667,6 @@ _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;
@ -615,10 +683,8 @@ _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);
status = cairo_surface_status ((cairo_surface_t *)surface);
if (status)
return status;
if (!surface)
return CAIRO_STATUS_NO_MEMORY;
_cairo_scaled_glyph_set_surface (scaled_glyph,
&base,
surface);
@ -626,25 +692,19 @@ _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
@ -683,9 +743,8 @@ _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);
status = cairo_surface_status ((cairo_surface_t *)surface);
if (status)
return status;
if (!surface)
return CAIRO_STATUS_NO_MEMORY;
/* Create a CGBitmapContext for the dest surface for drawing into */
{
@ -809,7 +868,7 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font,
*num_glyphs = glyphCount - 1;
*glyphs =
(cairo_glyph_t *) _cairo_malloc_ab(*num_glyphs, sizeof (cairo_glyph_t));
(cairo_glyph_t *) malloc(*num_glyphs * (sizeof (cairo_glyph_t)));
if (*glyphs == NULL) {
return CAIRO_STATUS_NO_MEMORY;
}

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

@ -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,7 +137,6 @@ 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)
@ -693,16 +692,13 @@ _cairo_bo_event_init (cairo_bo_event_t *event,
event->point = point;
}
static cairo_status_t
static void
_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. */
if (_cairo_skip_list_insert (&queue->intersection_queue, event,
event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) == NULL)
status = CAIRO_STATUS_NO_MEMORY;
return status;
_cairo_skip_list_insert (&queue->intersection_queue, event,
event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION);
}
static void
@ -754,14 +750,16 @@ _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 = _cairo_malloc_ab (num_events, sizeof (cairo_bo_event_t) + sizeof(cairo_bo_event_t*));
if (events == NULL)
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);
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 = num_events;
event_queue->num_startstop_events = (unsigned)(num_events);
event_queue->next_startstop_event_index = 0;
for (i = 0; i < num_edges; i++) {
@ -794,9 +792,11 @@ _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 cairo_status_t
static void
_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 CAIRO_STATUS_SUCCESS;
return;
/* 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 CAIRO_STATUS_SUCCESS;
return;
status = _cairo_bo_edge_intersect (left, right, &intersection);
if (status == CAIRO_BO_STATUS_PARALLEL ||
status == CAIRO_BO_STATUS_NO_INTERSECTION)
{
return CAIRO_STATUS_SUCCESS;
return;
}
_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);
return _cairo_bo_event_queue_insert (event_queue, &event);
_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 cairo_status_t
static void
_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
cairo_bo_edge_t *edge)
{
@ -858,8 +858,6 @@ _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)
@ -878,8 +876,6 @@ _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
@ -1061,6 +1057,7 @@ _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;
@ -1102,11 +1099,11 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
left_bot.x != right_bot.x ||
left_bot.y != right_bot.y)
{
_cairo_traps_add_trap_from_points (bo_traps->traps,
fixed_top,
fixed_bot,
left_top, left_bot,
right_top, right_bot);
status = _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) "
@ -1120,8 +1117,7 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
_cairo_freelist_free (&bo_traps->freelist, trap);
left->deferred_trap = NULL;
return _cairo_traps_status (bo_traps->traps);
return status;
}
/* Start a new trapezoid at the given top y coordinate, whose edges
@ -1258,7 +1254,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_t status = CAIRO_STATUS_SUCCESS;
int intersection_count = 0;
cairo_bo_event_queue_t event_queue;
cairo_bo_sweep_line_t sweep_line;
@ -1268,10 +1264,7 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
cairo_bo_edge_t *left, *right;
cairo_bo_edge_t *edge1, *edge2;
status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
if (status)
return status;
_cairo_bo_event_queue_init (&event_queue, edges, num_edges);
_cairo_bo_sweep_line_init (&sweep_line);
_cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
@ -1303,9 +1296,7 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
case CAIRO_BO_EVENT_TYPE_START:
edge = event->e1;
status = _cairo_bo_sweep_line_insert (&sweep_line, edge);
if (status)
goto unwind;
_cairo_bo_sweep_line_insert (&sweep_line, edge);
/* Cache the insert position for use in pass 2.
event->e2 = Sortlist::prev (sweep_line, edge);
*/
@ -1313,13 +1304,9 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
left = edge->prev;
right = edge->next;
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, left, edge);
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
if (status)
goto unwind;
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
#if DEBUG_PRINT_STATE
print_state ("After processing start", &event_queue, &sweep_line);
@ -1339,9 +1326,7 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
if (status)
goto unwind;
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
if (status)
goto unwind;
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
#if DEBUG_PRINT_STATE
print_state ("After processing stop", &event_queue, &sweep_line);
@ -1369,15 +1354,11 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
/* after the swap e2 is left of e1 */
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
left, edge2);
if (status)
goto unwind;
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
_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);
@ -1421,7 +1402,6 @@ _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;
@ -1433,13 +1413,9 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
if (0 == polygon->num_edges)
return CAIRO_STATUS_SUCCESS;
if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
edges = stack_edges;
} else {
edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t));
if (edges == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
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. */
@ -1519,8 +1495,7 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
xmin, ymin, xmax, ymax,
&intersections);
if (edges != stack_edges)
free (edges);
free (edges);
return status;
}
@ -1757,7 +1732,7 @@ run_test (const char *test_name,
while (intersections) {
int num_edges = _cairo_array_num_elements (&intersected_edges);
passes++;
edges = _cairo_malloc_ab (num_edges, sizeof (cairo_bo_edge_t));
edges = malloc (num_edges * sizeof (cairo_bo_edge_t));
assert (edges != NULL);
memcpy (edges, _cairo_array_index (&intersected_edges, 0), num_edges * sizeof (cairo_bo_edge_t));
_cairo_array_fini (&intersected_edges);
@ -1796,7 +1771,7 @@ main (void)
unsigned int i, num_random;
test_t *test;
for (i = 0; i < ARRAY_LENGTH (tests); i++) {
for (i = 0; i < sizeof (tests) / sizeof (tests[0]); 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
#include "cairo-types-private.h"
typedef struct _cairo_cache cairo_cache_t;
/**
* cairo_cache_entry_t:

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

@ -38,6 +38,17 @@
#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 const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
extern cairo_private const cairo_rectangle_list_t _cairo_rectangles_nil;
struct _cairo_clip_path {
unsigned int ref_count;
@ -63,7 +63,7 @@ struct _cairo_clip {
* clip paths
*/
cairo_surface_t *surface;
cairo_rectangle_int_t surface_rect;
cairo_rectangle_int16_t surface_rect;
/*
* Surface clip serial number to store
* in the surface when this clip is set
@ -72,8 +72,7 @@ struct _cairo_clip {
/*
* A clip region that can be placed in the surface
*/
cairo_region_t region;
cairo_bool_t has_region;
pixman_region16_t *region;
/*
* If the surface supports path clipping, we store the list of
* clipping paths that has been set here as a linked list.
@ -84,15 +83,18 @@ struct _cairo_clip {
cairo_private void
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target);
cairo_private cairo_status_t
cairo_private void
_cairo_clip_fini (cairo_clip_t *clip);
cairo_private void
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
cairo_private cairo_status_t
cairo_private void
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
cairo_clip_t *other,
cairo_surface_t *target);
cairo_private void
cairo_private cairo_status_t
_cairo_clip_reset (cairo_clip_t *clip);
cairo_private cairo_status_t
@ -105,11 +107,11 @@ _cairo_clip_clip (cairo_clip_t *clip,
cairo_private cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_rectangle_int_t *rectangle);
cairo_rectangle_int16_t *rectangle);
cairo_private cairo_status_t
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
cairo_region_t *region);
pixman_region16_t *region);
cairo_private cairo_status_t
_cairo_clip_combine_to_surface (cairo_clip_t *clip,
@ -117,7 +119,7 @@ _cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int_t *extents);
const cairo_rectangle_int16_t *extents);
cairo_private void
_cairo_clip_translate (cairo_clip_t *clip,

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

@ -1,4 +1,3 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
@ -62,13 +61,28 @@ _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
clip->serial = 0;
_cairo_region_init (&clip->region);
clip->has_region = FALSE;
clip->region = NULL;
clip->path = NULL;
}
cairo_status_t
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_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
{
clip->mode = other->mode;
@ -78,27 +92,17 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
clip->serial = other->serial;
_cairo_region_init (&clip->region);
if (other->has_region) {
if (_cairo_region_copy (&clip->region, &other->region) !=
CAIRO_STATUS_SUCCESS)
{
_cairo_region_fini (&clip->region);
cairo_surface_destroy (clip->surface);
return CAIRO_STATUS_NO_MEMORY;
}
clip->has_region = TRUE;
if (other->region == NULL) {
clip->region = other->region;
} else {
clip->has_region = FALSE;
clip->region = pixman_region_create ();
pixman_region_copy (clip->region, other->region);
}
clip->path = _cairo_clip_path_reference (other->path);
return CAIRO_STATUS_SUCCESS;
}
void
cairo_status_t
_cairo_clip_reset (cairo_clip_t *clip)
{
/* destroy any existing clip-region artifacts */
@ -107,29 +111,25 @@ _cairo_clip_reset (cairo_clip_t *clip)
clip->serial = 0;
if (clip->has_region) {
/* _cairo_region_fini just releases the resources used but
* doesn't bother with leaving the region in a valid state.
* So _cairo_region_init has to be called afterwards. */
_cairo_region_fini (&clip->region);
_cairo_region_init (&clip->region);
clip->has_region = FALSE;
}
if (clip->region)
pixman_region_destroy (clip->region);
clip->region = NULL;
_cairo_clip_path_destroy (clip->path);
clip->path = NULL;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
while (clip_path) {
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t extents;
cairo_rectangle_int_t extents_rect;
cairo_rectangle_int16_t extents_rect;
_cairo_traps_init (&traps);
@ -156,7 +156,7 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
if (!clip)
return CAIRO_STATUS_SUCCESS;
@ -170,22 +170,27 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
return status;
}
if (clip->has_region) {
if (clip->region) {
pixman_region16_t *intersection;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_region_t intersection;
pixman_region_status_t pixman_status;
_cairo_region_init_rect (&intersection, rectangle);
intersection = _cairo_region_create_from_rectangle (rectangle);
if (intersection == NULL)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_region_intersect (&intersection, &clip->region,
&intersection);
pixman_status = pixman_region_intersect (intersection,
clip->region,
intersection);
if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS)
_cairo_region_extents_rectangle (intersection, rectangle);
else
status = CAIRO_STATUS_NO_MEMORY;
if (!status)
_cairo_region_get_extents (&intersection, rectangle);
pixman_region_destroy (intersection);
_cairo_region_fini (&intersection);
if (status)
return status;
if (status)
return status;
}
if (clip->surface)
@ -196,10 +201,8 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_status_t
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
cairo_region_t *region)
pixman_region16_t *region)
{
cairo_status_t status;
if (!clip)
return CAIRO_STATUS_SUCCESS;
@ -207,23 +210,28 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
/* Intersect clip path into region. */
}
if (clip->has_region) {
status = _cairo_region_intersect (region, &clip->region, region);
if (status)
return status;
}
if (clip->region)
pixman_region_intersect (region, clip->region, region);
if (clip->surface) {
cairo_region_t clip_rect;
pixman_region16_t *clip_rect;
pixman_region_status_t pixman_status;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
_cairo_region_init_rect (&clip_rect, &clip->surface_rect);
clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
if (clip_rect == NULL)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_region_intersect (region, &clip_rect, region);
pixman_status = pixman_region_intersect (region,
clip_rect,
region);
if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
status = CAIRO_STATUS_NO_MEMORY;
_cairo_region_fini (&clip_rect);
pixman_region_destroy (clip_rect);
if (status)
return status;
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
@ -239,7 +247,7 @@ _cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int_t *extents)
const cairo_rectangle_int16_t *extents)
{
cairo_pattern_union_t pattern;
cairo_status_t status;
@ -321,44 +329,42 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
free (clip_path);
}
static cairo_int_status_t
static cairo_status_t
_cairo_clip_intersect_region (cairo_clip_t *clip,
cairo_traps_t *traps,
cairo_surface_t *target)
{
cairo_region_t region;
cairo_int_status_t status;
pixman_region16_t *region;
cairo_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->has_region) {
status = _cairo_region_copy (&clip->region, &region);
if (status == CAIRO_STATUS_SUCCESS)
clip->has_region = TRUE;
if (clip->region == NULL) {
clip->region = region;
} else {
cairo_region_t intersection;
_cairo_region_init (&intersection);
pixman_region16_t *intersection = pixman_region_create();
status = _cairo_region_intersect (&intersection,
&clip->region,
&region);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_region_copy (&clip->region, &intersection);
_cairo_region_fini (&intersection);
if (pixman_region_intersect (intersection,
clip->region, region)
== PIXMAN_REGION_STATUS_SUCCESS) {
pixman_region_destroy (clip->region);
clip->region = intersection;
} else {
status = CAIRO_STATUS_NO_MEMORY;
}
pixman_region_destroy (region);
}
clip->serial = _cairo_surface_allocate_clip_serial (target);
_cairo_region_fini (&region);
return status;
}
@ -371,7 +377,7 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
{
cairo_pattern_union_t pattern;
cairo_box_t extents;
cairo_rectangle_int_t surface_rect, target_rect;
cairo_rectangle_int16_t surface_rect, target_rect;
cairo_surface_t *surface;
cairo_status_t status;
@ -396,16 +402,14 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
CAIRO_CONTENT_ALPHA,
surface_rect.width,
surface_rect.height,
CAIRO_COLOR_WHITE,
NULL);
CAIRO_COLOR_WHITE);
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_CONTENT_COLOR);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
&pattern.base,
@ -505,8 +509,8 @@ _cairo_clip_translate (cairo_clip_t *clip,
cairo_fixed_t tx,
cairo_fixed_t ty)
{
if (clip->has_region) {
_cairo_region_translate (&clip->region,
if (clip->region) {
pixman_region_translate (clip->region,
_cairo_fixed_integer_part (tx),
_cairo_fixed_integer_part (ty));
}
@ -545,7 +549,7 @@ _cairo_clip_path_reapply_clip_path (cairo_clip_t *clip,
clip_path->antialias);
}
cairo_status_t
void
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
cairo_clip_t *other,
cairo_surface_t *target)
@ -556,22 +560,18 @@ _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->has_region) {
if (_cairo_region_copy (&clip->region, &other->region) !=
CAIRO_STATUS_SUCCESS)
goto BAIL;
clip->has_region = TRUE;
if (other->region) {
clip->region = pixman_region_create ();
pixman_region_copy (clip->region, other->region);
}
if (other->surface) {
if (_cairo_surface_clone_similar (target, other->surface,
_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) !=
CAIRO_STATUS_SUCCESS)
goto BAIL;
&clip->surface);
clip->surface_rect = other->surface_rect;
}
@ -579,16 +579,6 @@ _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)
_cairo_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 =
@ -597,24 +587,19 @@ static const cairo_rectangle_list_t _cairo_rectangles_not_representable =
{ CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, NULL, 0 };
static cairo_bool_t
_cairo_clip_int_rect_to_user (cairo_gstate_t *gstate,
cairo_rectangle_int_t *clip_rect,
cairo_rectangle_t *user_rect)
_cairo_clip_rect_to_user (cairo_gstate_t *gstate,
double x, double y, double width, double height,
cairo_rectangle_t *rectangle)
{
double x2 = x + width;
double y2 = y + height;
cairo_bool_t is_tight;
double x1 = clip_rect->x;
double y1 = clip_rect->y;
double x2 = clip_rect->x + clip_rect->width;
double y2 = clip_rect->y + clip_rect->height;
_cairo_gstate_backend_to_user_rectangle (gstate, &x1, &y1, &x2, &y2, &is_tight);
user_rect->x = x1;
user_rect->y = y1;
user_rect->width = x2 - x1;
user_rect->height = y2 - y1;
_cairo_gstate_backend_to_user_rectangle (gstate, &x, &y, &x2, &y2, &is_tight);
rectangle->x = x;
rectangle->y = y;
rectangle->width = x2 - x;
rectangle->height = y2 - y;
return is_tight;
}
@ -622,51 +607,42 @@ cairo_private cairo_rectangle_list_t*
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
{
cairo_rectangle_list_t *list;
cairo_rectangle_t *rectangles = NULL;
cairo_rectangle_t *rectangles;
int n_boxes;
if (clip->path || clip->surface)
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
if (clip->has_region) {
cairo_box_int_t *boxes;
n_boxes = clip->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) {
pixman_box16_t *boxes;
int i;
if (_cairo_region_get_boxes (&clip->region, &n_boxes, &boxes) != CAIRO_STATUS_SUCCESS)
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t));
if (rectangles == NULL) {
_cairo_region_boxes_fini (&clip->region, boxes);
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
}
boxes = pixman_region_rects (clip->region);
for (i = 0; i < n_boxes; ++i) {
cairo_rectangle_int_t clip_rect = { boxes[i].p1.x, boxes[i].p1.y,
boxes[i].p2.x - boxes[i].p1.x,
boxes[i].p2.y - boxes[i].p1.y };
if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) {
_cairo_region_boxes_fini (&clip->region, boxes);
free (rectangles);
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
}
if (!_cairo_clip_rect_to_user(gstate, boxes[i].x1, boxes[i].y1,
boxes[i].x2 - boxes[i].x1,
boxes[i].y2 - boxes[i].y1,
&rectangles[i])) {
free (rectangles);
return (cairo_rectangle_list_t*)
&_cairo_rectangles_not_representable;
}
}
} else {
cairo_rectangle_int_t extents;
n_boxes = 1;
rectangles = malloc(sizeof (cairo_rectangle_t));
if (rectangles == NULL)
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
if (_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents) ||
!_cairo_clip_int_rect_to_user(gstate, &extents, rectangles))
{
free (rectangles);
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
}
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)) {
free (rectangles);
return (cairo_rectangle_list_t*)
&_cairo_rectangles_not_representable;
}
}
list = malloc (sizeof (cairo_rectangle_list_t));

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

@ -160,13 +160,3 @@ _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,11 +59,13 @@
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,10 +130,8 @@ _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) {
free (stream);
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
}
if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
stream->zlib_stream.next_in = stream->input_buf;
stream->zlib_stream.avail_in = 0;

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

@ -35,9 +35,10 @@
* Claudio Ciccani <klan@users.sf.net>
*/
#include "cairoint.h"
#include "cairo-directfb.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <directfb.h>
@ -46,6 +47,9 @@
#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).
@ -320,9 +324,9 @@ _directfb_buffer_surface_create (IDirectFB *dfb,
static cairo_status_t
_directfb_acquire_surface (cairo_directfb_surface_t *surface,
cairo_rectangle_int_t *intrest_rec,
cairo_rectangle_int16_t *intrest_rec,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect_out,
cairo_rectangle_int16_t *image_rect_out,
void **image_extra,
DFBSurfaceLockFlags lock_flags)
{
@ -333,7 +337,7 @@ _directfb_acquire_surface (cairo_directfb_surface_t *surface,
cairo_format_t cairo_format;
cairo_format = surface->format;
if (surface->format == (cairo_format_t) -1) {
if (surface->format == -1) {
if( intrest_rec ) {
source_rect.x = intrest_rec->x;
source_rect.y = intrest_rec->y;
@ -499,9 +503,9 @@ _cairo_directfb_surface_release_source_image (void *abstract_su
static cairo_status_t
_cairo_directfb_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect_out,
cairo_rectangle_int16_t *image_rect_out,
void **image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
@ -515,9 +519,9 @@ _cairo_directfb_surface_acquire_dest_image (void *abstract_sur
static void
_cairo_directfb_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
@ -911,7 +915,7 @@ static cairo_int_status_t
_cairo_directfb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int_t *rects,
cairo_rectangle_int16_t *rects,
int n_rects)
{
cairo_directfb_surface_t *dst = abstract_surface;
@ -1095,8 +1099,8 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
#endif /* DFB_COMPOSITE_TRAPEZOIDS */
static cairo_int_status_t
_cairo_directfb_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
_cairo_directfb_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
cairo_directfb_surface_t *surface = abstract_surface;
@ -1105,19 +1109,16 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface,
__FUNCTION__, surface, region);
if (region) {
cairo_box_int_t *boxes;
int n_boxes, i;
if (_cairo_region_get_boxes (region, &n_boxes, &boxes) != CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_NO_MEMORY;
pixman_box16_t *boxes = pixman_region_rects (region);
int n_boxes = pixman_region_num_rects (region);
int i;
if (surface->n_clips != n_boxes) {
if( surface->clips )
free (surface->clips);
surface->clips = _cairo_malloc_ab (n_boxes, sizeof(DFBRegion));
surface->clips = malloc (n_boxes * sizeof(DFBRegion));
if (!surface->clips) {
_cairo_region_boxes_fini (region, boxes);
surface->n_clips = 0;
return CAIRO_STATUS_NO_MEMORY;
}
@ -1126,13 +1127,11 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface,
}
for (i = 0; i < n_boxes; i++) {
surface->clips[i].x1 = boxes[i].p1.x;
surface->clips[i].y1 = boxes[i].p1.y;
surface->clips[i].x2 = boxes[i].p2.x;
surface->clips[i].y2 = boxes[i].p2.y;
surface->clips[i].x1 = boxes[i].x1;
surface->clips[i].y1 = boxes[i].y1;
surface->clips[i].x2 = boxes[i].x2;
surface->clips[i].y2 = boxes[i].y2;
}
_cairo_region_boxes_fini (region, boxes);
}
else {
if (surface->clips) {
@ -1147,7 +1146,7 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface,
static cairo_int_status_t
_cairo_directfb_abstract_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_directfb_surface_t *surface = abstract_surface;
@ -1516,17 +1515,6 @@ _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*/
@ -1576,9 +1564,7 @@ static cairo_surface_backend_t cairo_directfb_surface_backend = {
#else
NULL, /* show_glyphs */
#endif
NULL, /* snapshot */
_cairo_directfb_surface_is_similar,
NULL /* reset */
NULL /* snapshot */
};

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

@ -41,8 +41,6 @@
#ifdef CAIRO_HAS_DIRECTFB_SURFACE
#include <directfb.h>
CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *

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

@ -52,10 +52,10 @@
#endif
#define CAIRO_VERSION_MAJOR 1
#define CAIRO_VERSION_MINOR 5
#define CAIRO_VERSION_MICRO 1
#define CAIRO_VERSION_MINOR 4
#define CAIRO_VERSION_MICRO 2
#define CAIRO_VERSION_STRING "1.5.1"
#define CAIRO_VERSION_STRING "1.4.2"
@PS_SURFACE_FEATURE@
@ -65,8 +65,6 @@
@XLIB_SURFACE_FEATURE@
@XLIB_XRENDER_SURFACE_FEATURE@
@QUARTZ_SURFACE_FEATURE@
@XCB_SURFACE_FEATURE@

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

@ -36,4 +36,102 @@
#include "cairoint.h"
#include "cairo-fixed-private.h"
cairo_fixed_t
_cairo_fixed_from_int (int i)
{
return i << 16;
}
/* This is the "magic number" approach to converting a double into fixed
* point as described here:
*
* http://www.stereopsis.com/sree/fpu2006.html (an overview)
* http://www.d6.com/users/checker/pdfs/gdmfp.pdf (in detail)
*
* The basic idea is to add a large enough number to the double that the
* literal floating point is moved up to the extent that it forces the
* double's value to be shifted down to the bottom of the mantissa (to make
* room for the large number being added in). Since the mantissa is, at a
* given moment in time, a fixed point integer itself, one can convert a
* float to various fixed point representations by moving around the point
* of a floating point number through arithmetic operations. This behavior
* is reliable on most modern platforms as it is mandated by the IEEE-754
* standard for floating point arithmetic.
*
* For our purposes, a "magic number" must be carefully selected that is
* both large enough to produce the desired point-shifting effect, and also
* has no lower bits in its representation that would interfere with our
* value at the bottom of the mantissa. The magic number is calculated as
* follows:
*
* (2 ^ (MANTISSA_SIZE - FRACTIONAL_SIZE)) * 1.5
*
* where in our case:
* - MANTISSA_SIZE for 64-bit doubles is 52
* - FRACTIONAL_SIZE for 16.16 fixed point is 16
*
* Although this approach provides a very large speedup of this function
* on a wide-array of systems, it does come with two caveats:
*
* 1) It uses banker's rounding as opposed to arithmetic rounding.
* 2) It doesn't function properly if the FPU is in single-precision
* mode.
*/
#define CAIRO_MAGIC_NUMBER_FIXED_16_16 (103079215104.0)
cairo_fixed_t
_cairo_fixed_from_double (double d)
{
union {
double d;
int32_t i[2];
} u;
u.d = d + CAIRO_MAGIC_NUMBER_FIXED_16_16;
#ifdef FLOAT_WORDS_BIGENDIAN
return u.i[1];
#else
return u.i[0];
#endif
}
cairo_fixed_t
_cairo_fixed_from_26_6 (uint32_t i)
{
return i << 10;
}
double
_cairo_fixed_to_double (cairo_fixed_t f)
{
return ((double) f) / 65536.0;
}
int
_cairo_fixed_is_integer (cairo_fixed_t f)
{
return (f & 0xFFFF) == 0;
}
int
_cairo_fixed_integer_part (cairo_fixed_t f)
{
return f >> 16;
}
int
_cairo_fixed_integer_floor (cairo_fixed_t f)
{
if (f >= 0)
return f >> 16;
else
return -((-f - 1) >> 16) - 1;
}
int
_cairo_fixed_integer_ceil (cairo_fixed_t f)
{
if (f > 0)
return ((f - 1)>>16) + 1;
else
return - (-f >> 16);
}

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

@ -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,14 +113,10 @@ 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;
cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
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);
@ -137,7 +133,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);
@ -156,12 +152,11 @@ 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:
@ -177,7 +172,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)
@ -245,7 +240,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;
@ -281,7 +276,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;
@ -317,7 +312,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;
@ -353,7 +348,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,6 +26,8 @@
#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,9 +19,8 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "cairoint.h"
#include <stdlib.h>
#include <string.h>
#include "cairo-freelist-private.h"
void

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

@ -37,12 +37,10 @@
* Carl Worth <cworth@cworth.org>
*/
#include "cairoint.h"
#include <float.h>
#include "cairo-ft-private.h"
#include <float.h>
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
@ -64,9 +62,11 @@
*/
#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
@ -156,6 +156,8 @@ 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)
@ -259,7 +261,6 @@ _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;
}
}
@ -332,16 +333,14 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
unscaled->face = NULL;
filename_copy = strdup (filename);
if (filename_copy == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
if (filename_copy == NULL)
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;
@ -376,7 +375,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
@ -420,8 +419,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_unscaled_font_reference (&unscaled->base);
_cairo_ft_unscaled_font_map_unlock ();
_cairo_unscaled_font_reference (&unscaled->base);
return unscaled;
}
@ -557,7 +556,6 @@ _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;
}
@ -616,7 +614,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 cairo_status_t
static void
_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
cairo_matrix_t *scale)
{
@ -631,7 +629,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 CAIRO_STATUS_SUCCESS;
return;
unscaled->have_scale = TRUE;
unscaled->current_scale = *scale;
@ -660,6 +658,7 @@ _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) {
@ -669,14 +668,17 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
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);
if (error) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
#endif /* MOZCAIRO */
assert (error == 0);
} else {
double min_distance = DBL_MAX;
int i;
@ -705,13 +707,8 @@ _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);
if (error) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
assert (error == 0);
}
return CAIRO_STATUS_SUCCESS;
}
/* Empirically-derived subpixel filtering values thanks to Keith
@ -755,11 +752,9 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
data = bitmap->buffer;
assert (stride == bitmap->pitch);
} else {
data = _cairo_malloc_ab (height, stride);
if (!data) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
data = malloc (stride * height);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
}
if (stride == bitmap->pitch) {
memcpy (data, bitmap->buffer, stride * height);
@ -805,11 +800,9 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
if (own_buffer) {
data = bitmap->buffer;
} else {
data = _cairo_malloc_ab (height, stride);
if (!data) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
data = malloc (stride * height);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
}
memcpy (data, bitmap->buffer, stride * height);
}
format = CAIRO_FORMAT_A8;
@ -848,12 +841,6 @@ _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) {
@ -918,9 +905,6 @@ _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;
}
@ -1051,7 +1035,6 @@ _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;
}
@ -1059,7 +1042,6 @@ _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;
}
@ -1097,10 +1079,8 @@ _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) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
if (error)
return CAIRO_STATUS_NO_MEMORY;
}
status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
if (status)
@ -1198,33 +1178,24 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
/* Initialize it to empty
*/
status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
0, 0,
width, height);
if (status) {
cairo_surface_destroy (image);
return status;
}
_cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
0, 0,
width, height);
/* 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);
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
&pattern.base, NULL, image,
0, 0, 0, 0, 0, 0,
width,
height);
_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.
*/
@ -1474,7 +1445,6 @@ _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)
@ -1483,7 +1453,6 @@ _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;
}
@ -1496,26 +1465,13 @@ _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);
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_scaled_font_init (&scaled_font->base,
font_face,
font_matrix, ctm, options,
&cairo_ft_scaled_font_backend);
_cairo_ft_unscaled_font_set_scale (unscaled,
&scaled_font->base.scale);
metrics = &face->size->metrics;
@ -1593,10 +1549,8 @@ _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) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
if (!pattern)
return CAIRO_STATUS_NO_MEMORY;
}
switch (toy_face->weight)
{
@ -1666,7 +1620,6 @@ _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;
}
}
@ -1691,10 +1644,8 @@ _move_to (FT_Vector *to, void *closure)
x = _cairo_fixed_from_26_6 (to->x);
y = _cairo_fixed_from_26_6 (to->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;
_cairo_path_fixed_close_path (path);
_cairo_path_fixed_move_to (path, x, y);
return 0;
}
@ -1708,8 +1659,7 @@ _line_to (FT_Vector *to, void *closure)
x = _cairo_fixed_from_26_6 (to->x);
y = _cairo_fixed_from_26_6 (to->y);
if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
return 1;
_cairo_path_fixed_line_to (path, x, y);
return 0;
}
@ -1725,9 +1675,7 @@ _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
cairo_fixed_t x3, y3;
cairo_point_t conic;
if (_cairo_path_fixed_get_current_point (path, &x0, &y0) !=
CAIRO_STATUS_SUCCESS)
return 1;
_cairo_path_fixed_get_current_point (path, &x0, &y0);
conic.x = _cairo_fixed_from_26_6 (control->x);
conic.y = _cairo_fixed_from_26_6 (control->y);
@ -1741,11 +1689,10 @@ _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);
if (_cairo_path_fixed_curve_to (path,
x1, y1,
x2, y2,
x3, y3) != CAIRO_STATUS_SUCCESS)
return 1;
_cairo_path_fixed_curve_to (path,
x1, y1,
x2, y2,
x3, y3);
return 0;
}
@ -1768,11 +1715,10 @@ _cubic_to (FT_Vector *control1, FT_Vector *control2,
x2 = _cairo_fixed_from_26_6 (to->x);
y2 = _cairo_fixed_from_26_6 (to->y);
if (_cairo_path_fixed_curve_to (path,
x0, y0,
x1, y1,
x2, y2) != CAIRO_STATUS_SUCCESS)
return 1;
_cairo_path_fixed_curve_to (path,
x0, y0,
x1, y1,
x2, y2);
return 0;
}
@ -1797,7 +1743,6 @@ _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)
@ -1807,17 +1752,9 @@ _decompose_glyph_outline (FT_Face face,
/* Font glyphs have an inverted Y axis compared to cairo. */
FT_Outline_Transform (&glyph->outline, &invert_y);
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;
}
FT_Outline_Decompose (&glyph->outline, &outline_funcs, path);
status = _cairo_path_fixed_close_path (path);
if (status) {
_cairo_path_fixed_destroy (path);
return status;
}
_cairo_path_fixed_close_path (path);
*pathp = path;
@ -1861,16 +1798,14 @@ _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_t status = CAIRO_STATUS_SUCCESS;
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
&scaled_font->base.scale);
if (status)
goto FAIL;
_cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
&scaled_font->base.scale);
/* Ignore global advance unconditionally */
load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
@ -2016,12 +1951,9 @@ _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;
@ -2045,7 +1977,6 @@ _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
@ -2255,12 +2186,10 @@ _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 {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
else
return CAIRO_STATUS_NO_MEMORY;
}
}
static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
@ -2273,32 +2202,23 @@ 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, **prev_font_face;
cairo_ft_font_face_t *font_face;
/* Looked for an existing matching font face */
for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
for (font_face = unscaled->faces;
font_face;
prev_font_face = &font_face->next, 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))
{
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;
}
return cairo_font_face_reference (&font_face->base);
}
/* No match found, create a new one */
font_face = malloc (sizeof (cairo_ft_font_face_t));
if (!font_face) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
if (!font_face)
return NULL;
}
font_face->unscaled = unscaled;
_cairo_unscaled_font_reference (&unscaled->base);
@ -2456,8 +2376,10 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
if (font_face)
return font_face;
else
else {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
}
/**
@ -2507,10 +2429,12 @@ 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
} else {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
}
/**
@ -2548,7 +2472,6 @@ 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;
@ -2559,13 +2482,8 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
return NULL;
}
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;
}
_cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
&scaled_font->base.scale);
/* NOTE: We deliberately release the unscaled font's mutex here,
* so that we are not holding a lock across two separate calls to

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

@ -33,8 +33,7 @@ typedef struct _cairo_glitz_surface {
glitz_surface_t *surface;
glitz_format_t *format;
cairo_bool_t has_clip;
cairo_region_t clip;
pixman_region16_t *clip;
} cairo_glitz_surface_t;
static const cairo_surface_backend_t *
@ -45,9 +44,10 @@ _cairo_glitz_surface_finish (void *abstract_surface)
{
cairo_glitz_surface_t *surface = abstract_surface;
if (surface->has_clip) {
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
_cairo_region_fini (&surface->clip);
if (surface->clip)
{
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
pixman_region_destroy (surface->clip);
}
glitz_surface_destroy (surface->surface);
@ -110,90 +110,19 @@ _cairo_glitz_surface_create_similar (void *abstract_src,
return crsurface;
}
static cairo_bool_t
_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
{
switch (masks->bpp) {
case 32:
if (masks->alpha_mask == 0xff000000 &&
masks->red_mask == 0x00ff0000 &&
masks->green_mask == 0x0000ff00 &&
masks->blue_mask == 0x000000ff)
{
*format = CAIRO_FORMAT_ARGB32;
return TRUE;
}
if (masks->alpha_mask == 0x00000000 &&
masks->red_mask == 0x00ff0000 &&
masks->green_mask == 0x0000ff00 &&
masks->blue_mask == 0x000000ff)
{
*format = CAIRO_FORMAT_RGB24;
return TRUE;
}
break;
case 8:
if (masks->alpha_mask == 0xff)
{
*format = CAIRO_FORMAT_A8;
return TRUE;
}
break;
case 1:
if (masks->alpha_mask == 0x1)
{
*format = CAIRO_FORMAT_A1;
return TRUE;
}
break;
}
return FALSE;
}
static glitz_box_t *
_cairo_glitz_get_boxes_from_region (cairo_region_t *region, int *nboxes)
{
cairo_box_int_t *cboxes;
glitz_box_t *gboxes;
int n, i;
if (_cairo_region_get_boxes (&surface->clip, &n, &cboxes) != CAIRO_STATUS_SUCCESS)
return NULL;
*nboxes = n;
if (n == 0)
return NULL;
gboxes = _cairo_malloc_ab (n, sizeof(glitz_box_t));
if (gboxes == NULL)
goto done;
for (i = 0; i < n; i++) {
gboxes[i].x1 = cboxes[i].p1.x;
gboxes[i].y1 = cboxes[i].p1.y;
gboxes[i].x2 = cboxes[i].p2.x;
gboxes[i].y2 = cboxes[i].p2.y;
}
done:
_cairo_region_boxes_fini (&sruface->clip, &cboxes);
return gboxes;
}
static cairo_status_t
_cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
cairo_rectangle_int_t *interest,
cairo_rectangle_int16_t *interest,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *rect_out)
cairo_rectangle_int16_t *rect_out)
{
cairo_image_surface_t *image;
int x1, y1, x2, y2;
int width, height;
unsigned char *pixels;
cairo_format_masks_t masks;
cairo_format_masks_t format;
glitz_buffer_t *buffer;
glitz_pixel_format_t pf;
cairo_format_t format;
x1 = 0;
y1 = 0;
@ -231,44 +160,44 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
if (surface->format->color.fourcc == GLITZ_FOURCC_RGB) {
if (surface->format->color.red_size > 0) {
masks.bpp = 32;
format.bpp = 32;
if (surface->format->color.alpha_size > 0)
masks.alpha_mask = 0xff000000;
format.alpha_mask = 0xff000000;
else
masks.alpha_mask = 0x0;
format.alpha_mask = 0x0;
masks.red_mask = 0xff0000;
masks.green_mask = 0xff00;
masks.blue_mask = 0xff;
format.red_mask = 0xff0000;
format.green_mask = 0xff00;
format.blue_mask = 0xff;
} else {
masks.bpp = 8;
masks.blue_mask = masks.green_mask = masks.red_mask = 0x0;
masks.alpha_mask = 0xff;
format.bpp = 8;
format.blue_mask = format.green_mask = format.red_mask = 0x0;
format.alpha_mask = 0xff;
}
} else {
masks.bpp = 32;
masks.alpha_mask = 0xff000000;
masks.red_mask = 0xff0000;
masks.green_mask = 0xff00;
masks.blue_mask = 0xff;
format.bpp = 32;
format.alpha_mask = 0xff000000;
format.red_mask = 0xff0000;
format.green_mask = 0xff00;
format.blue_mask = 0xff;
}
pf.fourcc = GLITZ_FOURCC_RGB;
pf.masks.bpp = masks.bpp;
pf.masks.alpha_mask = masks.alpha_mask;
pf.masks.red_mask = masks.red_mask;
pf.masks.green_mask = masks.green_mask;
pf.masks.blue_mask = masks.blue_mask;
pf.masks.bpp = format.bpp;
pf.masks.alpha_mask = format.alpha_mask;
pf.masks.red_mask = format.red_mask;
pf.masks.green_mask = format.green_mask;
pf.masks.blue_mask = format.blue_mask;
pf.xoffset = 0;
pf.skip_lines = 0;
/* XXX: we should eventually return images with negative stride,
need to verify that libpixman have no problem with this first. */
pf.bytes_per_line = (((width * masks.bpp) / 8) + 3) & -4;
pf.bytes_per_line = (((width * format.bpp) / 8) + 3) & -4;
pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;
pixels = _cairo_malloc_ab (height, pf.bytes_per_line);
pixels = malloc (height * pf.bytes_per_line);
if (!pixels)
return CAIRO_STATUS_NO_MEMORY;
@ -279,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->has_clip)
if (surface->clip)
glitz_surface_set_clip_region (surface->surface,
0, 0, NULL, 0);
@ -292,49 +221,24 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
glitz_buffer_destroy (buffer);
/* restore the clip, if any */
if (surface->has_clip) {
if (surface->clip) {
glitz_box_t *box;
int n;
box = _cairo_glitz_get_boxes_from_region (&surface->clip, &n);
if (box == NULL && n != 0) {
free (pixels);
return CAIRO_STATUS_NO_MEMORY;
}
int n;
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);
free (box);
}
/*
* Prefer to use a standard pixman format instead of the
* general masks case.
*/
if (_CAIRO_MASK_FORMAT (&masks, &format)) {
image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (pixels,
format,
x2 - x1,
y2 - y1,
pf.bytes_per_line);
if (image->base.status)
goto FAIL;
} else {
/*
* XXX This can't work. We must convert the data to one of the
* supported pixman formats. Pixman needs another function
* which takes data in an arbitrary format and converts it
* to something supported by that library.
*/
image = (cairo_image_surface_t *)
_cairo_image_surface_create_with_masks (pixels,
&masks,
x2 - x1,
y2 - y1,
pf.bytes_per_line);
if (image->base.status)
goto FAIL;
image = (cairo_image_surface_t *)
_cairo_image_surface_create_with_masks (pixels,
&format,
width, height,
pf.bytes_per_line);
if (image->base.status)
{
free (pixels);
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_image_surface_assume_ownership_of_data (image);
@ -342,47 +246,6 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
*image_out = image;
return CAIRO_STATUS_SUCCESS;
FAIL:
free (pixels);
return CAIRO_STATUS_NO_MEMORY;
}
static void
cairo_format_get_masks (cairo_format_t format,
uint32_t *bpp,
uint32_t *alpha,
uint32_t *red,
uint32_t *green,
uint32_t *blue)
{
*red = 0x0;
*green = 0x0;
*blue = 0x0;
*alpha = 0x0;
switch (format)
{
case CAIRO_FORMAT_ARGB32:
*alpha = 0xff000000;
case CAIRO_FORMAT_RGB24:
default:
*bpp = 32;
*red = 0x00ff0000;
*green = 0x0000ff00;
*blue = 0x000000ff;
break;
case CAIRO_FORMAT_A8:
*bpp = 8;
*alpha = 0xff;
break;
case CAIRO_FORMAT_A1:
*bpp = 1;
*alpha = 0x1;
break;
}
}
static cairo_status_t
@ -398,10 +261,15 @@ _cairo_glitz_surface_set_image (void *abstract_surface,
cairo_glitz_surface_t *surface = abstract_surface;
glitz_buffer_t *buffer;
glitz_pixel_format_t pf;
uint32_t bpp, am, rm, gm, bm;
pixman_format_t *format;
unsigned int bpp, am, rm, gm, bm;
char *data;
cairo_format_get_masks (image->format, &bpp, &am, &rm, &gm, &bm);
format = pixman_image_get_format (image->pixman_image);
if (!format)
return CAIRO_STATUS_NO_MEMORY;
pixman_format_get_masks (format, &bpp, &am, &rm, &gm, &bm);
pf.fourcc = GLITZ_FOURCC_RGB;
pf.masks.bpp = bpp;
@ -463,9 +331,9 @@ _cairo_glitz_surface_release_source_image (void *abstract_surface,
static cairo_status_t
_cairo_glitz_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect_out,
cairo_rectangle_int16_t *image_rect_out,
void **image_extra)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -485,9 +353,9 @@ _cairo_glitz_surface_acquire_dest_image (void *abstract_surfa
static void
_cairo_glitz_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -524,8 +392,8 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface,
{
cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
cairo_content_t content;
cairo_rectangle_int_t image_extent;
cairo_rectangle_int_t extent;
cairo_rectangle_int16_t image_extent;
cairo_rectangle_int16_t extent;
content = _cairo_content_from_format (image_src->format);
@ -722,7 +590,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
(cairo_gradient_pattern_t *) pattern;
char *data;
glitz_fixed16_16_t *params;
unsigned int n_params;
int n_params;
unsigned int *pixels;
unsigned int i, n_base_params;
glitz_buffer_t *buffer;
@ -759,22 +627,8 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
n_params = gradient->n_stops * 3 + n_base_params;
/* check for int overflow */
{
int size1, size2;
if (n_params >= INT32_MAX / sizeof (glitz_fixed16_16_t) ||
gradient->n_stops >= INT32_MAX / sizeof (unsigned int))
return CAIRO_STATUS_NO_MEMORY;
size1 = n_params * sizeof (glitz_fixed16_16_t);
size2 = gradient->n_stops * sizeof (unsigned int);
if (size1 >= INT32_MAX - size2)
return CAIRO_STATUS_NO_MEMORY;
data = malloc (size1 + size2);
}
data = malloc (sizeof (glitz_fixed16_16_t) * n_params +
sizeof (unsigned int) * gradient->n_stops);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
@ -814,7 +668,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
}
glitz_set_pixels (src->surface, 0, 0, gradient->n_stops, 1,
(glitz_pixel_format_t *)&format, buffer);
&format, buffer);
glitz_buffer_destroy (buffer);
@ -822,22 +676,22 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
{
cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern;
params[0] = grad->p1.x;
params[1] = grad->p1.y;
params[2] = grad->p2.x;
params[3] = grad->p2.y;
params[0] = grad->gradient.p1.x;
params[1] = grad->gradient.p1.y;
params[2] = grad->gradient.p2.x;
params[3] = grad->gradient.p2.y;
attr->filter = GLITZ_FILTER_LINEAR_GRADIENT;
}
else
{
cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern;
params[0] = grad->c1.x;
params[1] = grad->c1.y;
params[2] = grad->radius1;
params[3] = grad->c2.x;
params[4] = grad->c2.y;
params[5] = grad->radius2;
params[0] = grad->gradient.c1.x;
params[1] = grad->gradient.c1.y;
params[2] = grad->gradient.c1.radius;
params[3] = grad->gradient.c2.x;
params[4] = grad->gradient.c2.y;
params[5] = grad->gradient.c2.radius;
attr->filter = GLITZ_FILTER_RADIAL_GRADIENT;
}
@ -968,16 +822,11 @@ _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_COLOR_IS_OPAQUE (&combined) ?
CAIRO_CONTENT_COLOR :
CAIRO_CONTENT_COLOR_ALPHA);
_cairo_pattern_init_solid (&tmp.solid, &combined);
mask = NULL;
} else {
status = _cairo_pattern_init_copy (&tmp.base, src);
if (status)
return status;
_cairo_pattern_init_copy (&tmp.base, src);
}
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
@ -992,9 +841,7 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
if (mask)
{
status = _cairo_pattern_init_copy (&tmp.base, mask);
if (status)
return status;
_cairo_pattern_init_copy (&tmp.base, mask);
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
mask_x, mask_y,
@ -1110,7 +957,7 @@ static cairo_int_status_t
_cairo_glitz_surface_fill_rectangles (void *abstract_dst,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int_t *rects,
cairo_rectangle_int16_t *rects,
int n_rects)
{
cairo_glitz_surface_t *dst = abstract_dst;
@ -1155,8 +1002,7 @@ _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,
NULL);
(cairo_color_t *) color);
if (src->base.status)
return CAIRO_STATUS_NO_MEMORY;
@ -1225,9 +1071,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
{
status = _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
if (status)
return status;
_cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base,
dst,
@ -1372,7 +1216,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
}
pixman_add_trapezoids (image->pixman_image, -dst_x, -dst_y,
n_traps, (pixman_trapezoid_t *) traps);
(pixman_trapezoid_t *) traps, n_traps);
mask = (cairo_glitz_surface_t *)
_cairo_surface_create_similar_scratch (&dst->base,
@ -1430,47 +1274,35 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
static cairo_int_status_t
_cairo_glitz_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region);
pixman_region16_t *region)
{
cairo_glitz_surface_t *surface = abstract_surface;
if (region)
{
glitz_box_t *box;
int n;
if (!surface->has_clip) {
_cairo_region_init (&surface->clip);
surface->has_clip = TRUE;
}
if (_cairo_region_copy (&surface->clip, region) != CAIRO_STATUS_SUCCESS)
{
_cairo_region_fini (&surface->clip);
surface->has_clip = FALSE;
return CAIRO_STATUS_NO_MEMORY;
}
box = _cairo_glitz_get_boxes_from_region (&surface->clip, &n);
if (box == NULL && n != 0) {
_cairo_region_fini (&surface->clip);
surface->has_clip = FALSE;
return CAIRO_STATUS_NO_MEMORY;
}
if (!surface->clip)
{
surface->clip = pixman_region_create ();
if (!surface->clip)
return CAIRO_STATUS_NO_MEMORY;
}
pixman_region_copy (surface->clip, region);
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);
free (box);
}
else
{
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
if (surface->has_clip) {
_cairo_region_fini (&surface->clip);
surface->has_clip = FALSE;
}
if (surface->clip)
pixman_region_destroy (surface->clip);
surface->clip = NULL;
}
return CAIRO_STATUS_SUCCESS;
@ -1478,7 +1310,7 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface,
static cairo_int_status_t
_cairo_glitz_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -1980,6 +1812,7 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
glitz_point_fixed_t p1, p2;
glitz_pixel_format_t pf;
glitz_buffer_t *buffer;
pixman_format_t *format;
unsigned int bpp, am, rm, gm, bm;
cairo_int_status_t status;
@ -2016,6 +1849,10 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
format = pixman_image_get_format (glyph_surface->pixman_image);
if (!format)
return CAIRO_STATUS_NO_MEMORY;
if (_cairo_glitz_area_find (font_private->root.area,
glyph_surface->width,
glyph_surface->height,
@ -2035,7 +1872,7 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
return CAIRO_STATUS_NO_MEMORY;
}
cairo_format_get_masks (glyph_surface->format, &bpp, &am, &rm, &gm, &bm);
pixman_format_get_masks (format, &bpp, &am, &rm, &gm, &bm);
pf.fourcc = GLITZ_FOURCC_RGB;
pf.masks.bpp = bpp;
@ -2139,19 +1976,9 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
if (num_glyphs > N_STACK_BUF)
{
char *data;
size_t size1, size2;
if ((size_t)num_glyphs >= INT32_MAX / sizeof(void*) ||
(size_t)num_glyphs >= INT32_MAX / sizeof(glitz_float_t) ||
((size_t)num_glyphs * sizeof(glitz_float_t)) >= INT32_MAX / 16)
goto FAIL1;
size1 = num_glyphs * sizeof(void *);
size2 = num_glyphs * sizeof(glitz_float_t) * 16;
if (size1 >= INT32_MAX - size2)
goto FAIL1;
data = malloc (size1 + size2);
data = malloc (num_glyphs * sizeof (void *) +
num_glyphs * sizeof (glitz_float_t) * 16);
if (!data)
goto FAIL1;
@ -2345,33 +2172,6 @@ _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,
@ -2394,18 +2194,7 @@ 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,
NULL, /* paint */
NULL, /* mask */
NULL, /* stroke */
NULL, /* fill */
NULL, /* show_glyphs */
NULL, /* snapshot */
_cairo_glitz_surface_is_similar,
_cairo_glitz_surface_reset
_cairo_glitz_surface_scaled_glyph_fini
};
static const cairo_surface_backend_t *
@ -2451,9 +2240,9 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
glitz_surface_reference (surface);
crsurface->surface = surface;
crsurface->format = format;
crsurface->has_clip = FALSE;
crsurface->surface = surface;
crsurface->format = format;
crsurface->clip = NULL;
return (cairo_surface_t *) crsurface;
}

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

@ -35,6 +35,8 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include <stdlib.h>
#include "cairoint.h"
#include "cairo-clip-private.h"
@ -62,8 +64,6 @@ 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,12 +91,13 @@ _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,
CAIRO_CONTENT_COLOR);
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
if (gstate->source->status)
return CAIRO_STATUS_NO_MEMORY;
return target ? target->status : CAIRO_STATUS_NULL_POINTER;
gstate->next = NULL;
return CAIRO_STATUS_SUCCESS;
}
/**
@ -130,9 +131,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
_cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
status = _cairo_clip_init_copy (&gstate->clip, &other->clip);
if (status)
return status;
_cairo_clip_init_copy (&gstate->clip, &other->clip);
gstate->target = cairo_surface_reference (other->target);
/* parent_target is always set to NULL; it's only ever set by redirect_target */
@ -161,7 +160,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
_cairo_clip_reset (&gstate->clip);
_cairo_clip_fini (&gstate->clip);
cairo_surface_destroy (gstate->target);
gstate->target = NULL;
@ -176,7 +175,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
gstate->source = NULL;
}
static void
void
_cairo_gstate_destroy (cairo_gstate_t *gstate)
{
if (gstate == NULL)
@ -198,7 +197,7 @@ _cairo_gstate_destroy (cairo_gstate_t *gstate)
* Return value: a new cairo_gstate_t or NULL if there is insufficient
* memory.
**/
static cairo_gstate_t*
cairo_gstate_t*
_cairo_gstate_clone (cairo_gstate_t *other)
{
cairo_status_t status;
@ -219,55 +218,6 @@ _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)
@ -302,11 +252,9 @@ _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.
**/
cairo_status_t
void
_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);
@ -321,18 +269,14 @@ _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_reset (&gstate->clip);
status = _cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
if (status)
return status;
_cairo_clip_fini (&gstate->clip);
_cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
/* 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;
}
/**
@ -412,7 +356,7 @@ _cairo_gstate_set_source (cairo_gstate_t *gstate,
if (source->status)
return source->status;
source = cairo_pattern_reference (source);
cairo_pattern_reference (source);
cairo_pattern_destroy (gstate->source);
gstate->source = source;
gstate->source_ctm_inverse = gstate->ctm_inverse;
@ -530,7 +474,7 @@ _cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dash
return CAIRO_STATUS_SUCCESS;
}
gstate->stroke_style.dash = _cairo_malloc_ab (gstate->stroke_style.num_dashes, sizeof (double));
gstate->stroke_style.dash = malloc (gstate->stroke_style.num_dashes * sizeof (double));
if (gstate->stroke_style.dash == NULL) {
gstate->stroke_style.num_dashes = 0;
return CAIRO_STATUS_NO_MEMORY;
@ -563,24 +507,6 @@ _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)
{
@ -657,16 +583,13 @@ _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);
status = cairo_matrix_invert (&tmp);
if (status)
return status;
cairo_matrix_invert (&tmp);
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
return CAIRO_STATUS_SUCCESS;
@ -690,39 +613,49 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
return CAIRO_STATUS_SUCCESS;
}
void
cairo_status_t
_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;
}
void
cairo_status_t
_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;
}
void
cairo_status_t
_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;
}
void
cairo_status_t
_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;
}
void
cairo_status_t
_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
@ -764,7 +697,7 @@ _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
}
*/
static cairo_status_t
static void
_cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_pattern_t *original,
@ -772,12 +705,8 @@ _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) {
@ -787,26 +716,25 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
_cairo_pattern_transform (pattern, &surface->device_transform);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
static void
_cairo_gstate_copy_transformed_source (cairo_gstate_t *gstate,
cairo_pattern_t *pattern)
{
return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
gstate->source,
&gstate->source_ctm_inverse);
_cairo_gstate_copy_transformed_pattern (gstate, pattern,
gstate->source,
&gstate->source_ctm_inverse);
}
static cairo_status_t
static void
_cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_pattern_t *mask)
{
return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
mask,
&gstate->ctm_inverse);
_cairo_gstate_copy_transformed_pattern (gstate, pattern,
mask,
&gstate->ctm_inverse);
}
cairo_status_t
@ -822,9 +750,7 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
if (status)
return status;
status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
if (status)
return status;
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
status = _cairo_surface_paint (gstate->target,
gstate->op,
@ -931,22 +857,16 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
if (status)
return status;
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;
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
_cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
status = _cairo_surface_mask (gstate->target,
gstate->op,
&source_pattern.base,
&mask_pattern.base);
_cairo_pattern_fini (&mask_pattern.base);
CLEANUP_SOURCE:
_cairo_pattern_fini (&source_pattern.base);
_cairo_pattern_fini (&mask_pattern.base);
return status;
}
@ -967,10 +887,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (status)
return status;
status = _cairo_gstate_copy_transformed_source (gstate,
&source_pattern.base);
if (status)
return status;
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
status = _cairo_surface_stroke (gstate->target,
gstate->op,
@ -1037,9 +954,7 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (status)
return status;
status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
if (status)
return status;
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
status = _cairo_surface_fill (gstate->target,
gstate->op,
@ -1086,13 +1001,29 @@ BAIL:
cairo_status_t
_cairo_gstate_copy_page (cairo_gstate_t *gstate)
{
return _cairo_surface_copy_page (gstate->target);
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;
}
cairo_status_t
_cairo_gstate_show_page (cairo_gstate_t *gstate)
{
return _cairo_surface_show_page (gstate->target);
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;
}
static void
@ -1194,9 +1125,7 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
{
_cairo_clip_reset (&gstate->clip);
return CAIRO_STATUS_SUCCESS;
return _cairo_clip_reset (&gstate->clip);
}
cairo_status_t
@ -1214,7 +1143,7 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
double *x2,
double *y2)
{
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents;
cairo_status_t status;
status = _cairo_surface_get_extents (gstate->target, &extents);
@ -1261,15 +1190,12 @@ _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;
status = _cairo_gstate_set_font_face (gstate, font_face);
if (status)
return status;
_cairo_gstate_set_font_face (gstate, font_face);
cairo_font_face_destroy (font_face);
return CAIRO_STATUS_SUCCESS;
@ -1304,13 +1230,15 @@ _cairo_gstate_get_font_matrix (cairo_gstate_t *gstate,
*matrix = gstate->font_matrix;
}
void
cairo_status_t
_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
@ -1429,19 +1357,17 @@ _cairo_gstate_get_scaled_font (cairo_gstate_t *gstate,
static cairo_status_t
_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
{
cairo_font_face_t *font_face;
if (!gstate->font_face) {
cairo_font_face_t *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;
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;
}
return CAIRO_STATUS_SUCCESS;
}
@ -1451,10 +1377,9 @@ _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 != NULL)
return gstate->scaled_font->status;
if (gstate->scaled_font)
return CAIRO_STATUS_SUCCESS;
status = _cairo_gstate_ensure_font_face (gstate);
if (status)
@ -1463,16 +1388,13 @@ _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);
scaled_font = cairo_scaled_font_create (gstate->font_face,
&gstate->font_matrix,
&gstate->ctm,
&options);
gstate->scaled_font = cairo_scaled_font_create (gstate->font_face,
&gstate->font_matrix,
&gstate->ctm,
&options);
status = cairo_scaled_font_status (scaled_font);
if (status)
return status;
gstate->scaled_font = scaled_font;
if (!gstate->scaled_font)
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
}
@ -1487,7 +1409,7 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
cairo_scaled_font_extents (gstate->scaled_font, extents);
return cairo_scaled_font_status (gstate->scaled_font);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -1504,8 +1426,13 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
if (status)
return status;
return _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
utf8, glyphs, num_glyphs);
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;
}
cairo_status_t
@ -1541,7 +1468,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
glyphs, num_glyphs,
extents);
return cairo_scaled_font_status (gstate->scaled_font);
return CAIRO_STATUS_SUCCESS;
}
#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t)))
@ -1570,7 +1497,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
if (num_glyphs <= STACK_GLYPHS_LEN) {
transformed_glyphs = stack_transformed_glyphs;
} else {
transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
@ -1578,9 +1505,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs);
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
if (status)
goto CLEANUP_GLYPHS;
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
status = _cairo_surface_show_glyphs (gstate->target,
gstate->op,
@ -1591,7 +1516,6 @@ _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);
@ -1615,7 +1539,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
if (num_glyphs < STACK_GLYPHS_LEN)
transformed_glyphs = stack_transformed_glyphs;
else
transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;

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

@ -39,13 +39,51 @@
#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 ARRAY_LENGTH (hash_table_arrangements)
#define NUM_HASH_TABLE_ARRANGEMENTS ((int)(sizeof(hash_table_arrangements)/sizeof(hash_table_arrangements[0])))
struct _cairo_hash_table {
cairo_hash_keys_equal_func_t keys_equal;
@ -481,12 +481,8 @@ _cairo_hash_table_insert (cairo_hash_table_t *hash_table,
hash_table->live_entries++;
status = _cairo_hash_table_resize (hash_table);
if (status) {
/* abort the insert... */
*entry = DEAD_ENTRY;
hash_table->live_entries--;
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}
@ -565,9 +561,6 @@ _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) {
/* Should we fail to shrink the hash table, it is left unaltered,
* and we don't need to propagate the error status. */
if (--hash_table->iterating == 0)
_cairo_hash_table_resize (hash_table);
}
}

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

@ -62,7 +62,7 @@ _cairo_hull_create (cairo_pen_vertex_t *vertices, int num_vertices)
*extremum = vertices[0].point;
vertices[0].point = tmp;
hull = _cairo_malloc_ab (num_vertices, sizeof (cairo_hull_t));
hull = malloc (num_vertices * sizeof (cairo_hull_t));
if (hull == NULL)
return NULL;

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

@ -1,4 +1,3 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2003 University of Southern California
@ -37,7 +36,7 @@
#include "cairoint.h"
static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
{
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
@ -83,6 +82,23 @@ static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
};
static int
_cairo_format_bpp (cairo_format_t format)
{
switch (format) {
case CAIRO_FORMAT_A1:
return 1;
case CAIRO_FORMAT_A8:
return 8;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_ARGB32:
return 32;
}
ASSERT_NOT_REACHED;
return 32;
}
cairo_surface_t *
_cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
cairo_format_t format)
@ -113,47 +129,75 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
return &surface->base;
}
static cairo_bool_t
_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
/* Try to recover a cairo_format_t from a pixman_format
* by looking at the bpp and masks values. */
static cairo_format_t
_cairo_format_from_pixman_format (pixman_format_t *pixman_format)
{
/* XXX: many formats are simply not supported by pixman, so this function
* converts the masks into something we know will be supported.
*/
switch (masks->bpp) {
unsigned int bpp, am, rm, gm, bm;
pixman_format_get_masks (pixman_format, &bpp, &am, &rm, &gm, &bm);
/* See definition of cairo_internal_format_t for an explanation of
* the CAIRO_INTERNAL_FORMAT values used here. */
switch (bpp) {
case 32:
if (masks->alpha_mask == 0xff000000 &&
masks->red_mask == 0x00ff0000 &&
masks->green_mask == 0x0000ff00 &&
masks->blue_mask == 0x000000ff)
{
*format = CAIRO_FORMAT_ARGB32;
return TRUE;
}
if (masks->alpha_mask == 0x00000000 &&
masks->red_mask == 0x00ff0000 &&
masks->green_mask == 0x0000ff00 &&
masks->blue_mask == 0x000000ff)
{
*format = CAIRO_FORMAT_RGB24;
return TRUE;
if (am == 0xff000000) {
if (rm == 0x00ff0000 &&
gm == 0x0000ff00 &&
bm == 0x000000ff)
return CAIRO_FORMAT_ARGB32;
if (rm == 0x000000ff &&
gm == 0x0000ff00 &&
bm == 0x00ff0000)
return CAIRO_INTERNAL_FORMAT_ABGR32;
} else if (am == 0x0) {
if (rm == 0x00ff0000 &&
gm == 0x0000ff00 &&
bm == 0x000000ff)
return CAIRO_FORMAT_RGB24;
if (rm == 0x000000ff &&
gm == 0x0000ff00 &&
bm == 0x00ff0000)
return CAIRO_INTERNAL_FORMAT_BGR24;
}
break;
case 16:
if (am == 0x0 &&
rm == 0xf800 &&
gm == 0x07e0 &&
bm == 0x001f)
return CAIRO_FORMAT_RGB16_565;
break;
case 8:
if (masks->alpha_mask == 0xff)
{
*format = CAIRO_FORMAT_A8;
return TRUE;
}
if (am == 0xff &&
rm == 0x0 &&
gm == 0x0 &&
bm == 0x0)
return CAIRO_FORMAT_A8;
break;
case 1:
if (masks->alpha_mask == 0x1)
{
*format = CAIRO_FORMAT_A1;
return TRUE;
}
if (am == 0x1 &&
rm == 0x0 &&
gm == 0x0 &&
bm == 0x0)
return CAIRO_FORMAT_A1;
break;
}
return FALSE;
fprintf (stderr,
"Error: Cairo " PACKAGE_VERSION " does not yet support the requested image format:\n"
"\tDepth: %d\n"
"\tAlpha mask: 0x%08x\n"
"\tRed mask: 0x%08x\n"
"\tGreen mask: 0x%08x\n"
"\tBlue mask: 0x%08x\n"
"Please file an enhancement request (quoting the above) at:\n"
PACKAGE_BUGREPORT "\n",
bpp, am, rm, gm, bm);
ASSERT_NOT_REACHED;
return (cairo_format_t) -1;
}
/* XXX: This function really should be eliminated. We don't really
@ -162,46 +206,63 @@ _CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
* that accepts a cairo_internal_format_t rather than mask values. */
cairo_surface_t *
_cairo_image_surface_create_with_masks (unsigned char *data,
cairo_format_masks_t *masks,
cairo_format_masks_t *format,
int width,
int height,
int stride)
{
cairo_format_t format;
if (!_CAIRO_MASK_FORMAT (masks, &format)) {
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
cairo_surface_t *surface;
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);
if (pixman_format == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
return cairo_image_surface_create_for_data (data,
format,
width,
height,
stride);
cairo_format = _cairo_format_from_pixman_format (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;
}
surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
cairo_format);
return surface;
}
static pixman_format_code_t
_cairo_format_to_pixman_format_code (cairo_format_t format)
static pixman_format_t *
_create_pixman_format (cairo_format_t format)
{
int ret = 0;
switch (format) {
case CAIRO_FORMAT_A1:
ret = PIXMAN_a1;
return pixman_format_create (PIXMAN_FORMAT_NAME_A1);
break;
case CAIRO_FORMAT_A8:
ret = PIXMAN_a8;
return pixman_format_create (PIXMAN_FORMAT_NAME_A8);
break;
case CAIRO_FORMAT_RGB24:
ret = PIXMAN_x8r8g8b8;
return pixman_format_create (PIXMAN_FORMAT_NAME_RGB24);
break;
case CAIRO_FORMAT_ARGB32:
default:
ret = PIXMAN_a8r8g8b8;
return pixman_format_create (PIXMAN_FORMAT_NAME_ARGB32);
break;
}
assert (ret);
return ret;
}
/**
@ -229,28 +290,31 @@ cairo_image_surface_create (cairo_format_t format,
int width,
int height)
{
cairo_surface_t *surface;
pixman_format_code_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 = _cairo_format_to_pixman_format_code (format);
pixman_image = pixman_image_create_bits (pixman_format, width, height,
NULL, -1);
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);
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_unref (pixman_image);
}
return surface;
}
@ -305,27 +369,32 @@ cairo_image_surface_create_for_data (unsigned char *data,
int height,
int stride)
{
cairo_surface_t *surface;
pixman_format_code_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 = _cairo_format_to_pixman_format_code (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_for_data ((pixman_bits_t *) data, pixman_format,
width, height,
_cairo_format_bpp (format),
stride);
pixman_format_destroy (pixman_format);
pixman_image = pixman_image_create_bits (pixman_format, width, height,
(uint32_t *) data, stride);
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_unref (pixman_image);
}
return surface;
}
@ -498,7 +567,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_INTERNAL_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_INTERNAL_FORMAT_BGR24:
return CAIRO_CONTENT_COLOR;
case CAIRO_FORMAT_A8:
@ -528,7 +597,7 @@ _cairo_image_surface_finish (void *abstract_surface)
cairo_image_surface_t *surface = abstract_surface;
if (surface->pixman_image) {
pixman_image_unref (surface->pixman_image);
pixman_image_destroy (surface->pixman_image);
surface->pixman_image = NULL;
}
@ -566,9 +635,9 @@ _cairo_image_surface_release_source_image (void *abstract_surf
static cairo_status_t
_cairo_image_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect_out,
cairo_rectangle_int16_t *image_rect_out,
void **image_extra)
{
cairo_image_surface_t *surface = abstract_surface;
@ -586,9 +655,9 @@ _cairo_image_surface_acquire_dest_image (void *abstract_surfa
static void
_cairo_image_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
}
@ -621,8 +690,7 @@ _cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
_cairo_matrix_to_pixman_matrix (matrix, &pixman_transform);
if (!pixman_image_set_transform (surface->pixman_image, &pixman_transform))
return CAIRO_STATUS_NO_MEMORY;
pixman_image_set_transform (surface->pixman_image, &pixman_transform);
return CAIRO_STATUS_SUCCESS;
}
@ -658,7 +726,7 @@ _cairo_image_surface_set_filter (cairo_image_surface_t *surface, cairo_filter_t
pixman_filter = PIXMAN_FILTER_BEST;
}
pixman_image_set_filter (surface->pixman_image, pixman_filter, NULL, 0);
pixman_image_set_filter (surface->pixman_image, pixman_filter);
return CAIRO_STATUS_SUCCESS;
}
@ -698,43 +766,43 @@ _cairo_image_surface_set_attributes (cairo_image_surface_t *surface,
* time the X server is ported to pixman, (which will change a lot of
* things in pixman I think).
*/
static pixman_op_t
static pixman_operator_t
_pixman_operator (cairo_operator_t op)
{
switch (op) {
case CAIRO_OPERATOR_CLEAR:
return PIXMAN_OP_CLEAR;
return PIXMAN_OPERATOR_CLEAR;
case CAIRO_OPERATOR_SOURCE:
return PIXMAN_OP_SRC;
return PIXMAN_OPERATOR_SRC;
case CAIRO_OPERATOR_OVER:
return PIXMAN_OP_OVER;
return PIXMAN_OPERATOR_OVER;
case CAIRO_OPERATOR_IN:
return PIXMAN_OP_IN;
return PIXMAN_OPERATOR_IN;
case CAIRO_OPERATOR_OUT:
return PIXMAN_OP_OUT;
return PIXMAN_OPERATOR_OUT;
case CAIRO_OPERATOR_ATOP:
return PIXMAN_OP_ATOP;
return PIXMAN_OPERATOR_ATOP;
case CAIRO_OPERATOR_DEST:
return PIXMAN_OP_DST;
return PIXMAN_OPERATOR_DST;
case CAIRO_OPERATOR_DEST_OVER:
return PIXMAN_OP_OVER_REVERSE;
return PIXMAN_OPERATOR_OVER_REVERSE;
case CAIRO_OPERATOR_DEST_IN:
return PIXMAN_OP_IN_REVERSE;
return PIXMAN_OPERATOR_IN_REVERSE;
case CAIRO_OPERATOR_DEST_OUT:
return PIXMAN_OP_OUT_REVERSE;
return PIXMAN_OPERATOR_OUT_REVERSE;
case CAIRO_OPERATOR_DEST_ATOP:
return PIXMAN_OP_ATOP_REVERSE;
return PIXMAN_OPERATOR_ATOP_REVERSE;
case CAIRO_OPERATOR_XOR:
return PIXMAN_OP_XOR;
return PIXMAN_OPERATOR_XOR;
case CAIRO_OPERATOR_ADD:
return PIXMAN_OP_ADD;
return PIXMAN_OPERATOR_ADD;
case CAIRO_OPERATOR_SATURATE:
return PIXMAN_OP_SATURATE;
return PIXMAN_OPERATOR_SATURATE;
default:
return PIXMAN_OP_OVER;
return PIXMAN_OPERATOR_OVER;
}
}
@ -779,28 +847,28 @@ _cairo_image_surface_composite (cairo_operator_t op,
if (status)
goto CLEANUP_SURFACES;
pixman_image_composite (_pixman_operator (op),
src->pixman_image,
mask->pixman_image,
dst->pixman_image,
src_x + src_attr.x_offset,
src_y + src_attr.y_offset,
mask_x + mask_attr.x_offset,
mask_y + mask_attr.y_offset,
dst_x, dst_y,
width, height);
pixman_composite (_pixman_operator (op),
src->pixman_image,
mask->pixman_image,
dst->pixman_image,
src_x + src_attr.x_offset,
src_y + src_attr.y_offset,
mask_x + mask_attr.x_offset,
mask_y + mask_attr.y_offset,
dst_x, dst_y,
width, height);
}
else
{
pixman_image_composite (_pixman_operator (op),
src->pixman_image,
NULL,
dst->pixman_image,
src_x + src_attr.x_offset,
src_y + src_attr.y_offset,
0, 0,
dst_x, dst_y,
width, height);
pixman_composite (_pixman_operator (op),
src->pixman_image,
NULL,
dst->pixman_image,
src_x + src_attr.x_offset,
src_y + src_attr.y_offset,
0, 0,
dst_x, dst_y,
width, height);
}
if (!_cairo_operator_bounded_by_source (op))
@ -822,60 +890,29 @@ _cairo_image_surface_composite (cairo_operator_t op,
return status;
}
#define STACK_RECTS_LEN (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_rectangle16_t))
static cairo_int_status_t
_cairo_image_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int_t *rects,
cairo_rectangle_int16_t *rects,
int num_rects)
{
cairo_image_surface_t *surface = abstract_surface;
pixman_color_t pixman_color;
pixman_rectangle16_t stack_rects[STACK_RECTS_LEN];
pixman_rectangle16_t *pixman_rects = stack_rects;
int i;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
pixman_color.red = color->red_short;
pixman_color.green = color->green_short;
pixman_color.blue = color->blue_short;
pixman_color.alpha = color->alpha_short;
if (num_rects > ARRAY_LENGTH(stack_rects)) {
pixman_rects = _cairo_malloc_ab (num_rects, sizeof(pixman_rectangle16_t));
if (pixman_rects == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
/* 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);
for (i = 0; i < num_rects; i++) {
pixman_rects[i].x = rects[i].x;
pixman_rects[i].y = rects[i].y;
pixman_rects[i].width = rects[i].width;
pixman_rects[i].height = rects[i].height;
}
/* XXX: pixman_fill_rectangles() should be implemented */
if (!pixman_image_fill_rectangles (_pixman_operator(op),
surface->pixman_image,
&pixman_color,
num_rects,
pixman_rects))
status = CAIRO_STATUS_NO_MEMORY;
if (pixman_rects != stack_rects)
free (pixman_rects);
return status;
return CAIRO_STATUS_SUCCESS;
}
#undef STACK_RECTS_LEN
#define STACK_TRAPS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_trapezoid_t)))
static cairo_int_status_t
_cairo_image_surface_composite_trapezoids (cairo_operator_t op,
cairo_pattern_t *pattern,
@ -895,33 +932,10 @@ _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_code_t format;
uint32_t *mask_data;
pixman_trapezoid_t stack_traps[STACK_TRAPS_LEN];
pixman_trapezoid_t *pixman_traps = stack_traps;
int mask_stride;
int mask_bpp;
int ret, i;
/* Convert traps to pixman traps */
if (num_traps > ARRAY_LENGTH(stack_traps)) {
pixman_traps = _cairo_malloc_ab (num_traps, sizeof(pixman_trapezoid_t));
if (pixman_traps == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
for (i = 0; i < num_traps; i++) {
pixman_traps[i].top = _cairo_fixed_to_16_16 (traps[i].top);
pixman_traps[i].bottom = _cairo_fixed_to_16_16 (traps[i].bottom);
pixman_traps[i].left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x);
pixman_traps[i].left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y);
pixman_traps[i].left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x);
pixman_traps[i].left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y);
pixman_traps[i].right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x);
pixman_traps[i].right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y);
pixman_traps[i].right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x);
pixman_traps[i].right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y);
}
pixman_format_t *format;
pixman_bits_t *mask_data;
int mask_stride;
int mask_bpp;
/* Special case adding trapezoids onto a mask surface; we want to avoid
* creating an intermediate temporary mask unecessarily.
@ -943,9 +957,8 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
antialias != CAIRO_ANTIALIAS_NONE)
{
pixman_add_trapezoids (dst->pixman_image, 0, 0,
num_traps, pixman_traps);
status = CAIRO_STATUS_SUCCESS;
goto finish;
(pixman_trapezoid_t *) traps, num_traps);
return CAIRO_STATUS_SUCCESS;
}
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
@ -953,7 +966,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
(cairo_surface_t **) &src,
&attributes);
if (status)
goto finish;
return status;
status = _cairo_image_surface_set_attributes (src, &attributes);
if (status)
@ -961,50 +974,54 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
switch (antialias) {
case CAIRO_ANTIALIAS_NONE:
format = PIXMAN_a1;
ret = 1;
assert (ret);
mask_stride = ((width + 31) / 8) & ~0x03;
format = pixman_format_create (PIXMAN_FORMAT_NAME_A1);
mask_stride = (width + 31)/8;
mask_bpp = 1;
break;
case CAIRO_ANTIALIAS_GRAY:
case CAIRO_ANTIALIAS_SUBPIXEL:
case CAIRO_ANTIALIAS_DEFAULT:
default:
format = PIXMAN_a8;
ret = 1;
assert (ret);
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
mask_stride = (width + 3) & ~3;
mask_bpp = 8;
break;
}
/* The image must be initially transparent */
mask_data = calloc (1, mask_stride * height);
if (mask_data == NULL) {
if (!format) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_SOURCE;
}
mask = pixman_image_create_bits (format, width, height,
mask_data, mask_stride);
if (mask == NULL) {
/* The image must be initially transparent */
mask_data = calloc (1, mask_stride * height);
if (!mask_data) {
status = CAIRO_STATUS_NO_MEMORY;
pixman_format_destroy (format);
goto CLEANUP_SOURCE;
}
mask = pixman_image_create_for_data (mask_data, format, width, height,
mask_bpp, mask_stride);
pixman_format_destroy (format);
if (!mask) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_IMAGE_DATA;
}
/* XXX: The pixman_trapezoid_t cast is evil and needs to go away
* somehow. */
pixman_add_trapezoids (mask, - dst_x, - dst_y,
num_traps, pixman_traps);
(pixman_trapezoid_t *) traps, num_traps);
pixman_image_composite (_pixman_operator (op),
src->pixman_image,
mask,
dst->pixman_image,
src_x + attributes.x_offset,
src_y + attributes.y_offset,
0, 0,
dst_x, dst_y,
width, height);
pixman_composite (_pixman_operator (op),
src->pixman_image,
mask,
dst->pixman_image,
src_x + attributes.x_offset,
src_y + attributes.y_offset,
0, 0,
dst_x, dst_y,
width, height);
if (!_cairo_operator_bounded_by_mask (op))
status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
@ -1013,7 +1030,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
src_x, src_y,
0, 0,
dst_x, dst_y, width, height);
pixman_image_unref (mask);
pixman_image_destroy (mask);
CLEANUP_IMAGE_DATA:
free (mask_data);
@ -1021,23 +1038,16 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
CLEANUP_SOURCE:
_cairo_pattern_release_surface (pattern, &src->base, &attributes);
finish:
if (pixman_traps != stack_traps)
free (pixman_traps);
return status;
}
#undef STACK_TRAPS_LEN
cairo_int_status_t
_cairo_image_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
pixman_region16_t *region)
{
cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
if (!pixman_image_set_clip_region (surface->pixman_image, &region->rgn))
return CAIRO_STATUS_NO_MEMORY;
pixman_image_set_clip_region (surface->pixman_image, region);
surface->has_clip = region != NULL;
@ -1046,7 +1056,7 @@ _cairo_image_surface_set_clip_region (void *abstract_surface,
static cairo_int_status_t
_cairo_image_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_image_surface_t *surface = abstract_surface;
@ -1058,28 +1068,6 @@ _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
@ -1111,22 +1099,7 @@ 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 */
_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
NULL /* old_show_glyphs */
};
/* A convenience function for when one needs to coerce an image

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

@ -35,6 +35,7 @@
*/
#define _GNU_SOURCE
#include <stdlib.h>
#include "cairoint.h"
@ -197,7 +198,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 @sx, @sy to the transformation in @matrix. The
* Applies scaling by @tx, @ty 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.
**/
@ -475,10 +476,6 @@ cairo_matrix_invert (cairo_matrix_t *matrix)
if (det == 0)
return CAIRO_STATUS_INVALID_MATRIX;
/* this weird construct is for detecting NaNs */
if (! (det * det > 0.))
return CAIRO_STATUS_INVALID_MATRIX;
_cairo_matrix_compute_adjoint (matrix);
_cairo_matrix_scalar_multiply (matrix, 1 / det);
@ -499,7 +496,7 @@ _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,
}
/* Compute the amount that each basis vector is scaled by. */
void
cairo_status_t
_cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
double *sx, double *sy, int x_major)
{
@ -539,6 +536,8 @@ _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
*sy = major;
}
}
return CAIRO_STATUS_SUCCESS;
}
cairo_bool_t
@ -736,13 +735,13 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix,
*pixman_transform = pixman_identity_transform;
}
else {
pixman_transform->matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
pixman_transform->matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
pixman_transform->matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0);
pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
pixman_transform->matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx);
pixman_transform->matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy);
pixman_transform->matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0);
pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
pixman_transform->matrix[2][0] = 0;
pixman_transform->matrix[2][1] = 0;

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

@ -212,11 +212,7 @@ static cairo_status_t
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
cairo_status_t status;
status = _cairo_pattern_init_copy (pattern, other);
if (status)
return status;
_cairo_pattern_init_copy (pattern, other);
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern =
@ -439,7 +435,7 @@ _cairo_meta_surface_show_glyphs (void *abstract_surface,
if (status)
goto CLEANUP_COMMAND;
command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
command->glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
if (command->glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_SOURCE;
@ -556,7 +552,7 @@ _cairo_meta_surface_intersect_clip_path (void *dst,
*/
static cairo_int_status_t
_cairo_meta_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_meta_surface_t *surface = abstract_surface;
@ -652,9 +648,6 @@ _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;
@ -675,9 +668,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
dev_path = _cairo_command_get_path (command);
if (dev_path && has_device_transform) {
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
if (status)
break;
_cairo_path_fixed_init_copy (&path_copy, dev_path);
_cairo_path_fixed_device_transform (&path_copy, device_transform);
dev_path = &path_copy;
}
@ -735,7 +726,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
int i, num_glyphs = command->show_glyphs.num_glyphs;
if (has_device_transform) {
dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
dev_glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
if (dev_glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
break;
@ -763,7 +754,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)
_cairo_clip_reset (&clip);
status = _cairo_clip_reset (&clip);
else
status = _cairo_clip_clip (&clip, dev_path,
command->intersect_clip_path.fill_rule,
@ -782,7 +773,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
}
_cairo_clip_reset (&clip);
_cairo_clip_fini (&clip);
return status;
}

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

@ -35,12 +35,8 @@
* Peter Weilbacher <mozilla@Weilbacher.org>
*/
#include "cairoint.h"
#include "cairo-os2-private.h"
#include <fontconfig/fontconfig.h>
#include <stdlib.h>
#include <stdio.h>
#include <float.h>
#ifdef BUILD_CAIRO_DLL
# define INCL_WIN
@ -53,6 +49,9 @@
# 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
@ -69,6 +68,14 @@
/* 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)
{
@ -96,10 +103,20 @@ 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
@ -120,7 +137,28 @@ cairo_os2_fini (void)
_cairo_ft_font_reset_static_data ();
#endif
CAIRO_MUTEX_FINALIZE ();
/* 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
/* Uninitialize FontConfig */
FcFini ();
@ -296,9 +334,8 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
ULONG ulPixels;
/* allocate temporary pixel buffer */
pchPixBuf = (unsigned char *) _cairo_malloc_abc (surface->bitmap_info.cy,
surface->bitmap_info.cx,
3);
pchPixBuf = (unsigned char *) malloc (3 * surface->bitmap_info.cx *
surface->bitmap_info.cy);
pchPixSource = surface->pixels; /* start at beginning of pixel buffer */
pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */
@ -517,9 +554,9 @@ _cairo_os2_surface_release_source_image (void *abstract_surface
static cairo_status_t
_cairo_os2_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void **image_extra)
{
cairo_os2_surface_t *local_os2_surface;
@ -552,9 +589,9 @@ _cairo_os2_surface_acquire_dest_image (void *abstract_surfac
static void
_cairo_os2_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
cairo_os2_surface_t *local_os2_surface;
@ -628,7 +665,7 @@ _cairo_os2_surface_release_dest_image (void *abstract_surface
static cairo_int_status_t
_cairo_os2_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_os2_surface_t *local_os2_surface;
@ -714,7 +751,7 @@ cairo_os2_surface_create (HPS hps_client_window,
local_os2_surface->bitmap_info.cBitCount = 32;
/* Allocate memory for pixels */
local_os2_surface->pixels = (unsigned char *) _cairo_malloc_abc (height, width, 4);
local_os2_surface->pixels = (unsigned char *) malloc (width * height * 4);
if (!(local_os2_surface->pixels)) {
/* Not enough memory for the pixels! */
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
@ -784,7 +821,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
}
/* Allocate memory for new stuffs */
pchNewPixels = (unsigned char *) _cairo_malloc_abc (new_height, new_width, 4);
pchNewPixels = (unsigned char *) malloc (new_width * new_height * 4);
if (!pchNewPixels) {
/* Not enough memory for the pixels!
* Everything remains the same!

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

@ -37,7 +37,7 @@
#ifndef CAIRO_OUTPUT_STREAM_PRIVATE_H
#define CAIRO_OUTPUT_STREAM_PRIVATE_H
#include "cairo-types-private.h"
typedef struct _cairo_output_stream cairo_output_stream_t;
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 void
cairo_private int
_cairo_dtostr (char *buffer, size_t size, double d);
cairo_private void

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

@ -34,12 +34,11 @@
* Kristian Høgsberg <krh@redhat.com>
*/
#include "cairoint.h"
#include "cairo-output-stream-private.h"
#include <stdio.h>
#include <locale.h>
#include <ctype.h>
#include "cairoint.h"
#include "cairo-output-stream-private.h"
#ifdef _MSC_VER
#define snprintf _snprintf
@ -64,7 +63,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 */
@ -72,7 +71,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 */
@ -120,7 +119,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;
@ -138,8 +137,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;
}
@ -215,49 +214,52 @@ _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>
*/
void
int
_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--;
}
}
if (*p == '.') {
*p = 0;
p--;
}
}
return p + 1 - buffer;
}
enum {
@ -276,13 +278,10 @@ void
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
const char *fmt, va_list ap)
{
#define SINGLE_FMT_BUFFER_SIZE 32
char buffer[512], single_fmt[SINGLE_FMT_BUFFER_SIZE];
int single_fmt_length;
char *p;
char buffer[512], single_fmt[32];
char *p, *end;
const char *f, *start;
int length_modifier, width;
cairo_bool_t var_width;
int length_modifier;
if (stream->status)
return;
@ -306,14 +305,10 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
if (*f == '0')
f++;
var_width = FALSE;
if (*f == '*') {
var_width = TRUE;
f++;
}
while (isdigit (*f))
f++;
if (isdigit (*f)) {
strtol (f, &end, 10);
f = end;
}
length_modifier = 0;
if (*f == 'l') {
@ -321,15 +316,9 @@ _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, single_fmt_length);
single_fmt[single_fmt_length] = '\0';
memcpy (single_fmt, start, f + 1 - start);
single_fmt[f + 1 - start] = '\0';
/* Flush contents of buffer before snprintf()'ing into it. */
_cairo_output_stream_write (stream, buffer, p - buffer);
@ -348,27 +337,15 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
case 'o':
case 'x':
case 'X':
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));
}
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:
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));
}
snprintf (buffer, sizeof buffer,
single_fmt, va_arg (ap, long int));
break;
case 's':
snprintf (buffer, sizeof buffer,
@ -469,11 +446,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;
@ -489,12 +466,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);
@ -535,7 +512,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);

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

@ -36,37 +36,106 @@
#ifndef CAIRO_PAGINATED_SURFACE_H
#define CAIRO_PAGINATED_SURFACE_H
#include "cairo.h"
#include "cairoint.h"
#include "cairo-surface-private.h"
typedef enum {
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
CAIRO_PAGINATED_MODE_RENDER /* render page contents */
} cairo_paginated_mode_t;
typedef struct _cairo_paginated_surface {
cairo_surface_t base;
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);
/* The target surface to hold the final result. */
cairo_surface_t *target;
/* 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;
cairo_content_t content;
/* 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);
/* 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_surface_t *
_cairo_paginated_surface_get_target (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;
cairo_private cairo_bool_t
_cairo_surface_is_paginated (cairo_surface_t *surface);
#endif /* CAIRO_PAGINATED_SURFACE_H */

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

@ -36,17 +36,45 @@
/* 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-private.h for
* (PostScript, PDF, etc.). See cairo-paginated-surface-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
@ -134,15 +162,11 @@ _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);
@ -177,22 +201,15 @@ _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_int_t extents;
cairo_rectangle_int16_t extents;
status = _cairo_surface_get_extents (surface->target, &extents);
if (status)
return status;
_cairo_surface_get_extents (surface->target, &extents);
image = _cairo_paginated_surface_create_image_surface (surface,
extents.width,
extents.height);
status = _cairo_meta_surface_replay (surface->meta, image);
if (status) {
cairo_surface_destroy (image);
return status;
}
_cairo_meta_surface_replay (surface->meta, image);
*image_out = (cairo_image_surface_t*) image;
*image_extra = NULL;
@ -218,16 +235,13 @@ _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);
status = _cairo_meta_surface_replay (surface->meta, analysis);
_cairo_meta_surface_replay (surface->meta, analysis);
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
if (status || analysis->status) {
if (status == CAIRO_STATUS_SUCCESS)
status = analysis->status;
if (analysis->status) {
status = analysis->status;
cairo_surface_destroy (analysis);
return status;
}
@ -243,29 +257,26 @@ _paint_page (cairo_paginated_surface_t *surface)
surface->height * y_scale);
_cairo_surface_set_device_scale (image, x_scale, y_scale);
status = _cairo_meta_surface_replay (surface->meta, image);
if (status)
goto CLEANUP_IMAGE;
_cairo_meta_surface_replay (surface->meta, image);
pattern = cairo_pattern_create_for_surface (image);
cairo_matrix_init_scale (&matrix, x_scale, y_scale);
cairo_pattern_set_matrix (pattern, &matrix);
status = _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
cairo_pattern_destroy (pattern);
CLEANUP_IMAGE:
cairo_surface_destroy (image);
}
else
{
status = _cairo_meta_surface_replay (surface->meta, surface->target);
_cairo_meta_surface_replay (surface->meta, surface->target);
}
cairo_surface_destroy (analysis);
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -287,9 +298,7 @@ _cairo_paginated_surface_copy_page (void *abstract_surface)
if (status)
return status;
status = _paint_page (surface);
if (status)
return status;
_paint_page (surface);
surface->page_num++;
@ -314,16 +323,9 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
if (status)
return status;
status = _paint_page (surface);
if (status)
return status;
_paint_page (surface);
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_show_page (surface->target);
cairo_surface_destroy (surface->meta);
@ -354,7 +356,7 @@ _cairo_paginated_surface_intersect_clip_path (void *abstract_surface,
static cairo_int_status_t
_cairo_paginated_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_paginated_surface_t *surface = abstract_surface;
@ -483,7 +485,6 @@ _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
@ -501,22 +502,16 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
#if 0
return _cairo_surface_snapshot (other->meta);
#else
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents;
cairo_surface_t *surface;
status = _cairo_surface_get_extents (other->target, &extents);
if (status)
return (cairo_surface_t*) &_cairo_surface_nil;
_cairo_surface_get_extents (other->target, &extents);
surface = _cairo_paginated_surface_create_image_surface (other,
extents.width,
extents.height);
status = _cairo_meta_surface_replay (other->meta, surface);
if (status) {
cairo_surface_destroy (surface);
surface = (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_meta_surface_replay (other->meta, surface);
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 void
static cairo_status_t
_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 void
static cairo_status_t
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *point)
{
if (bounder->has_point) {
@ -104,6 +104,8 @@ _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,28 +88,37 @@ _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;
_cairo_polygon_close (polygon);
_cairo_polygon_move_to (polygon, point);
status = _cairo_polygon_close (polygon);
if (status)
return status;
status = _cairo_polygon_move_to (polygon, point);
if (status)
return status;
filler->current_point = *point;
return _cairo_polygon_status (&filler->polygon);
return CAIRO_STATUS_SUCCESS;
}
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;
_cairo_polygon_line_to (polygon, point);
status = _cairo_polygon_line_to (polygon, point);
if (status)
return status;
filler->current_point = *point;
return _cairo_polygon_status (&filler->polygon);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -129,12 +138,15 @@ _cairo_filler_curve_to (void *closure,
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
status = _cairo_spline_decompose (&spline, filler->tolerance);
_cairo_spline_decompose (&spline, filler->tolerance);
if (status)
goto CLEANUP_SPLINE;
for (i = 1; i < spline.num_points; i++)
_cairo_polygon_line_to (polygon, &spline.points[i]);
for (i = 1; i < spline.num_points; i++) {
status = _cairo_polygon_line_to (polygon, &spline.points[i]);
if (status)
break;
}
CLEANUP_SPLINE:
_cairo_spline_fini (&spline);
@ -147,12 +159,15 @@ _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;
_cairo_polygon_close (polygon);
status = _cairo_polygon_close (polygon);
if (status)
return status;
return _cairo_polygon_status (polygon);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@ -186,8 +201,7 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
if (status)
goto BAIL;
_cairo_polygon_close (&filler.polygon);
status = _cairo_polygon_status (&filler.polygon);
status = _cairo_polygon_close (&filler.polygon);
if (status)
goto BAIL;

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

@ -1,4 +1,3 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
@ -36,6 +35,7 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include <stdlib.h>
#include "cairoint.h"
#include "cairo-path-fixed-private.h"
@ -356,8 +356,8 @@ _cairo_path_fixed_add (cairo_path_fixed_t *path,
cairo_point_t *points,
int num_points)
{
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)
if (path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE ||
path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
{
cairo_path_buf_t *buf;
@ -510,19 +510,25 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
{
cairo_path_buf_t *buf = path->buf_head;
int i;
cairo_int64_t i64temp;
cairo_fixed_t fixedtemp;
while (buf) {
for (i = 0; i < buf->num_points; i++) {
if (scalex == CAIRO_FIXED_ONE) {
buf->points[i].x += offx;
} else {
buf->points[i].x = _cairo_fixed_mul (buf->points[i].x + offx, scalex);
fixedtemp = buf->points[i].x + offx;
i64temp = _cairo_int32x32_64_mul (fixedtemp, scalex);
buf->points[i].x = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
}
if (scaley == CAIRO_FIXED_ONE) {
buf->points[i].y += offy;
} else {
buf->points[i].y = _cairo_fixed_mul (buf->points[i].y + offy, scaley);
fixedtemp = buf->points[i].y + offy;
i64temp = _cairo_int32x32_64_mul (fixedtemp, scaley);
buf->points[i].y = _cairo_int64_to_int32(_cairo_int64_rsl (i64temp, 16));
}
}

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

@ -67,7 +67,7 @@ typedef struct cairo_stroker {
} cairo_stroker_t;
/* private functions */
static cairo_status_t
static void
_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 cairo_status_t
static void
_cairo_stroker_init (cairo_stroker_t *stroker,
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *ctm,
@ -156,18 +156,15 @@ _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;
status = _cairo_pen_init (&stroker->pen,
stroke_style->line_width / 2.0,
tolerance, ctm);
if (status)
return status;
_cairo_pen_init (&stroker->pen,
stroke_style->line_width / 2.0,
tolerance, ctm);
stroker->has_current_face = FALSE;
stroker->has_first_face = FALSE;
@ -177,8 +174,6 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
_cairo_stroker_start_dash (stroker);
else
stroker->dashed = FALSE;
return CAIRO_STATUS_SUCCESS;
}
static void
@ -210,7 +205,6 @@ _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
@ -237,21 +231,13 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
tri[0] = in->point;
if (clockwise) {
status = _cairo_pen_find_active_ccw_vertex_index (pen, &in->dev_vector, &start);
if (status)
return status;
_cairo_pen_find_active_ccw_vertex_index (pen, &in->dev_vector, &start);
step = -1;
status = _cairo_pen_find_active_ccw_vertex_index (pen, &out->dev_vector, &stop);
if (status)
return status;
_cairo_pen_find_active_ccw_vertex_index (pen, &out->dev_vector, &stop);
} else {
status = _cairo_pen_find_active_cw_vertex_index (pen, &in->dev_vector, &start);
if (status)
return status;
_cairo_pen_find_active_cw_vertex_index (pen, &in->dev_vector, &start);
step = +1;
status = _cairo_pen_find_active_cw_vertex_index (pen, &out->dev_vector, &stop);
if (status)
return status;
_cairo_pen_find_active_cw_vertex_index (pen, &out->dev_vector, &stop);
}
i = start;
@ -259,9 +245,7 @@ _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);
status = _cairo_traps_tessellate_triangle (stroker->traps, tri);
if (status)
return status;
_cairo_traps_tessellate_triangle (stroker->traps, tri);
tri[1] = tri[2];
i += step;
if (i < 0)
@ -394,23 +378,17 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
cairo_pen_t *pen = &stroker->pen;
slope = f->dev_vector;
status = _cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
if (status)
return status;
_cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
slope.dx = -slope.dx;
slope.dy = -slope.dy;
status = _cairo_pen_find_active_cw_vertex_index (pen, &slope, &stop);
if (status)
return status;
_cairo_pen_find_active_cw_vertex_index (pen, &slope, &stop);
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);
status = _cairo_traps_tessellate_triangle (stroker->traps, tri);
if (status)
return status;
_cairo_traps_tessellate_triangle (stroker->traps, tri);
tri[1] = tri[2];
}
tri[2] = f->ccw;
@ -441,14 +419,8 @@ _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;
@ -995,11 +967,9 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
status = _cairo_stroker_init (&stroker, stroke_style,
ctm, ctm_inverse, tolerance,
traps);
if (status)
return status;
_cairo_stroker_init (&stroker, stroke_style,
ctm, ctm_inverse, tolerance,
traps);
if (stroker.style->dash)
status = _cairo_path_fixed_interpret (path,

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

@ -34,10 +34,9 @@
* 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 };
@ -136,7 +135,6 @@ _cairo_path_count (cairo_path_t *path,
double tolerance,
cairo_bool_t flatten)
{
cairo_status_t status;
cpc_t cpc;
cpc.count = 0;
@ -144,17 +142,15 @@ _cairo_path_count (cairo_path_t *path,
cpc.current_point.x = 0;
cpc.current_point.y = 0;
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;
_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);
return cpc.count;
}
@ -279,8 +275,7 @@ _cpp_curve_to_flatten (void *closure,
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
status = _cairo_spline_decompose (&spline,
_cairo_gstate_get_tolerance (cpp->gstate));
status = _cairo_spline_decompose (&spline, cpp->gstate->tolerance);
if (status)
goto out;
@ -310,13 +305,12 @@ _cpp_close_path (void *closure)
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
static void
_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;
@ -324,22 +318,18 @@ _cairo_path_populate (cairo_path_t *path,
cpp.current_point.x = 0;
cpp.current_point.y = 0;
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;
_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);
/* Sanity check the count */
assert (cpp.data - path->data == path->num_data);
return status;
}
cairo_path_t *
@ -347,10 +337,6 @@ _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;
@ -374,21 +360,18 @@ _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,
_cairo_gstate_get_tolerance (gstate),
flatten);
if (path->num_data <= 0) {
free (path);
return (cairo_path_t*) &_cairo_path_nil;
}
gstate->tolerance, flatten);
path->data = _cairo_malloc_ab (path->num_data, sizeof (cairo_path_data_t));
path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
if (path->data == NULL) {
free (path);
return (cairo_path_t*) &_cairo_path_nil;
}
path->status = _cairo_path_populate (path, path_fixed,
gstate, flatten);
path->status = CAIRO_STATUS_SUCCESS;
_cairo_path_populate (path, path_fixed,
gstate, flatten);
return path;
}
@ -477,7 +460,6 @@ _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];
@ -510,10 +492,6 @@ _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;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -45,13 +45,15 @@ _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);
void
cairo_status_t
_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
@ -78,7 +80,7 @@ _cairo_pen_init (cairo_pen_t *pen,
radius,
ctm);
pen->vertices = _cairo_malloc_ab (pen->num_vertices, sizeof (cairo_pen_vertex_t));
pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL) {
return CAIRO_STATUS_NO_MEMORY;
}
@ -119,7 +121,7 @@ _cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other)
*pen = *other;
if (pen->num_vertices) {
pen->vertices = _cairo_malloc_ab (pen->num_vertices, sizeof (cairo_pen_vertex_t));
pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL) {
return CAIRO_STATUS_NO_MEMORY;
}
@ -133,7 +135,6 @@ 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;
@ -149,9 +150,7 @@ _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];
status = _cairo_hull_compute (pen->vertices, &pen->num_vertices);
if (status)
return status;
_cairo_hull_compute (pen->vertices, &pen->num_vertices);
_cairo_pen_compute_slopes (pen);
@ -389,18 +388,15 @@ _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
final_slope.dy = -final_slope.dy;
}
status = _cairo_pen_find_active_cw_vertex_index (pen,
&initial_slope,
&active);
if (status)
return status;
_cairo_pen_find_active_cw_vertex_index (pen, &initial_slope, &active);
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;
_cairo_polygon_line_to (polygon, &hull_point);
status = _cairo_polygon_line_to (polygon, &hull_point);
if (status)
return status;
if (i + step == stop)
slope = final_slope;
@ -441,24 +437,19 @@ _cairo_pen_stroke_spline (cairo_pen_t *pen,
status = _cairo_spline_decompose (spline, tolerance);
if (status)
goto BAIL;
return status;
status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_FORWARD, &polygon);
if (status)
goto BAIL;
return status;
status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_REVERSE, &polygon);
if (status)
goto BAIL;
return status;
_cairo_polygon_close (&polygon);
status = _cairo_polygon_status (&polygon);
if (status)
goto BAIL;
status = _cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
BAIL:
_cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
_cairo_polygon_fini (&polygon);
return status;
return CAIRO_STATUS_SUCCESS;
}

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

@ -35,9 +35,8 @@
* Kristian Høgsberg <krh@redhat.com>
*/
#include "cairoint.h"
#include <errno.h>
#include "cairoint.h"
#include <png.h>
/* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
@ -83,25 +82,6 @@ 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,
@ -128,7 +108,7 @@ write_png (cairo_surface_t *surface,
else if (status != CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
rows = _cairo_malloc_ab (image->height, sizeof(png_byte*));
rows = malloc (image->height * sizeof(png_byte*));
if (rows == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL1;
@ -137,9 +117,7 @@ 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,
png_simple_error_callback,
png_simple_warning_callback);
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL2;
@ -151,9 +129,10 @@ write_png (cairo_surface_t *surface,
goto BAIL3;
}
status = setjmp (png_jmpbuf (png));
if (status)
if (setjmp (png_jmpbuf (png))) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL3;
}
png_set_write_fn (png, closure, write_func, NULL);
@ -175,7 +154,7 @@ write_png (cairo_surface_t *surface,
png_color_type = PNG_COLOR_TYPE_GRAY;
break;
default:
status = CAIRO_STATUS_INVALID_FORMAT;
status = CAIRO_STATUS_NULL_POINTER;
goto BAIL3;
}
@ -227,13 +206,8 @@ stdio_write_func (png_structp png, png_bytep data, png_size_t size)
FILE *fp;
fp = png_get_io_ptr (png);
while (size) {
size_t ret = fwrite (data, 1, size, fp);
size -= ret;
data += ret;
if (size && ferror (fp))
png_error(png, "Write Error");
}
if (fwrite (data, 1, size, fp) != size)
png_error(png, "Write Error");
}
/**
@ -358,20 +332,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,
png_simple_error_callback,
png_simple_warning_callback);
NULL,
NULL);
if (png == NULL)
goto BAIL;
@ -399,11 +373,7 @@ 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);
@ -429,11 +399,11 @@ read_png (png_rw_ptr read_func,
png_read_update_info (png, info);
pixel_size = 4;
data = _cairo_malloc_abc (png_height, png_width, pixel_size);
data = malloc (png_width * png_height * pixel_size);
if (data == NULL)
goto BAIL;
row_pointers = _cairo_malloc_ab (png_height, sizeof(char *));
row_pointers = malloc (png_height * sizeof(char *));
if (row_pointers == NULL)
goto BAIL;
@ -472,13 +442,8 @@ stdio_read_func (png_structp png, png_bytep data, png_size_t size)
FILE *fp;
fp = png_get_io_ptr (png);
while (size) {
size_t ret = fread (data, 1, size, fp);
size -= ret;
data += ret;
if (size && ferror (fp))
png_error(png, "Read Error");
}
if (fread (data, 1, size, fp) != size)
png_error(png, "Read Error");
}
/**

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

@ -34,6 +34,7 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include <stdlib.h>
#include "cairoint.h"
/* private functions */
@ -44,8 +45,6 @@ _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;
@ -67,19 +66,13 @@ _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 = ARRAY_LENGTH (polygon->edges_embedded);
int embedded_size = sizeof (polygon->edges_embedded) / sizeof (polygon->edges_embedded[0]);
int new_size = 2 * MAX (old_size, 16);
/* we have a local buffer at polygon->edges_embedded. try to fulfill the request
@ -93,7 +86,7 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
assert (polygon->num_edges <= polygon->edges_size);
if (polygon->edges == polygon->edges_embedded) {
new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t));
new_edges = malloc (new_size * sizeof (cairo_edge_t));
if (new_edges)
memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t));
} else {
@ -110,22 +103,22 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
return CAIRO_STATUS_SUCCESS;
}
void
cairo_status_t
_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) {
polygon->status = _cairo_polygon_grow (polygon);
if (polygon->status)
return;
status = _cairo_polygon_grow (polygon);
if (status) {
return status;
}
}
edge = &polygon->edges[polygon->num_edges];
@ -143,45 +136,49 @@ _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;
}
void
cairo_status_t
_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;
}
void
cairo_status_t
_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point)
{
if (polygon->status)
return;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
if (polygon->has_current_point) {
_cairo_polygon_add_edge (polygon, &polygon->current_point, point);
status = _cairo_polygon_add_edge (polygon, &polygon->current_point, point);
} else {
_cairo_polygon_move_to (polygon, point);
}
return status;
}
void
cairo_status_t
_cairo_polygon_close (cairo_polygon_t *polygon)
{
if (polygon->status)
return;
cairo_status_t status;
if (polygon->has_current_point) {
_cairo_polygon_add_edge (polygon,
&polygon->current_point,
&polygon->first_point);
status = _cairo_polygon_add_edge (polygon,
&polygon->current_point,
&polygon->first_point);
if (status)
return status;
polygon->has_current_point = FALSE;
}
return CAIRO_STATUS_SUCCESS;
}

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

@ -39,9 +39,9 @@
#include "cairoint.h"
#include "cairo-ps.h"
#include "cairo-ps-surface-private.h"
#include "cairo-ps-test.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-paginated-private.h"
#include "cairo-paginated-surface-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-output-stream-private.h"
@ -52,6 +52,40 @@
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
@ -148,7 +182,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,
@ -263,7 +297,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, status2;
cairo_status_t status;
ps_path_info_t path_info;
word_wrap = _word_wrap_stream_create (stream, 79);
@ -281,9 +315,7 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface,
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_output_stream_get_status (word_wrap);
status2 = _cairo_output_stream_destroy (word_wrap);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
_cairo_output_stream_destroy (word_wrap);
return status;
}
@ -452,18 +484,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 = 1; i < font_subset->num_glyphs; i++)
for (i = 0; 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);
font_subset->num_glyphs + 1);
for (i = 1; i < font_subset->num_glyphs; i++)
for (i = 0; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->final_stream,
"/g%d %d def\n", i, i);
"/g%d %d def\n", i, i + 1);
_cairo_output_stream_printf (surface->final_stream,
"end readonly def\n");
@ -547,8 +579,6 @@ _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) {
@ -604,7 +634,7 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
static void
_cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
@ -628,8 +658,6 @@ _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
@ -638,7 +666,6 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
{
cairo_status_t status;
cairo_matrix_t matrix;
unsigned int i;
@ -651,9 +678,7 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
font_subset->subset_id);
matrix = font_subset->scaled_font->scale;
status = cairo_matrix_invert (&matrix);
/* _cairo_scaled_font_init ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_invert (&matrix);
_cairo_output_stream_printf (surface->final_stream,
"\t/FontType\t3\n"
"\t/FontMatrix\t[%f %f %f %f 0 0]\n"
@ -666,11 +691,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
-matrix.yy);
for (i = 0; i < font_subset->num_glyphs; i++) {
status = _cairo_ps_surface_emit_glyph (surface,
font_subset->scaled_font,
font_subset->glyphs[i], i);
if (status)
return status;
_cairo_ps_surface_emit_glyph (surface,
font_subset->scaled_font,
font_subset->glyphs[i], i);
}
_cairo_output_stream_printf (surface->final_stream,
@ -786,7 +809,8 @@ _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_simple ();
surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT,
PS_SURFACE_MAX_GLYPHS_PER_FONT);
if (! surface->font_subsets)
goto CLEANUP_OUTPUT_STREAM;
@ -795,7 +819,6 @@ _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;
@ -811,8 +834,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
&cairo_ps_surface_paginated_backend);
CLEANUP_OUTPUT_STREAM:
status = _cairo_output_stream_destroy (surface->stream);
/* Ignore status---we're already on a failure path. */
_cairo_output_stream_destroy (surface->stream);
CLEANUP_TMPFILE:
fclose (surface->tmpfile);
CLEANUP_SURFACE:
@ -1179,7 +1201,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, status2;
cairo_status_t status;
cairo_ps_surface_t *surface = abstract_surface;
int i, num_comments;
char **comments;
@ -1192,13 +1214,16 @@ _cairo_ps_surface_finish (void *abstract_surface)
_cairo_ps_surface_emit_footer (surface);
status = _cairo_output_stream_destroy (surface->stream);
_cairo_output_stream_close (surface->stream);
status = _cairo_output_stream_get_status (surface->stream);
_cairo_output_stream_destroy (surface->stream);
fclose (surface->tmpfile);
status2 = _cairo_output_stream_destroy (surface->final_stream);
_cairo_output_stream_close (surface->final_stream);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
status = _cairo_output_stream_get_status (surface->final_stream);
_cairo_output_stream_destroy (surface->final_stream);
num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
comments = _cairo_array_index (&surface->dsc_header_comments, 0);
@ -1358,12 +1383,32 @@ 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 (surface->force_fallbacks)
if (cairo_ps_force_fallbacks)
return FALSE;
if (! pattern_supported (pattern))
@ -1497,7 +1542,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,
@ -1517,7 +1562,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
cairo_image_surface_t *image,
const char *name)
{
cairo_status_t status, status2;
cairo_status_t status;
unsigned char *rgb, *compressed;
unsigned long rgb_size, compressed_size;
cairo_surface_t *opaque;
@ -1543,29 +1588,20 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
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_fill_rectangle (opaque,
CAIRO_OPERATOR_SOURCE,
CAIRO_COLOR_WHITE,
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_surface_composite (CAIRO_OPERATOR_OVER,
&pattern.base,
NULL,
opaque,
0, 0,
0, 0,
0, 0,
image->width,
image->height);
_cairo_pattern_fini (&pattern.base);
opaque_image = (cairo_image_surface_t *) opaque;
@ -1583,7 +1619,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
i = 0;
for (y = 0; y < opaque_image->height; y++) {
uint32_t *pixel = (uint32_t *) (opaque_image->data + y * opaque_image->stride);
pixman_bits_t *pixel = (pixman_bits_t *) (opaque_image->data + y * opaque_image->stride);
for (x = 0; x < opaque_image->width; x++, pixel++) {
rgb[i++] = (*pixel & 0x00ff0000) >> 16;
rgb[i++] = (*pixel & 0x0000ff00) >> 8;
@ -1610,12 +1646,8 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
_cairo_output_stream_write (base85_stream, compressed, compressed_size);
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_destroy (base85_stream);
_cairo_output_stream_destroy (string_array_stream);
_cairo_output_stream_printf (surface->stream,
"] def\n");
@ -1647,7 +1679,6 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
status = CAIRO_STATUS_SUCCESS;
bail3:
free (compressed);
bail2:
free (rgb);
@ -1674,26 +1705,19 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
pattern->color.blue);
}
static cairo_status_t
static void
_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;
status = cairo_matrix_invert (&inverse);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
cairo_matrix_invert (&inverse);
if (_cairo_surface_is_meta (pattern->surface)) {
_cairo_output_stream_printf (surface->stream, "/MyPattern {\n");
status = _cairo_meta_surface_replay (pattern->surface, &surface->base);
if (status)
return status;
_cairo_meta_surface_replay (pattern->surface, &surface->base);
bbox_width = surface->width;
bbox_height = surface->height;
xstep = surface->width;
@ -1781,8 +1805,6 @@ _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
@ -1799,13 +1821,12 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
/* XXX: NYI */
}
static cairo_status_t
static void
_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:
@ -1813,10 +1834,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pa
break;
case CAIRO_PATTERN_TYPE_SURFACE:
status = _cairo_ps_surface_emit_surface_pattern (surface,
(cairo_surface_pattern_t *) pattern);
if (status)
return status;
_cairo_ps_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
break;
case CAIRO_PATTERN_TYPE_LINEAR:
@ -1827,8 +1845,6 @@ _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
@ -1878,7 +1894,7 @@ _cairo_ps_surface_intersect_clip_path (void *abstract_surface,
static cairo_int_status_t
_cairo_ps_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_ps_surface_t *surface = abstract_surface;
@ -1913,8 +1929,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_rectangle_int_t extents, pattern_extents;
cairo_status_t status;
cairo_rectangle_int16_t extents, pattern_extents;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_ps_surface_analyze_operation (surface, op, source);
@ -1926,25 +1941,17 @@ _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");
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_surface_get_extents (&surface->base, &extents);
_cairo_pattern_get_extents (source, &pattern_extents);
_cairo_rectangle_intersect (&extents, &pattern_extents);
status = _cairo_ps_surface_emit_pattern (surface, source);
if (status)
return status;
_cairo_ps_surface_emit_pattern (surface, source);
_cairo_output_stream_printf (stream, "%d %d M\n",
extents.x, extents.y);
@ -1958,7 +1965,6 @@ _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;
}
@ -2037,7 +2043,7 @@ _cairo_ps_surface_stroke (void *abstract_surface,
* can modify some of the values.
*/
if (num_dashes % 2) {
dash = _cairo_malloc_abc (num_dashes, 2, sizeof (double));
dash = malloc (2 * num_dashes * sizeof (double));
if (dash == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -2194,7 +2200,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;
cairo_scaled_font_subsets_glyph_t subset_glyph;
unsigned int font_id;
cairo_ps_glyph_id_t *glyph_ids;
cairo_status_t status;
unsigned int num_glyphs_unsigned, i, j, last, end;
@ -2215,18 +2221,18 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
num_glyphs_unsigned = num_glyphs;
_cairo_ps_surface_emit_pattern (surface, source);
glyph_ids = _cairo_malloc_ab (num_glyphs_unsigned, sizeof (cairo_ps_glyph_id_t));
glyph_ids = malloc (num_glyphs_unsigned*sizeof (cairo_ps_glyph_id_t));
if (glyph_ids == NULL)
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < num_glyphs_unsigned; i++) {
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
scaled_font, glyphs[i].index,
&subset_glyph);
&font_id,
&(glyph_ids[i].subset_id),
&(glyph_ids[i].glyph_id));
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;
@ -2236,7 +2242,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
"/CairoFont-%d-%d findfont\n"
"[ %f %f %f %f 0 0 ] makefont\n"
"setfont\n",
subset_glyph.font_id,
font_id,
glyph_ids[i].subset_id,
scaled_font->scale.xx,
scaled_font->scale.yx,

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

@ -51,16 +51,13 @@ typedef struct cairo_quartz_surface {
CGContextRef cgContext;
CGAffineTransform cgContextBaseCTM;
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents;
/* 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,24 +101,47 @@ static void quartz_image_to_png (CGImageRef, char *dest);
* Cairo path -> Quartz path conversion helpers
*/
typedef struct _quartz_stroke {
CGContextRef cgContext;
cairo_matrix_t *ctm_inverse;
} quartz_stroke_t;
/* 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;
}
/* 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)));
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);
CGContextMoveToPoint ((CGContextRef) closure,
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
return CAIRO_STATUS_SUCCESS;
}
@ -126,17 +149,12 @@ 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)));
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);
if (CGContextIsPathEmpty ((CGContextRef) closure))
CGContextMoveToPoint ((CGContextRef) closure,
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
else
CGContextAddLineToPoint (stroke->cgContext, x, y);
CGContextAddLineToPoint ((CGContextRef) closure,
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
return CAIRO_STATUS_SUCCESS;
}
@ -147,22 +165,11 @@ _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);
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);
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));
return CAIRO_STATUS_SUCCESS;
}
@ -170,14 +177,26 @@ static cairo_status_t
_cairo_path_to_quartz_context_close_path (void *closure)
{
//ND((stderr, "closepath\n"));
quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
CGContextClosePath (stroke->cgContext);
CGContextClosePath ((CGContextRef) closure);
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,
quartz_stroke_t *stroke)
CGContextRef cgc)
{
return _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
@ -185,7 +204,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,
stroke);
cgc);
}
/*
@ -267,8 +286,8 @@ _cairo_quartz_cairo_matrix_to_quartz (const cairo_matrix_t *src,
CGAffineTransform *dst)
{
dst->a = src->xx;
dst->b = src->yx;
dst->c = src->xy;
dst->b = src->xy;
dst->c = src->yx;
dst->d = src->yy;
dst->tx = src->x0;
dst->ty = src->y0;
@ -282,7 +301,7 @@ static void
ComputeGradientValue (void *info, const float *in, float *out)
{
float fdist = *in; /* 0.0 .. 1.0 */
cairo_fixed_t fdist_fix = _cairo_fixed_from_double(*in);
cairo_fixed_16_16_t fdist_fix = _cairo_fixed_from_double(*in);
cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info;
unsigned int i;
@ -346,13 +365,6 @@ _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;
@ -374,10 +386,10 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
CGFunctionRef gradFunc;
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
start = CGPointMake (_cairo_fixed_to_double (lpat->p1.x) - x0,
_cairo_fixed_to_double (lpat->p1.y) - y0);
end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x) - x0,
_cairo_fixed_to_double (lpat->p2.y) - y0);
start = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p1.x) - x0,
_cairo_fixed_to_double (lpat->gradient.p1.y) - y0);
end = CGPointMake (_cairo_fixed_to_double (lpat->gradient.p2.x) - x0,
_cairo_fixed_to_double (lpat->gradient.p2.y) - y0);
cairo_pattern_reference (abspat);
gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat);
@ -398,18 +410,18 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
CGFunctionRef gradFunc;
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
start = CGPointMake (_cairo_fixed_to_double (rpat->c1.x) - x0,
_cairo_fixed_to_double (rpat->c1.y) - y0);
end = CGPointMake (_cairo_fixed_to_double (rpat->c2.x) - x0,
_cairo_fixed_to_double (rpat->c2.y) - y0);
start = CGPointMake (_cairo_fixed_to_double (rpat->gradient.c1.x) - x0,
_cairo_fixed_to_double (rpat->gradient.c1.y) - y0);
end = CGPointMake (_cairo_fixed_to_double (rpat->gradient.c2.x) - x0,
_cairo_fixed_to_double (rpat->gradient.c2.y) - y0);
cairo_pattern_reference (abspat);
gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
shading = CGShadingCreateRadial (rgb,
start,
_cairo_fixed_to_double (rpat->r1),
_cairo_fixed_to_double (rpat->gradient.c1.radius),
end,
_cairo_fixed_to_double (rpat->r2),
_cairo_fixed_to_double (rpat->gradient.c2.radius),
gradFunc,
true, true);
CGColorSpaceRelease(rgb);
@ -423,30 +435,38 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
return NULL;
}
/* 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)
/* 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 = NULL;
cairo_bool_t flip = FALSE;
CGImageRef img;
if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) {
/* XXXtodo/perf don't use clone if the source surface is an image surface! Instead,
/* 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,
* just create the CGImage directly!
*/
cairo_surface_t *ref_type = target;
cairo_surface_t *dummy = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cairo_surface_t *new_surf = NULL;
cairo_rectangle_int_t rect;
if (ref_type == NULL)
ref_type = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cairo_rectangle_int16_t rect;
_cairo_surface_get_extents (pat_surf, &rect);
_cairo_surface_clone_similar (ref_type, pat_surf, rect.x, rect.y,
_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
rect.width, rect.height, &new_surf);
if (target == NULL)
cairo_surface_destroy(ref_type);
cairo_surface_destroy(dummy);
quartz_surf = (cairo_quartz_surface_t *) new_surf;
} else {
@ -456,21 +476,15 @@ _cairo_quartz_surface_to_quartz (cairo_surface_t *target, cairo_surface_t *pat_s
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;
}
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;
img = CGBitmapContextCreateImage (quartz_surf->cgContext);
if (!img) {
// ... give up.
@ -479,33 +493,17 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
return;
}
/* 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) {
if (flip) {
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);
@ -517,11 +515,7 @@ static cairo_status_t
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
cairo_status_t status;
status = _cairo_pattern_init_copy (pattern, other);
if (status)
return status;
_cairo_pattern_init_copy (pattern, other);
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern =
@ -545,7 +539,7 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
{
cairo_surface_pattern_t *spat;
cairo_surface_t *pat_surf;
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents;
CGRect pbounds;
CGAffineTransform ptransform, stransform;
@ -569,24 +563,8 @@ _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;
// 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;
pbounds.size.width = extents.width;
pbounds.size.height = extents.height;
m = spat->base.matrix;
cairo_matrix_invert(&m);
@ -606,6 +584,38 @@ _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 */
@ -632,13 +642,12 @@ 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));
@ -667,44 +676,19 @@ _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_int_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);
patternSpace = CGColorSpaceCreatePattern(NULL);
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetFillColorSpace (surface->cgContext, patternSpace);
CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
CGContextSetStrokeColorSpace (surface->cgContext, patternSpace);
@ -732,11 +716,7 @@ _cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
cairo_pattern_t *source)
{
if (surface->sourceImage) {
CGImageRelease(surface->sourceImage);
surface->sourceImage = NULL;
cairo_surface_destroy(surface->sourceImageSurface);
surface->sourceImageSurface = NULL;
// nothing to do; we don't use sourceImage yet
}
if (surface->sourceShading) {
@ -885,21 +865,12 @@ _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_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect,
void **image_extra)
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect,
void **image_extra)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t status;
@ -920,10 +891,10 @@ _cairo_quartz_surface_acquire_dest_image (void *abstract_surface,
static void
_cairo_quartz_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
void *image_extra)
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
unsigned char *imageData = (unsigned char *) image_extra;
@ -994,6 +965,7 @@ _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;
@ -1080,7 +1052,7 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
static cairo_int_status_t
_cairo_quartz_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *extents)
cairo_rectangle_int16_t *extents)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
@ -1114,19 +1086,6 @@ _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;
}
@ -1149,7 +1108,6 @@ _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));
@ -1168,10 +1126,7 @@ _cairo_quartz_surface_fill (void *abstract_surface,
}
CGContextBeginPath (surface->cgContext);
stroke.cgContext = surface->cgContext;
stroke.ctm_inverse = NULL;
_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
if (action == DO_SOLID || action == DO_PATTERN) {
if (fill_rule == CAIRO_FILL_RULE_WINDING)
@ -1188,21 +1143,6 @@ _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;
}
@ -1229,8 +1169,6 @@ _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));
@ -1246,8 +1184,6 @@ _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
@ -1255,7 +1191,7 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
float *fdash = sdash;
unsigned int k;
if (style->num_dashes > STATIC_DASH)
fdash = _cairo_malloc_ab (style->num_dashes, sizeof (float));
fdash = malloc (sizeof(float)*style->num_dashes);
for (k = 0; k < style->num_dashes; k++)
fdash[k] = (float) style->dash[k];
@ -1275,25 +1211,13 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
}
CGContextBeginPath (surface->cgContext);
stroke.cgContext = surface->cgContext;
stroke.ctm_inverse = ctm_inverse;
_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
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);
@ -1319,21 +1243,9 @@ _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)
@ -1350,7 +1262,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_IMAGE || action == DO_SHADING) {
} else if (action == DO_SHADING) {
CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
} else {
/* Unsupported */
@ -1360,9 +1272,9 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op));
fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font);
atsfref = FMGetATSFontRefFromFont (fid);
cgfref = CGFontCreateWithPlatformFont (&atsfref);
ATSUFontID fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font);
ATSFontRef atsfref = FMGetATSFontRefFromFont (fid);
CGFontRef cgfref = CGFontCreateWithPlatformFont (&atsfref);
CGContextSetFont (surface->cgContext, cgfref);
CGFontRelease (cgfref);
@ -1373,11 +1285,8 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
* text matrix?
*/
//ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y));
cairoTextTransform = CGAffineTransformMake (scaled_font->font_matrix.xx,
scaled_font->font_matrix.yx,
scaled_font->font_matrix.xy,
scaled_font->font_matrix.yy,
0., 0.);
CGAffineTransform cairoTextTransform, textTransform, ctm;
_cairo_quartz_cairo_matrix_to_quartz (&scaled_font->font_matrix, &cairoTextTransform);
textTransform = CGAffineTransformMakeTranslation (glyphs[0].x, glyphs[0].y);
textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0);
@ -1393,27 +1302,51 @@ _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*) _cairo_malloc_ab (num_glyphs, sizeof(CGGlyph));
cg_advances = (CGSize*) _cairo_malloc_ab (num_glyphs, sizeof(CGSize));
cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs);
cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs);
}
xprev = glyphs[0].x;
yprev = glyphs[0].y;
#ifndef MOZILLA_CAIRO_NOT_DEFINED
float xprev = glyphs[0].x;
float 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++) {
@ -1431,17 +1364,8 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
free (cg_advances);
}
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) {
if (action == DO_SHADING)
CGContextDrawShading (surface->cgContext, surface->sourceShading);
}
_cairo_quartz_teardown_source (surface, source);
@ -1497,7 +1421,6 @@ _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));
@ -1513,9 +1436,7 @@ _cairo_quartz_surface_intersect_clip_path (void *abstract_surface,
CGContextSaveGState (surface->cgContext);
} else {
CGContextBeginPath (surface->cgContext);
stroke.cgContext = surface->cgContext;
stroke.ctm_inverse = NULL;
_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
if (fill_rule == CAIRO_FILL_RULE_WINDING)
CGContextClip (surface->cgContext);
else
@ -1534,7 +1455,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,
_cairo_quartz_surface_release_source_image,
NULL, /* release_source_image */
_cairo_quartz_surface_acquire_dest_image,
_cairo_quartz_surface_release_dest_image,
_cairo_quartz_surface_clone_similar,
@ -1711,7 +1632,7 @@ cairo_quartz_surface_create (cairo_format_t format,
return (cairo_surface_t*) &_cairo_surface_nil;
}
imageData = _cairo_malloc_ab (height, stride);
imageData = malloc (height * stride);
if (!imageData) {
CGColorSpaceRelease (cgColorspace);
_cairo_error (CAIRO_STATUS_NO_MEMORY);

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

@ -41,19 +41,19 @@
/* XXX We currently have a confusing mix of boxes and rectangles as
* exemplified by this function. A cairo_box_t is a rectangular area
* represented by the coordinates of the upper left and lower right
* corners, expressed in fixed point numbers. A cairo_rectangle_int_t is
* corners, expressed in fixed point numbers. A cairo_rectangle_int16_t is
* also a rectangular area, but represented by the upper left corner
* and the width and the height, as integer numbers.
*
* This function converts a cairo_box_t to a cairo_rectangle_int_t by
* This function converts a cairo_box_t to a cairo_rectangle_int16_t by
* increasing the area to the nearest integer coordinates. We should
* standardize on cairo_rectangle_fixed_t and cairo_rectangle_int_t, and
* standardize on cairo_rectangle_int16_t and cairo_rectangle_int16_t, and
* this function could be renamed to the more reasonable
* _cairo_rectangle_fixed_round.
*/
void
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_t *rectangle)
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int16_t *rectangle)
{
rectangle->x = _cairo_fixed_integer_floor (box->p1.x);
rectangle->y = _cairo_fixed_integer_floor (box->p1.y);
@ -62,7 +62,7 @@ _cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_t *rectangl
}
void
_cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *src)
_cairo_rectangle_intersect (cairo_rectangle_int16_t *dest, cairo_rectangle_int16_t *src)
{
int x1, y1, x2, y2;

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

@ -1,4 +1,3 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
@ -32,178 +31,52 @@
*
* Contributor(s):
* Owen Taylor <otaylor@redhat.com>
* Vladimir Vukicevic <vladimir@pobox.com>
*/
#include "cairoint.h"
#include <cairoint.h>
void
_cairo_region_init (cairo_region_t *region)
/**
* _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)
{
pixman_region_init (&region->rgn);
}
void
_cairo_region_init_rect (cairo_region_t *region,
cairo_rectangle_int_t *rect)
{
pixman_region_init_rect (&region->rgn,
rect->x, rect->y,
rect->width, rect->height);
}
#define STACK_BOXES_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(pixman_box16_t)))
cairo_int_status_t
_cairo_region_init_boxes (cairo_region_t *region,
cairo_box_int_t *boxes,
int count)
{
pixman_box16_t stack_pboxes[STACK_BOXES_LEN];
pixman_box16_t *pboxes = stack_pboxes;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
int i;
if (count > ARRAY_LENGTH(stack_pboxes)) {
pboxes = _cairo_malloc_ab (count, sizeof(pixman_box16_t));
if (pboxes == NULL)
return CAIRO_STATUS_NO_MEMORY;
/* 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;
}
for (i = 0; i < count; i++) {
pboxes[i].x1 = boxes[i].p1.x;
pboxes[i].y1 = boxes[i].p1.y;
pboxes[i].x2 = boxes[i].p2.x;
pboxes[i].y2 = boxes[i].p2.y;
}
if (!pixman_region_init_rects (&region->rgn, pboxes, count))
status = CAIRO_STATUS_NO_MEMORY;
if (pboxes != stack_pboxes)
free (pboxes);
return status;
}
void
_cairo_region_fini (cairo_region_t *region)
{
pixman_region_fini (&region->rgn);
}
cairo_int_status_t
_cairo_region_copy (cairo_region_t *dst, cairo_region_t *src)
{
if (!pixman_region_copy (&dst->rgn, &src->rgn))
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
}
int
_cairo_region_num_boxes (cairo_region_t *region)
{
return pixman_region_n_rects (&region->rgn);
}
cairo_int_status_t
_cairo_region_get_boxes (cairo_region_t *region, int *num_boxes, cairo_box_int_t **boxes)
{
int nboxes;
pixman_box16_t *pboxes;
cairo_box_int_t *cboxes;
int i;
pboxes = pixman_region_rectangles (&region->rgn, &nboxes);
if (nboxes == 0) {
*num_boxes = 0;
*boxes = NULL;
return CAIRO_STATUS_SUCCESS;
}
cboxes = _cairo_malloc_ab (nboxes, sizeof(cairo_box_int_t));
if (cboxes == NULL)
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < nboxes; i++) {
cboxes[i].p1.x = pboxes[i].x1;
cboxes[i].p1.y = pboxes[i].y1;
cboxes[i].p2.x = pboxes[i].x2;
cboxes[i].p2.y = pboxes[i].y2;
}
*num_boxes = nboxes;
*boxes = cboxes;
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_region_boxes_fini (cairo_region_t *region, cairo_box_int_t *boxes)
{
free (boxes);
return region;
}
/**
* _cairo_region_get_extents:
* @region: a #cairo_region_t
* _cairo_region_extents_rectangle:
* @region: a #pixman_region16_t
* @rect: rectangle into which to store the extents
*
* Gets the bounding box of a region as a cairo_rectangle_int_t
* Gets the bounding box of a region as a cairo_rectangle_int16_t
**/
void
_cairo_region_get_extents (cairo_region_t *region, cairo_rectangle_int_t *extents)
_cairo_region_extents_rectangle (pixman_region16_t *region,
cairo_rectangle_int16_t *rect)
{
pixman_box16_t *pextents = pixman_region_extents (&region->rgn);
pixman_box16_t *region_extents = pixman_region_extents (region);
extents->x = pextents->x1;
extents->y = pextents->y1;
extents->width = pextents->x2 - pextents->x1;
extents->height = pextents->y2 - pextents->y1;
}
cairo_int_status_t
_cairo_region_subtract (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
{
if (!pixman_region_subtract (&dst->rgn, &a->rgn, &b->rgn))
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_region_intersect (cairo_region_t *dst, cairo_region_t *a, cairo_region_t *b)
{
if (!pixman_region_intersect (&dst->rgn, &a->rgn, &b->rgn))
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
}
cairo_int_status_t
_cairo_region_union_rect (cairo_region_t *dst,
cairo_region_t *src,
cairo_rectangle_int_t *rect)
{
if (!pixman_region_union_rect (&dst->rgn, &src->rgn,
rect->x, rect->y,
rect->width, rect->height))
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
}
cairo_bool_t
_cairo_region_not_empty (cairo_region_t *region)
{
return (cairo_bool_t) pixman_region_not_empty (&region->rgn);
}
void
_cairo_region_translate (cairo_region_t *region,
int x, int y)
{
pixman_region_translate (&region->rgn, x, y);
rect->x = region_extents->x1;
rect->y = region_extents->y1;
rect->width = region_extents->x2 - region_extents->x1;
rect->height = region_extents->y2 - region_extents->y1;
}

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

@ -1,4 +1,9 @@
#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
#define _cairo_svg_test_force_fallbacks _moz__cairo_svg_test_force_fallbacks
#define _cairo_xlib_test_disable_render _moz__cairo_xlib_test_disable_render
#define cairo_append_path _moz_cairo_append_path
#define cairo_arc _moz_cairo_arc
#define cairo_arc_negative _moz_cairo_arc_negative

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

@ -39,17 +39,19 @@
#include "cairoint.h"
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;
typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
/**
* _cairo_scaled_font_subsets_create_scaled:
* _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.
*
* Create a new #cairo_scaled_font_subsets_t object which can be used
* to create subsets of any number of cairo_scaled_font_t
@ -58,57 +60,16 @@ typedef struct _cairo_scaled_font_subsets_glyph {
* subsets with glyph indices packed into the range
* [0 .. max_glyphs_per_subset).
*
* 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.
* @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_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_create (int max_glyphs_unscaled_per_subset,
int max_glyphs_scaled_per_subset);
/**
* _cairo_scaled_font_subsets_destroy:
@ -124,8 +85,6 @@ _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
@ -167,17 +126,6 @@ _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.
@ -186,7 +134,9 @@ 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,
cairo_scaled_font_subsets_glyph_t *subset_glyph_ret);
unsigned int *font_id_ret,
unsigned int *subset_id_ret,
unsigned int *subset_glyph_index_ret);
typedef void
(*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset,
@ -303,37 +253,6 @@ _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;
@ -422,15 +341,6 @@ _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
@ -484,43 +394,6 @@ _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,21 +42,12 @@
#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 {
cairo_subsets_type_t type;
int max_glyphs_per_unscaled_subset_limit;
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;
@ -67,7 +58,6 @@ 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;
@ -84,7 +74,6 @@ 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 {
@ -118,8 +107,7 @@ _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,
double x_advance)
unsigned int subset_glyph_index)
{
cairo_sub_font_glyph_t *sub_font_glyph;
@ -130,7 +118,6 @@ _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;
}
@ -208,8 +195,7 @@ _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_composite)
cairo_bool_t is_scaled)
{
cairo_sub_font_t *sub_font;
@ -218,11 +204,10 @@ _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 = scaled_font;
sub_font->scaled_font = cairo_scaled_font_reference (scaled_font);
sub_font->font_id = font_id;
sub_font->current_subset = 0;
@ -235,11 +220,6 @@ _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;
}
@ -265,9 +245,10 @@ _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,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
_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_glyph_t key, *sub_font_glyph;
@ -275,12 +256,8 @@ _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_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;
*subset_id = sub_font_glyph->subset_id;
*subset_glyph_index = sub_font_glyph->subset_glyph_index;
return CAIRO_STATUS_SUCCESS;
}
@ -291,11 +268,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,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
unsigned int *subset_id,
unsigned int *subset_glyph_index)
{
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,
@ -305,24 +282,11 @@ _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++;
}
}
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_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
sub_font->current_subset,
sub_font->num_glyphs_in_current_subset++,
scaled_glyph->metrics.x_advance);
sub_font->num_glyphs_in_current_subset++);
if (sub_font_glyph == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -338,18 +302,12 @@ _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) {
_cairo_sub_font_glyph_destroy (sub_font_glyph);
if (status)
return status;
}
}
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;
*subset_id = sub_font_glyph->subset_id;
*subset_glyph_index = sub_font_glyph->subset_glyph_index;
return CAIRO_STATUS_SUCCESS;
}
@ -366,31 +324,23 @@ _cairo_sub_font_collect (void *entry, void *closure)
for (i = 0; i <= sub_font->current_subset; i++) {
collection->subset_id = i;
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;
}
collection->num_glyphs = 0;
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;
subset.num_glyphs = collection->num_glyphs;
/* No need to check for out of memory here. If to_unicode is NULL, the PDF
* surface does not emit an ToUnicode stream */
subset.to_unicode = _cairo_malloc_ab (collection->num_glyphs, sizeof (unsigned long));
subset.to_unicode = malloc (collection->num_glyphs*sizeof(unsigned long));
if (subset.to_unicode) {
for (j = 0; j < collection->num_glyphs; j++) {
/* default unicode character required when mapping fails */
@ -405,8 +355,9 @@ _cairo_sub_font_collect (void *entry, void *closure)
}
}
static cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
int max_glyphs_per_scaled_subset)
{
cairo_scaled_font_subsets_t *subsets;
@ -414,9 +365,12 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
if (subsets == NULL)
return NULL;
subsets->type = type;
subsets->max_glyphs_per_unscaled_subset_limit = max_glyphs_per_unscaled_subset;
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);
@ -427,7 +381,7 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
if (! subsets->scaled_sub_fonts) {
_cairo_hash_table_destroy (subsets->unscaled_sub_fonts);
free (subsets->unscaled_sub_fonts);
free (subsets);
return NULL;
}
@ -435,24 +389,6 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
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)
{
@ -468,44 +404,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,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
unsigned int *font_id,
unsigned int *subset_id,
unsigned int *subset_glyph_index)
{
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->type != CAIRO_SUBSETS_SCALED) {
if (subsets->max_glyphs_per_unscaled_subset_limit > 0) {
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_glyph);
if (status == CAIRO_STATUS_SUCCESS)
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;
}
}
}
/* Lookup glyph in scaled subsets */
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;
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;
}
}
}
/* Glyph not found. Determine whether the glyph is outline or
@ -514,96 +450,51 @@ _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 && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (status == 0 && subsets->type != CAIRO_SUBSETS_SCALED) {
if (status == 0 && subsets->max_glyphs_per_unscaled_subset_limit > 0) {
/* 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))
{
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,
sub_font = _cairo_sub_font_create (subsets, scaled_font,
subsets->num_sub_fonts++,
max_glyphs,
subset_glyph->is_scaled,
subset_glyph->is_composite);
if (sub_font == NULL) {
cairo_scaled_font_destroy (unscaled_font);
subsets->max_glyphs_per_unscaled_subset_limit,
FALSE);
if (sub_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts,
&sub_font->base);
if (status) {
_cairo_sub_font_destroy (sub_font);
if (status)
return status;
}
}
} else {
} else if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
/* 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))
{
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),
sub_font = _cairo_sub_font_create (subsets, scaled_font,
subsets->num_sub_fonts++,
max_glyphs,
subset_glyph->is_scaled,
subset_glyph->is_composite);
if (sub_font == NULL) {
cairo_scaled_font_destroy (scaled_font);
subsets->max_glyphs_per_scaled_subset_limit,
TRUE);
if (sub_font == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_hash_table_insert (subsets->scaled_sub_fonts,
&sub_font->base);
if (status) {
_cairo_sub_font_destroy (sub_font);
if (status)
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_glyph);
return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index,
subset_id, subset_glyph_index);
}
static cairo_status_t
@ -618,11 +509,7 @@ _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 = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long));
collection.glyphs = malloc (collection.glyphs_size * sizeof(unsigned long));
if (collection.glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -653,7 +540,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-private.h"
#include "cairo-scaled-font-test.h"
static cairo_bool_t
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
@ -135,9 +135,6 @@ _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;
}
@ -156,7 +153,6 @@ 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.
@ -189,6 +185,8 @@ 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);
@ -215,7 +213,6 @@ _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;
@ -334,7 +331,14 @@ _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. */
#define MAX_GLYPHS_CACHED_PER_FONT 256
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;
}
/*
* Basic cairo_scaled_font_t object management
@ -348,40 +352,23 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
const cairo_font_options_t *options,
const cairo_scaled_font_backend_t *backend)
{
cairo_matrix_t inverse;
cairo_status_t status;
scaled_font->ref_count = 1;
status = cairo_font_options_status ((cairo_font_options_t *) options);
if (status)
return status;
_cairo_user_data_array_init (&scaled_font->user_data);
/* 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);
inverse = scaled_font->scale;
status = cairo_matrix_invert (&inverse);
if (status)
return status;
CAIRO_MUTEX_INIT (&scaled_font->mutex);
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
_cairo_scaled_glyph_destroy,
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);
max_glyphs_cached_per_font);
scaled_font->surface_backend = NULL;
scaled_font->surface_private = NULL;
@ -409,7 +396,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
@ -443,7 +430,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)
@ -487,12 +474,9 @@ 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 (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
return NULL;
_cairo_scaled_font_init_key (&key, font_face,
font_matrix, ctm, options);
@ -517,44 +501,35 @@ 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;
}
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 scaled_font;
}
/* 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) {
/* 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 (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
}
} 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) {
_cairo_scaled_font_map_unlock ();
return NULL;
}
status = _cairo_hash_table_insert (font_map->hash_table,
&scaled_font->hash_entry);
_cairo_scaled_font_map_unlock ();
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;
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;
}
}
return scaled_font;
@ -773,13 +748,10 @@ 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_t status = CAIRO_STATUS_SUCCESS;
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);
@ -802,7 +774,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).
@ -813,7 +785,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_t status = CAIRO_STATUS_SUCCESS;
int i;
double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0;
cairo_bool_t visible = FALSE;
@ -927,7 +899,7 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
if (status)
goto DONE;
*glyphs = (cairo_glyph_t *) _cairo_malloc_ab ((*num_glyphs), sizeof (cairo_glyph_t));
*glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t)));
if (*glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
@ -974,8 +946,8 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
int i;
short min_x = INT16_MAX, max_x = INT16_MIN;
short min_y = INT16_MAX, max_y = INT16_MIN;
int min_x = INT16_MAX, max_x = INT16_MIN;
int min_y = INT16_MAX, max_y = INT16_MIN;
if (scaled_font->status)
return scaled_font->status;
@ -1128,7 +1100,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
_cairo_pattern_fini (&glyph_pattern.base);
if (status)
goto CLEANUP_MASK;
break;
}
if (mask != NULL) {
@ -1204,42 +1176,6 @@ _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:
@ -1262,7 +1198,6 @@ 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;
@ -1285,10 +1220,19 @@ _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)) {
status = _add_unit_rectangle_to_path (path,
x + xoff, y + yoff);
if (status)
return status;
_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);
}
}
}
@ -1334,8 +1278,6 @@ _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)
@ -1360,9 +1302,6 @@ _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;
@ -1662,9 +1601,6 @@ 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,24 +26,7 @@
#include "cairoint.h"
/*
* 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)
#define MAX_LEVEL 31
/*
* Skip list element. In order to use the skip list, the caller must
@ -69,7 +52,7 @@ typedef struct _skip_list {
size_t elt_size;
size_t data_size;
skip_elt_t *chains[MAX_LEVEL];
skip_elt_t *freelists[MAX_FREELIST_LEVEL];
skip_elt_t *freelists[MAX_LEVEL];
int max_level;
} cairo_skip_list_t;

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

@ -21,7 +21,11 @@
* OF THIS SOFTWARE.
*/
#include "cairoint.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include "cairo-skiplist-private.h"
@ -232,9 +236,6 @@ _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;
}
@ -250,7 +251,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_FREELIST_LEVEL; i++) {
for (i=0; i<MAX_LEVEL; i++) {
elt = list->freelists[i];
while (elt) {
skip_elt_t *nextfree = elt->prev;
@ -264,17 +265,14 @@ _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)
{
@ -288,23 +286,19 @@ random_level (void)
static void *
alloc_node_for_level (cairo_skip_list_t *list, unsigned level)
{
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;
if (list->freelists[level-1]) {
skip_elt_t *elt = list->freelists[level-1];
list->freelists[level-1] = elt->prev;
return ELT_DATA(elt);
}
return malloc (list->elt_size
+ (FREELIST_MAX_LEVEL_FOR (level) - 1) * sizeof (skip_elt_t *));
return malloc (list->elt_size + (level-1) * sizeof (skip_elt_t *));
}
static void
free_elt (cairo_skip_list_t *list, skip_elt_t *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;
elt->prev = list->freelists[elt->prev_index];
list->freelists[elt->prev_index] = elt;
}
/*
@ -355,8 +349,6 @@ _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_embedded)
if (spline->points && spline->points != spline->points_embedded)
free (spline->points);
spline->points = spline->points_embedded;
spline->points_size = ARRAY_LENGTH (spline->points_embedded);
spline->points = NULL;
spline->points_size = 0;
spline->num_points = 0;
}
@ -104,12 +104,21 @@ _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) {
new_points = _cairo_malloc_ab (new_size, sizeof (cairo_point_t));
new_points = malloc (new_size * sizeof (cairo_point_t));
if (new_points)
memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t));
} else {
@ -275,8 +284,9 @@ _cairo_spline_decompose (cairo_spline_t *spline, double tolerance)
{
cairo_status_t status;
/* reset the spline, but keep the buffer */
spline->num_points = 0;
if (spline->points_size) {
_cairo_spline_fini (spline);
}
status = _cairo_spline_decompose_into (spline, tolerance * tolerance, spline);
if (status)

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

@ -62,7 +62,7 @@ _cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
if (other->dash == NULL) {
style->dash = NULL;
} else {
style->dash = _cairo_malloc_ab (style->num_dashes, sizeof (double));
style->dash = malloc (style->num_dashes * sizeof (double));
if (style->dash == NULL)
return CAIRO_STATUS_NO_MEMORY;

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

@ -99,7 +99,7 @@ cairo_private cairo_status_t
_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int_t *rects,
cairo_rectangle_int16_t *rects,
int num_rects);
cairo_private cairo_status_t

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

@ -35,16 +35,14 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include "cairoint.h"
#include "cairo-surface-fallback-private.h"
#include "cairo-clip-private.h"
typedef struct {
cairo_surface_t *dst;
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents;
cairo_image_surface_t *image;
cairo_rectangle_int_t image_rect;
cairo_rectangle_int16_t image_rect;
void *image_extra;
} fallback_state_t;
@ -106,7 +104,7 @@ typedef cairo_status_t (*cairo_draw_func_t) (void *clos
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int_t *extents);
const cairo_rectangle_int16_t *extents);
static cairo_status_t
_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
@ -114,7 +112,7 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_int_t *extents)
const cairo_rectangle_int16_t *extents)
{
cairo_surface_t *mask;
cairo_status_t status;
@ -159,7 +157,7 @@ _clip_and_composite_with_mask (cairo_clip_t *clip,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_int_t *extents)
const cairo_rectangle_int16_t *extents)
{
cairo_surface_pattern_t mask_pattern;
cairo_status_t status;
@ -193,7 +191,7 @@ _clip_and_composite_combine (cairo_clip_t *clip,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_int_t *extents)
const cairo_rectangle_int16_t *extents)
{
cairo_surface_t *intermediate;
cairo_surface_pattern_t dst_pattern;
@ -281,7 +279,7 @@ _clip_and_composite_source (cairo_clip_t *clip,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_int_t *extents)
const cairo_rectangle_int16_t *extents)
{
cairo_surface_pattern_t mask_pattern;
cairo_status_t status;
@ -322,7 +320,7 @@ _clip_and_composite_source (cairo_clip_t *clip,
}
static int
_cairo_rectangle_empty (const cairo_rectangle_int_t *rect)
_cairo_rectangle_empty (const cairo_rectangle_int16_t *rect)
{
return rect->width == 0 || rect->height == 0;
}
@ -355,7 +353,7 @@ _clip_and_composite (cairo_clip_t *clip,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_int_t *extents)
const cairo_rectangle_int16_t *extents)
{
cairo_pattern_union_t solid_pattern;
cairo_status_t status;
@ -365,8 +363,7 @@ _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_CONTENT_COLOR);
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
src = &solid_pattern.base;
op = CAIRO_OPERATOR_DEST_OUT;
}
@ -410,19 +407,18 @@ _composite_trap_region (cairo_clip_t *clip,
cairo_pattern_t *src,
cairo_operator_t op,
cairo_surface_t *dst,
cairo_region_t *trap_region,
cairo_rectangle_int_t *extents)
pixman_region16_t *trap_region,
cairo_rectangle_int16_t *extents)
{
cairo_status_t status;
cairo_pattern_union_t solid_pattern;
cairo_pattern_union_t mask;
int num_rects = _cairo_region_num_boxes (trap_region);
int num_rects = pixman_region_num_rects (trap_region);
unsigned int clip_serial;
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_CONTENT_COLOR);
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
src = &solid_pattern.base;
op = CAIRO_OPERATOR_DEST_OUT;
}
@ -456,11 +452,8 @@ _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_status_t status2 = _cairo_surface_set_clip (dst, clip);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
}
if (num_rects >1)
_cairo_surface_set_clip (dst, clip);
if (clip_surface)
_cairo_pattern_fini (&mask.base);
@ -483,7 +476,7 @@ _composite_traps_draw_func (void *closure,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int_t *extents)
const cairo_rectangle_int16_t *extents)
{
cairo_composite_traps_info_t *info = closure;
cairo_pattern_union_t pattern;
@ -492,8 +485,7 @@ _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_CONTENT_COLOR);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
if (!src)
src = &pattern.base;
@ -519,152 +511,145 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
cairo_antialias_t antialias)
{
cairo_status_t status;
cairo_region_t trap_region;
cairo_region_t clear_region;
cairo_bool_t has_trap_region = FALSE;
cairo_bool_t has_clear_region = FALSE;
cairo_rectangle_int_t extents;
pixman_region16_t *trap_region = NULL;
pixman_region16_t *clear_region = NULL;
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_INT_STATUS_UNSUPPORTED == status) {
has_trap_region = FALSE;
} else if (status) {
return status;
} else {
has_trap_region = TRUE;
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;
}
else
{
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int_t trap_extents;
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 (has_trap_region) {
status = _cairo_clip_intersect_to_region (clip, &trap_region);
status = _cairo_clip_intersect_to_region (clip, clear_region);
if (status)
return status;
if (status)
goto out;
_cairo_region_extents_rectangle (clear_region, &extents);
_cairo_region_get_extents (&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_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
return CAIRO_STATUS_NO_MEMORY;
_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.
*/
_cairo_region_init_rect (&clear_region, &extents);
has_clear_region = TRUE;
status = _cairo_clip_intersect_to_region (clip, &clear_region);
if (status)
goto out;
_cairo_region_get_extents (&clear_region, &extents);
status = _cairo_region_subtract (&clear_region, &clear_region, &trap_region);
if (status)
goto out;
if (!_cairo_region_not_empty (&clear_region)) {
_cairo_region_fini (&clear_region);
has_clear_region = FALSE;
}
} else {
status = _cairo_clip_intersect_to_rectangle (clip, &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;
}
}
if (status)
goto out;
goto out;
if (has_trap_region) {
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (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);
/* 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);
if (!status && has_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;
}
}
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;
}
}
}
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 (has_trap_region)
_cairo_region_fini (&trap_region);
if (has_clear_region)
_cairo_region_fini (&clear_region);
out:
if (trap_region)
pixman_region_destroy (trap_region);
if (clear_region)
pixman_region_destroy (clear_region);
return status;
}
@ -675,7 +660,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
cairo_pattern_t *source)
{
cairo_status_t status;
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents;
cairo_box_t box;
cairo_traps_t traps;
@ -684,7 +669,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
cairo_rectangle_int16_t source_extents;
status = _cairo_pattern_get_extents (source, &source_extents);
if (status)
return status;
@ -705,16 +690,16 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
if (status)
return status;
status = _clip_and_composite_trapezoids (source,
op,
surface,
&traps,
surface->clip,
CAIRO_ANTIALIAS_NONE);
_clip_and_composite_trapezoids (source,
op,
surface,
&traps,
surface->clip,
CAIRO_ANTIALIAS_NONE);
_cairo_traps_fini (&traps);
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -724,7 +709,7 @@ _cairo_surface_mask_draw_func (void *closure,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int_t *extents)
const cairo_rectangle_int16_t *extents)
{
cairo_pattern_t *mask = closure;
@ -751,7 +736,7 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
cairo_pattern_t *mask)
{
cairo_status_t status;
cairo_rectangle_int_t extents, source_extents, mask_extents;
cairo_rectangle_int16_t extents, source_extents, mask_extents;
status = _cairo_surface_get_extents (surface, &extents);
if (status)
@ -800,35 +785,9 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
{
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t box;
cairo_rectangle_int_t extents;
status = _cairo_surface_get_extents (surface, &extents);
if (status)
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_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,
@ -839,16 +798,16 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
return status;
}
status = _clip_and_composite_trapezoids (source,
op,
surface,
&traps,
surface->clip,
antialias);
_clip_and_composite_trapezoids (source,
op,
surface,
&traps,
surface->clip,
antialias);
_cairo_traps_fini (&traps);
return status;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -862,35 +821,9 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
{
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t box;
cairo_rectangle_int_t extents;
status = _cairo_surface_get_extents (surface, &extents);
if (status)
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_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,
@ -925,7 +858,7 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int_t *extents)
const cairo_rectangle_int16_t *extents)
{
cairo_show_glyphs_info_t *glyph_info = closure;
cairo_pattern_union_t pattern;
@ -945,8 +878,7 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
}
}
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
if (!src)
src = &pattern.base;
@ -988,7 +920,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents, glyph_extents;
cairo_show_glyphs_info_t glyph_info;
status = _cairo_surface_get_extents (surface, &extents);
@ -996,8 +928,6 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
return status;
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int16_t glyph_extents;
cairo_rectangle_int_t glyph_extents_full;
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs,
num_glyphs,
@ -1005,11 +935,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
if (status)
return status;
glyph_extents_full.x = glyph_extents.x;
glyph_extents_full.y = glyph_extents.y;
glyph_extents_full.width = glyph_extents.width;
glyph_extents_full.height = glyph_extents.height;
_cairo_rectangle_intersect (&extents, &glyph_extents_full);
_cairo_rectangle_intersect (&extents, &glyph_extents);
}
status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
@ -1053,21 +979,17 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
&pattern.base,
NULL,
snapshot,
0, 0,
0, 0,
0, 0,
image->width,
image->height);
_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);
@ -1124,11 +1046,11 @@ cairo_status_t
_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int_t *rects,
cairo_rectangle_int16_t *rects,
int num_rects)
{
fallback_state_t state;
cairo_rectangle_int_t *offset_rects = NULL;
cairo_rectangle_int16_t *offset_rects = NULL;
cairo_status_t status;
int x1, y1, x2, y2;
int i;
@ -1168,7 +1090,7 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
/* If the fetched image isn't at 0,0, we need to offset the rectangles */
if (state.image_rect.x != 0 || state.image_rect.y != 0) {
offset_rects = _cairo_malloc_ab (num_rects, sizeof (cairo_rectangle_int_t));
offset_rects = malloc (sizeof (cairo_rectangle_int16_t) * num_rects);
if (offset_rects == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto DONE;
@ -1224,7 +1146,7 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
/* If the destination image isn't at 0,0, we need to offset the trapezoids */
if (state.image_rect.x != 0 || state.image_rect.y != 0) {
offset_traps = _cairo_malloc_ab (num_traps, sizeof (cairo_trapezoid_t));
offset_traps = malloc (sizeof (cairo_trapezoid_t) * num_traps);
if (!offset_traps) {
status = CAIRO_STATUS_NO_MEMORY;
goto DONE;
@ -1236,14 +1158,13 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
traps = offset_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);
_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);

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

@ -1,4 +1,3 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
@ -36,8 +35,9 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include "cairoint.h"
#include <stdlib.h>
#include "cairoint.h"
#include "cairo-surface-fallback-private.h"
#include "cairo-clip-private.h"
@ -81,7 +81,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 cairo_status_t
static void
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
cairo_surface_t *destination,
cairo_pattern_t *pattern_out);
@ -180,10 +180,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,8 +289,7 @@ cairo_surface_create_similar (cairo_surface_t *other,
return _cairo_surface_create_similar_solid (other, content,
width, height,
CAIRO_COLOR_TRANSPARENT,
NULL);
CAIRO_COLOR_TRANSPARENT);
}
slim_hidden_def (cairo_surface_create_similar);
@ -299,8 +298,7 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
cairo_content_t content,
int width,
int height,
const cairo_color_t *color,
cairo_pattern_t *pattern)
const cairo_color_t *color)
{
cairo_status_t status;
cairo_surface_t *surface;
@ -313,23 +311,19 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
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;
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;
}
status = _cairo_surface_paint (surface,
color == CAIRO_COLOR_TRANSPARENT ?
CAIRO_OPERATOR_CLEAR :
CAIRO_OPERATOR_SOURCE, source);
if (source != pattern)
cairo_pattern_destroy (source);
cairo_pattern_destroy (source);
if (status) {
cairo_surface_destroy (surface);
@ -380,7 +374,7 @@ slim_hidden_def (cairo_surface_reference);
/**
* cairo_surface_destroy:
* @surface: a #cairo_surface_t
* @surface: a #cairo_t
*
* Decreases the reference count on @surface by one. If the result is
* zero, then @surface and all associated resources are freed. See
@ -407,34 +401,6 @@ 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
@ -503,8 +469,10 @@ 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;
}
@ -602,16 +570,13 @@ 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);
}
}
@ -957,9 +922,9 @@ _cairo_surface_release_source_image (cairo_surface_t *surface,
**/
cairo_status_t
_cairo_surface_acquire_dest_image (cairo_surface_t *surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void **image_extra)
{
assert (!surface->finished);
@ -983,9 +948,9 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
**/
void
_cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
assert (!surface->finished);
@ -1092,35 +1057,6 @@ _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,
@ -1195,7 +1131,7 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
int width,
int height)
{
cairo_rectangle_int_t rect;
cairo_rectangle_int16_t rect;
assert (! surface->is_snapshot);
@ -1221,7 +1157,7 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
* @region: the region to modify, in backend coordinates
*
* Applies an operator to a set of rectangles specified as a
* #cairo_region_t using a solid color as the source.
* #pixman_region16_t using a solid color as the source.
* See _cairo_surface_fill_rectangles() for full details.
*
* Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
@ -1230,47 +1166,34 @@ cairo_status_t
_cairo_surface_fill_region (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_region_t *region)
pixman_region16_t *region)
{
int num_boxes;
cairo_box_int_t *boxes;
cairo_rectangle_int_t stack_rects[CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_rectangle_int_t)];
cairo_rectangle_int_t *rects;
int num_rects = pixman_region_num_rects (region);
pixman_box16_t *boxes = pixman_region_rects (region);
cairo_rectangle_int16_t *rects;
cairo_status_t status;
int i;
assert (! surface->is_snapshot);
status = _cairo_region_get_boxes (region, &num_boxes, &boxes);
if (status)
return status;
if (num_boxes == 0)
if (!num_rects)
return CAIRO_STATUS_SUCCESS;
rects = stack_rects;
if (num_boxes > ARRAY_LENGTH (stack_rects)) {
rects = _cairo_malloc_ab (num_boxes, sizeof (cairo_rectangle_int_t));
if (!rects) {
_cairo_region_boxes_fini (region, boxes);
return CAIRO_STATUS_NO_MEMORY;
}
}
rects = malloc (sizeof (pixman_rectangle_t) * num_rects);
if (!rects)
return CAIRO_STATUS_NO_MEMORY;
for (i = 0; i < num_boxes; i++) {
rects[i].x = boxes[i].p1.x;
rects[i].y = boxes[i].p1.y;
rects[i].width = boxes[i].p2.x - boxes[i].p1.x;
rects[i].height = boxes[i].p2.y - boxes[i].p1.y;
for (i = 0; i < num_rects; i++) {
rects[i].x = boxes[i].x1;
rects[i].y = boxes[i].y1;
rects[i].width = boxes[i].x2 - boxes[i].x1;
rects[i].height = boxes[i].y2 - boxes[i].y1;
}
status = _cairo_surface_fill_rectangles (surface, op,
color, rects, num_boxes);
color, rects, num_rects);
_cairo_region_boxes_fini (region, boxes);
if (rects != stack_rects)
free (rects);
free (rects);
return status;
}
@ -1295,7 +1218,7 @@ cairo_status_t
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int_t *rects,
cairo_rectangle_int16_t *rects,
int num_rects)
{
cairo_int_status_t status;
@ -1332,9 +1255,7 @@ _cairo_surface_paint (cairo_surface_t *surface,
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (status)
return status;
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (surface->backend->paint) {
status = surface->backend->paint (surface, op, &dev_source.base);
@ -1362,26 +1283,20 @@ _cairo_surface_mask (cairo_surface_t *surface,
assert (! surface->is_snapshot);
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;
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
_cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
if (surface->backend->mask) {
status = surface->backend->mask (surface, op, &dev_source.base, &dev_mask.base);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto CLEANUP_MASK;
goto FINISH;
}
status = _cairo_surface_fallback_mask (surface, op, &dev_source.base, &dev_mask.base);
CLEANUP_MASK:
_cairo_pattern_fini (&dev_mask.base);
CLEANUP_SOURCE:
_cairo_pattern_fini (&dev_source.base);
FINISH:
_cairo_pattern_fini (&dev_mask.base);
_cairo_pattern_fini (&dev_source.base);
return status;
}
@ -1406,9 +1321,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (status)
return status;
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (surface->backend->stroke) {
status = surface->backend->stroke (surface, op, &dev_source.base,
@ -1447,9 +1360,7 @@ _cairo_surface_fill (cairo_surface_t *surface,
assert (! surface->is_snapshot);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (status)
return status;
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (surface->backend->fill) {
status = surface->backend->fill (surface, op, &dev_source.base,
@ -1519,7 +1430,10 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
traps, num_traps);
}
cairo_status_t
/* _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_surface_copy_page (cairo_surface_t *surface)
{
assert (! surface->is_snapshot);
@ -1530,14 +1444,16 @@ _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_STATUS_SUCCESS;
return CAIRO_INT_STATUS_UNSUPPORTED;
return surface->backend->copy_page (surface);
}
cairo_status_t
/* _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_surface_show_page (cairo_surface_t *surface)
{
assert (! surface->is_snapshot);
@ -1548,9 +1464,8 @@ _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_STATUS_SUCCESS;
return CAIRO_INT_STATUS_UNSUPPORTED;
return surface->backend->show_page (surface);
}
@ -1637,7 +1552,7 @@ _cairo_surface_reset_clip (cairo_surface_t *surface)
/**
* _cairo_surface_set_clip_region:
* @surface: the #cairo_surface_t to reset the clip on
* @region: the #cairo_region_t to use for clipping
* @region: the #pixman_region16_t to use for clipping
* @serial: the clip serial number associated with the region
*
* This function sets the clipping for the surface to
@ -1646,7 +1561,7 @@ _cairo_surface_reset_clip (cairo_surface_t *surface)
*/
cairo_status_t
_cairo_surface_set_clip_region (cairo_surface_t *surface,
cairo_region_t *region,
pixman_region16_t *region,
unsigned int serial)
{
cairo_status_t status;
@ -1785,9 +1700,9 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
clip->path,
clip->serial);
if (clip->has_region)
if (clip->region)
return _cairo_surface_set_clip_region (surface,
&clip->region,
clip->region,
clip->serial);
}
@ -1820,7 +1735,7 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
*/
cairo_status_t
_cairo_surface_get_extents (cairo_surface_t *surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
if (surface->status)
return surface->status;
@ -1849,11 +1764,9 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
if (!num_glyphs)
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_copy_pattern_for_destination (source,
surface,
&dev_source.base);
if (status)
return status;
_cairo_surface_copy_pattern_for_destination (source,
surface,
&dev_source.base);
cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
@ -1874,11 +1787,6 @@ _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);
@ -1948,20 +1856,18 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
static cairo_status_t
_cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
cairo_rectangle_int_t *src_rectangle,
cairo_rectangle_int_t *mask_rectangle,
cairo_rectangle_int16_t *src_rectangle,
cairo_rectangle_int16_t *mask_rectangle,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
{
cairo_rectangle_int_t dst_rectangle;
cairo_rectangle_int_t drawn_rectangle;
cairo_bool_t has_drawn_region = FALSE;
cairo_bool_t has_clear_region = FALSE;
cairo_region_t drawn_region;
cairo_region_t clear_region;
cairo_status_t status;
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;
/* The area that was drawn is the area in the destination rectangle but not within
* the source or the mask.
@ -1974,35 +1880,34 @@ _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
*/
_cairo_region_init_rect (&drawn_region, &drawn_rectangle);
_cairo_region_init_rect (&clear_region, &dst_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;
}
has_drawn_region = TRUE;
has_clear_region = TRUE;
if (_cairo_region_subtract (&clear_region, &clear_region, &drawn_region)
!= CAIRO_STATUS_SUCCESS)
{
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_REGIONS;
if (pixman_region_subtract (clear_region, clear_region, drawn_region) != PIXMAN_REGION_STATUS_SUCCESS) {
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 (has_drawn_region)
_cairo_region_fini (&drawn_region);
if (has_clear_region)
_cairo_region_fini (&clear_region);
CLEANUP_REGIONS:
if (drawn_region)
pixman_region_destroy (drawn_region);
if (clear_region)
pixman_region_destroy (clear_region);
return status;
}
@ -2048,9 +1953,9 @@ _cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
unsigned int width,
unsigned int height)
{
cairo_rectangle_int_t src_tmp, mask_tmp;
cairo_rectangle_int_t *src_rectangle = NULL;
cairo_rectangle_int_t *mask_rectangle = NULL;
cairo_rectangle_int16_t src_tmp, mask_tmp;
cairo_rectangle_int16_t *src_rectangle = NULL;
cairo_rectangle_int16_t *mask_rectangle = NULL;
assert (! dst->is_snapshot);
@ -2123,9 +2028,9 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
unsigned int width,
unsigned int height)
{
cairo_rectangle_int_t src_tmp, mask_tmp;
cairo_rectangle_int_t *src_rectangle = NULL;
cairo_rectangle_int_t *mask_rectangle = NULL;
cairo_rectangle_int16_t src_tmp, mask_tmp;
cairo_rectangle_int16_t *src_rectangle = NULL;
cairo_rectangle_int16_t *mask_rectangle = NULL;
assert (! dst->is_snapshot);
@ -2163,19 +2068,16 @@ _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.
*/
static cairo_status_t
void
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
cairo_surface_t *destination,
cairo_pattern_t *pattern_out)
{
cairo_status_t status;
status = _cairo_pattern_init_copy (pattern_out, pattern);
if (status)
return status;
_cairo_pattern_init_copy (pattern_out, pattern);
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
@ -2185,8 +2087,6 @@ _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

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

@ -1,4 +1,3 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Red Hat, Inc
@ -41,13 +40,15 @@
#include "cairoint.h"
#include "cairo-svg.h"
#include "cairo-svg-surface-private.h"
#include "cairo-svg-test.h"
#include "cairo-path-fixed-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-paginated-private.h"
#include "cairo-paginated-surface-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;
@ -58,7 +59,7 @@ static const cairo_svg_version_t _cairo_svg_versions[] =
CAIRO_SVG_VERSION_1_2
};
#define CAIRO_SVG_VERSION_LAST ARRAY_LENGTH (_cairo_svg_versions)
#define CAIRO_SVG_VERSION_LAST ((int)(sizeof (_cairo_svg_versions) / sizeof (_cairo_svg_versions[0])))
static cairo_bool_t
_cairo_svg_version_has_page_set_support (cairo_svg_version_t version)
@ -80,6 +81,7 @@ 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;
};
@ -113,6 +115,27 @@ 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;
@ -355,7 +378,13 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
surface->id = document->surface_id++;
surface->base_clip = document->clip_id++;
surface->is_base_clip_emitted = FALSE;
_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->xml_node = _cairo_memory_stream_create ();
_cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t));
@ -369,7 +398,6 @@ _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,
@ -409,6 +437,7 @@ _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;
@ -418,8 +447,7 @@ _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");
if (_cairo_array_append (&surface->page_set, &page) != CAIRO_STATUS_SUCCESS)
return NULL;
_cairo_array_append (&surface->page_set, &page);
return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
}
@ -678,27 +706,38 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
}
}
static cairo_status_t
static void
_cairo_svg_document_emit_font_subsets (cairo_svg_document_t *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_foreach_scaled (document->font_subsets,
_cairo_svg_document_emit_font_subset,
document);
_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)
{
@ -719,7 +758,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;
@ -737,7 +776,7 @@ _cairo_svg_surface_create_similar (void *abstract_src,
static cairo_status_t
_cairo_svg_surface_finish (void *abstract_surface)
{
cairo_status_t status, status2;
cairo_status_t status;
cairo_svg_surface_t *surface = abstract_surface;
cairo_svg_document_t *document = surface->document;
cairo_svg_page_t *page;
@ -748,15 +787,11 @@ _cairo_svg_surface_finish (void *abstract_surface)
else
status = CAIRO_STATUS_SUCCESS;
status2 = _cairo_output_stream_destroy (surface->xml_node);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
_cairo_output_stream_destroy (surface->xml_node);
for (i = 0; i < surface->page_set.num_elements; i++) {
page = _cairo_array_index (&surface->page_set, i);
status2 = _cairo_output_stream_destroy (page->xml_node);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
_cairo_output_stream_destroy (page->xml_node);
}
_cairo_array_fini (&surface->page_set);
@ -889,7 +924,7 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *outp
{
cairo_surface_t *surface;
cairo_surface_attributes_t surface_attr;
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents;
cairo_status_t status;
cairo_matrix_t p2u;
@ -906,9 +941,7 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *outp
return status;
p2u = pattern->base.matrix;
status = cairo_matrix_invert (&p2u);
if (status)
return status;
cairo_matrix_invert (&p2u);
if (pattern_id != invalid_pattern_id) {
_cairo_output_stream_printf (output,
@ -945,14 +978,12 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *outp
return status;
}
static cairo_status_t
static int
_cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
cairo_meta_surface_t *surface,
int *id)
cairo_meta_surface_t *surface)
{
cairo_status_t status;
cairo_surface_t *paginated_surface;
cairo_svg_surface_t *svg_surface;
cairo_surface_t *svg_surface;
cairo_meta_snapshot_t new_snapshot;
cairo_array_t *page_set;
@ -960,7 +991,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;
unsigned int i, id;
/* search in already emitted meta snapshots */
num_elements = document->meta_snapshots.num_elements;
@ -969,8 +1000,7 @@ _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)) {
*id = snapshot->id;
return CAIRO_STATUS_SUCCESS;
return snapshot->id;
}
}
@ -979,41 +1009,16 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
meta->content,
meta->width_pixels,
meta->height_pixels);
svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface);
svg_surface = _cairo_paginated_surface_get_target (paginated_surface);
cairo_surface_set_fallback_resolution (paginated_surface,
document->owner->x_fallback_resolution,
document->owner->y_fallback_resolution);
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;
}
_cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
_cairo_surface_show_page (paginated_surface);
new_snapshot.meta = meta;
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);
}
new_snapshot.id = ((cairo_svg_surface_t *) svg_surface)->id;
_cairo_array_append (&document->meta_snapshots, &new_snapshot);
if (meta->content == CAIRO_CONTENT_ALPHA) {
_cairo_svg_surface_emit_alpha_filter (document);
@ -1021,21 +1026,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",
svg_surface->id,
svg_surface->base_clip);
((cairo_svg_surface_t *) svg_surface)->id,
((cairo_svg_surface_t *) svg_surface)->base_clip);
} else {
_cairo_output_stream_printf (document->xml_node_defs,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
svg_surface->id,
svg_surface->base_clip);
((cairo_svg_surface_t *) svg_surface)->id,
((cairo_svg_surface_t *) svg_surface)->base_clip);
}
contents = svg_surface->xml_node;
page_set = &svg_surface->page_set;
contents = ((cairo_svg_surface_t *) svg_surface)->xml_node;
page_set = &((cairo_svg_surface_t *) svg_surface)->page_set;
if (_cairo_memory_stream_length (contents) > 0)
_cairo_svg_surface_store_page (svg_surface);
_cairo_svg_surface_store_page ((cairo_svg_surface_t *) svg_surface);
if (page_set->num_elements > 0) {
cairo_svg_page_t *page;
@ -1046,7 +1051,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);
@ -1057,7 +1062,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
/* cairo_surface_destroy (svg_surface); */
return CAIRO_STATUS_SUCCESS;
return id;
}
static cairo_status_t
@ -1070,19 +1075,14 @@ _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;
status = _cairo_svg_surface_emit_meta_surface (document, meta_surface, &id);
if (status)
return status;
id = _cairo_svg_surface_emit_meta_surface (document, meta_surface);
p2u = pattern->base.matrix;
cairo_matrix_invert (&p2u);
if (pattern_id != invalid_pattern_id) {
_cairo_output_stream_printf (output,
@ -1152,7 +1152,7 @@ _cairo_svg_surface_emit_operator (cairo_output_stream_t *output,
_cairo_output_stream_printf (output, "comp-op: %s; ", op_str[op]);
}
static cairo_status_t
static void
_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
cairo_solid_pattern_t *pattern,
cairo_output_stream_t *style,
@ -1166,11 +1166,9 @@ _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 cairo_status_t
static void
_cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface,
cairo_surface_pattern_t *pattern,
cairo_output_stream_t *style,
@ -1187,8 +1185,6 @@ _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
@ -1198,7 +1194,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
cairo_bool_t reverse_stops,
cairo_bool_t emulate_reflect)
{
cairo_gradient_stop_t *stops;
pixman_gradient_stop_t *stops;
double offset;
unsigned int n_stops;
unsigned int i;
@ -1212,16 +1208,16 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
_cairo_fixed_to_double (pattern->stops[0].x),
pattern->stops[0].color.red * 100.0,
pattern->stops[0].color.green * 100.0,
pattern->stops[0].color.blue * 100.0,
pattern->stops[0].color.alpha);
pattern->stops[0].color.red / 655.35,
pattern->stops[0].color.green / 655.35,
pattern->stops[0].color.blue / 655.35,
pattern->stops[0].color.alpha / 65535.0);
return;
}
if (emulate_reflect || reverse_stops) {
n_stops = emulate_reflect ? pattern->n_stops * 2 - 2: pattern->n_stops;
stops = _cairo_malloc_ab (n_stops, sizeof (cairo_gradient_stop_t));
stops = malloc (sizeof (pixman_gradient_stop_t) * n_stops);
for (i = 0; i < pattern->n_stops; i++) {
if (reverse_stops) {
@ -1260,22 +1256,22 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
offset,
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
stops[i].color.blue * 100.0,
stops[i].color.alpha);
stops[i].color.red / 655.35,
stops[i].color.green / 655.35,
stops[i].color.blue / 655.35,
stops[i].color.alpha / 65535.0);
}
else {
cairo_bool_t found = FALSE;
unsigned int offset_index;
cairo_color_t offset_color_start, offset_color_stop;
pixman_color_t offset_color_start, offset_color_stop;
for (i = 0; i < n_stops; i++) {
if (_cairo_fixed_to_double (stops[i].x) >= -start_offset) {
if (i > 0) {
if (stops[i].x != stops[i-1].x) {
double x0, x1;
cairo_color_t *color0, *color1;
pixman_color_t *color0, *color1;
x0 = _cairo_fixed_to_double (stops[i-1].x);
x1 = _cairo_fixed_to_double (stops[i].x);
@ -1311,20 +1307,20 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
"<stop offset=\"0\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
offset_color_start.red * 100.0,
offset_color_start.green * 100.0,
offset_color_start.blue * 100.0,
offset_color_start.alpha);
offset_color_start.red / 655.35,
offset_color_start.green / 655.35,
offset_color_start.blue / 655.35,
offset_color_start.alpha / 65535.0);
for (i = offset_index; i < n_stops; i++) {
_cairo_output_stream_printf (output,
"<stop offset=\"%f\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
_cairo_fixed_to_double (stops[i].x) + start_offset,
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
stops[i].color.blue * 100.0,
stops[i].color.alpha);
stops[i].color.red / 655.35,
stops[i].color.green / 655.35,
stops[i].color.blue / 655.35,
stops[i].color.alpha / 65535.0);
}
for (i = 0; i < offset_index; i++) {
_cairo_output_stream_printf (output,
@ -1332,20 +1328,20 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
1.0 + _cairo_fixed_to_double (stops[i].x) + start_offset,
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
stops[i].color.blue * 100.0,
stops[i].color.alpha);
stops[i].color.red / 655.35,
stops[i].color.green / 655.35,
stops[i].color.blue / 655.35,
stops[i].color.alpha / 65535.0);
}
_cairo_output_stream_printf (output,
"<stop offset=\"1\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
offset_color_stop.red * 100.0,
offset_color_stop.green * 100.0,
offset_color_stop.blue * 100.0,
offset_color_stop.alpha);
offset_color_stop.red / 655.35,
offset_color_stop.green / 655.35,
offset_color_stop.blue / 655.35,
offset_color_stop.alpha / 65535.0);
}
@ -1370,7 +1366,7 @@ _cairo_svg_surface_emit_pattern_extend (cairo_output_stream_t *output,
}
}
static cairo_status_t
static void
_cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
cairo_linear_pattern_t *pattern,
cairo_output_stream_t *style,
@ -1379,17 +1375,11 @@ _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->p1.x);
y0 = _cairo_fixed_to_double (pattern->p1.y);
x1 = _cairo_fixed_to_double (pattern->p2.x);
y1 = _cairo_fixed_to_double (pattern->p2.y);
x0 = _cairo_fixed_to_double (pattern->gradient.p1.x);
y0 = _cairo_fixed_to_double (pattern->gradient.p1.y);
x1 = _cairo_fixed_to_double (pattern->gradient.p2.x);
y1 = _cairo_fixed_to_double (pattern->gradient.p2.y);
_cairo_output_stream_printf (document->xml_node_defs,
"<linearGradient id=\"linear%d\" "
@ -1399,6 +1389,8 @@ _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);
@ -1412,11 +1404,9 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
document->linear_pattern_id);
document->linear_pattern_id++;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
static void
_cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
cairo_radial_pattern_t *pattern,
cairo_output_stream_t *style,
@ -1428,39 +1418,31 @@ _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;
cairo_point_t *c0, *c1;
cairo_fixed_t radius0, radius1;
pixman_circle_t *c0, *c1;
extend = pattern->base.base.extend;
if (pattern->r1 < pattern->r2) {
c0 = &pattern->c1;
c1 = &pattern->c2;
radius0 = pattern->r1;
radius1 = pattern->r2;
if (pattern->gradient.c1.radius < pattern->gradient.c2.radius) {
c0 = &pattern->gradient.c1;
c1 = &pattern->gradient.c2;
reverse_stops = FALSE;
} else {
c0 = &pattern->c2;
c1 = &pattern->c1;
radius0 = pattern->r2;
radius1 = pattern->r1;
c0 = &pattern->gradient.c2;
c1 = &pattern->gradient.c1;
reverse_stops = TRUE;
}
x0 = _cairo_fixed_to_double (c0->x);
y0 = _cairo_fixed_to_double (c0->y);
r0 = _cairo_fixed_to_double (radius0);
r0 = _cairo_fixed_to_double (c0->radius);
x1 = _cairo_fixed_to_double (c1->x);
y1 = _cairo_fixed_to_double (c1->y);
r1 = _cairo_fixed_to_double (radius1);
r1 = _cairo_fixed_to_double (c1->radius);
p2u = pattern->base.base.matrix;
status = cairo_matrix_invert (&p2u);
if (status)
return status;
cairo_matrix_invert (&p2u);
if (pattern->r1 == pattern->r2) {
if (pattern->gradient.c1.radius == pattern->gradient.c2.radius) {
_cairo_output_stream_printf (document->xml_node_defs,
"<radialGradient id=\"radial%d\" "
"gradientUnits=\"userSpaceOnUse\" "
@ -1483,19 +1465,19 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
"<stop offset=\"0\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
pattern->base.stops[0].color.red * 100.0,
pattern->base.stops[0].color.green * 100.0,
pattern->base.stops[0].color.blue * 100.0,
pattern->base.stops[0].color.alpha);
pattern->base.stops[0].color.red / 655.35,
pattern->base.stops[0].color.green / 655.35,
pattern->base.stops[0].color.blue / 655.35,
pattern->base.stops[0].color.alpha / 65535.0);
if (pattern->base.n_stops > 1)
_cairo_output_stream_printf (document->xml_node_defs,
"<stop offset=\"0\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
pattern->base.stops[1].color.red * 100.0,
pattern->base.stops[1].color.green * 100.0,
pattern->base.stops[1].color.blue * 100.0,
pattern->base.stops[1].color.alpha);
pattern->base.stops[1].color.red / 655.35,
pattern->base.stops[1].color.green / 655.35,
pattern->base.stops[1].color.blue / 655.35,
pattern->base.stops[1].color.alpha / 65535.0);
}
} else {
@ -1589,28 +1571,29 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
document->radial_pattern_id);
document->radial_pattern_id++;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
static void
_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:
return _cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke);
_cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke);
break;
case CAIRO_PATTERN_TYPE_SURFACE:
return _cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke);
_cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke);
break;
case CAIRO_PATTERN_TYPE_LINEAR:
return _cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
_cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
break;
case CAIRO_PATTERN_TYPE_RADIAL:
return _cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
_cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
break;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@ -1628,7 +1611,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; "
@ -1648,7 +1631,7 @@ _cairo_svg_surface_fill (void *abstract_surface,
static cairo_int_status_t
_cairo_svg_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_svg_surface_t *surface = abstract_surface;
@ -1703,7 +1686,6 @@ _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)
@ -1716,7 +1698,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
@ -1729,12 +1711,8 @@ _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))
{
status = _cairo_output_stream_destroy (surface->xml_node);
if (status)
return status;
op == CAIRO_OPERATOR_SOURCE)) {
_cairo_output_stream_destroy (surface->xml_node);
surface->xml_node = _cairo_memory_stream_create ();
if (op == CAIRO_OPERATOR_CLEAR) {
@ -1762,7 +1740,6 @@ _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;
@ -1771,7 +1748,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);
@ -1788,10 +1765,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
" </g>\n"
"</mask>\n");
_cairo_memory_stream_copy (mask_stream, document->xml_node_defs);
status = _cairo_output_stream_destroy (mask_stream);
if (status)
return status;
_cairo_output_stream_destroy (mask_stream);
snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d);\"",
document->mask_id);
@ -1821,7 +1795,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:
@ -1903,13 +1877,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;
cairo_scaled_font_subsets_glyph_t subset_glyph;
unsigned int font_id, subset_id, subset_glyph_index;
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;
@ -1927,7 +1901,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,
&subset_glyph);
&font_id, &subset_id, &subset_glyph_index);
if (status) {
glyphs += i;
num_glyphs -= i;
@ -1937,8 +1911,7 @@ _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",
subset_glyph.font_id,
subset_glyph.subset_glyph_index,
font_id, subset_glyph_index,
glyphs[i].x, glyphs[i].y);
}
@ -2061,7 +2034,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_scaled ();
document->font_subsets = _cairo_scaled_font_subsets_create (0, INT_MAX);
if (document->font_subsets == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
free (document);
@ -2119,7 +2092,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, status2;
cairo_status_t status;
cairo_output_stream_t *output = document->output_stream;
cairo_meta_snapshot_t *snapshot;
cairo_svg_surface_t *surface;
@ -2139,10 +2112,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
document->width, document->height,
_cairo_svg_internal_version_strings [document->svg_version]);
status = _cairo_svg_document_emit_font_subsets (document);
if (status)
return status;
_cairo_svg_document_emit_font_subsets (document);
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");
@ -2166,8 +2136,10 @@ _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\">\n",
page->surface_id);
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
page->surface_id,
page->clip_id);
_cairo_memory_stream_copy (page->xml_node, output);
_cairo_output_stream_printf (output, "</g>\n</page>\n");
}
@ -2175,23 +2147,20 @@ _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\">\n",
page->surface_id);
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
page->surface_id,
page->clip_id);
_cairo_memory_stream_copy (page->xml_node, output);
_cairo_output_stream_printf (output, "</g>\n");
}
_cairo_output_stream_printf (output, "</svg>\n");
status = _cairo_output_stream_destroy (document->xml_node_glyphs);
_cairo_output_stream_destroy (document->xml_node_glyphs);
_cairo_output_stream_destroy (document->xml_node_defs);
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;
status = _cairo_output_stream_destroy (output);
for (i = 0; i < document->meta_snapshots.num_elements; i++) {
snapshot = _cairo_array_index (&document->meta_snapshots, i);

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

@ -1,4 +1,3 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/*
* Copyright © 2002 Keith Packard
* Copyright © 2007 Red Hat, Inc.
@ -44,7 +43,7 @@
static cairo_status_t
_cairo_traps_grow (cairo_traps_t *traps);
static void
static cairo_status_t
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right);
@ -58,21 +57,10 @@ _cairo_traps_init (cairo_traps_t *traps)
traps->num_traps = 0;
traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
traps->traps = traps->traps_embedded;
traps->traps_size = 0;
traps->traps = NULL;
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
@ -99,104 +87,45 @@ cairo_status_t
_cairo_traps_init_box (cairo_traps_t *traps,
cairo_box_t *box)
{
_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;
_cairo_traps_init (traps);
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;
}
cairo_status_t
_cairo_traps_status (cairo_traps_t *traps)
{
return traps->status;
}
static void
static cairo_status_t
_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;
return traps->status;
/* 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 (top == bottom) {
return CAIRO_STATUS_SUCCESS;
}
if (traps->num_traps >= traps->traps_size) {
traps->status = _cairo_traps_grow (traps);
if (traps->status)
return;
return traps->status;
}
trap = &traps->traps[traps->num_traps];
@ -228,9 +157,11 @@ _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;
}
void
cairo_status_t
_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)
@ -239,7 +170,7 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair
cairo_line_t right;
if (traps->status)
return;
return traps->status;
left.p1 = left_p1;
left.p2 = left_p2;
@ -247,7 +178,7 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair
right.p1 = right_p1;
right.p2 = right_p2;
_cairo_traps_add_trap (traps, top, bottom, &left, &right);
return _cairo_traps_add_trap (traps, top, bottom, &left, &right);
}
/* make room for at least one more trap */
@ -255,15 +186,27 @@ static cairo_status_t
_cairo_traps_grow (cairo_traps_t *traps)
{
cairo_trapezoid_t *new_traps;
int new_size = 2 * MAX (traps->traps_size, 16);
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);
if (traps->status)
return traps->status;
if (traps->traps == traps->traps_embedded) {
new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
new_traps = malloc (new_size * sizeof (cairo_trapezoid_t));
if (new_traps)
memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
memcpy (new_traps, traps->traps, old_size * sizeof (cairo_trapezoid_t));
} else {
new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t));
}
@ -276,7 +219,7 @@ _cairo_traps_grow (cairo_traps_t *traps)
traps->traps = new_traps;
traps->traps_size = new_size;
return CAIRO_STATUS_SUCCESS;
return traps->status;
}
static int
@ -349,16 +292,21 @@ _cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
cairo_fixed_t ysc = _cairo_fixed_from_double (sy);
for (i = 0; i < num_traps; i++) {
offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc);
offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc);
offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc);
offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc);
offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc);
offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc);
offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc);
offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc);
offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc);
offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc);
#define FIXED_MUL(_a, _b) \
(_cairo_int64_to_int32(_cairo_int64_rsl(_cairo_int32x32_64_mul((_a), (_b)), 16)))
offset_traps[i].top = FIXED_MUL(src_traps[i].top + yoff, ysc);
offset_traps[i].bottom = FIXED_MUL(src_traps[i].bottom + yoff, ysc);
offset_traps[i].left.p1.x = FIXED_MUL(src_traps[i].left.p1.x + xoff, xsc);
offset_traps[i].left.p1.y = FIXED_MUL(src_traps[i].left.p1.y + yoff, ysc);
offset_traps[i].left.p2.x = FIXED_MUL(src_traps[i].left.p2.x + xoff, xsc);
offset_traps[i].left.p2.y = FIXED_MUL(src_traps[i].left.p2.y + yoff, ysc);
offset_traps[i].right.p1.x = FIXED_MUL(src_traps[i].right.p1.x + xoff, xsc);
offset_traps[i].right.p1.y = FIXED_MUL(src_traps[i].right.p1.y + yoff, ysc);
offset_traps[i].right.p2.x = FIXED_MUL(src_traps[i].right.p2.x + xoff, xsc);
offset_traps[i].right.p2.y = FIXED_MUL(src_traps[i].right.p2.y + yoff, ysc);
#undef FIXED_MUL
}
}
}
@ -575,30 +523,32 @@ _cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
*extents = traps->extents;
}
#define STACK_BOXES_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof(cairo_box_int_t)))
/**
* _cairo_traps_extract_region:
* @traps: a #cairo_traps_t
* @region: a #cairo_region_t
* @region: on return, %NULL is stored here if the trapezoids aren't
* exactly representable as a pixman region, otherwise a
* a pointer to such a region, newly allocated.
* (free with pixman region destroy)
*
* Determines if a set of trapezoids are exactly representable as a
* cairo region. If so, the passed-in region is initialized to
* the area representing the given traps. It should be finalized
* with _cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED
* is returned.
* pixman region, and if so creates such a region.
*
* Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
* or %CAIRO_STATUS_NO_MEMORY
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
**/
cairo_int_status_t
_cairo_traps_extract_region (cairo_traps_t *traps,
cairo_region_t *region)
cairo_status_t
_cairo_traps_extract_region (cairo_traps_t *traps,
pixman_region16_t **region)
{
cairo_box_int_t stack_boxes[STACK_BOXES_LEN];
cairo_box_int_t *boxes = stack_boxes;
int i, box_count;
cairo_int_status_t status;
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;
}
for (i = 0; i < traps->num_traps; i++)
if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
@ -607,45 +557,31 @@ _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))) {
return CAIRO_INT_STATUS_UNSUPPORTED;
*region = NULL;
return CAIRO_STATUS_SUCCESS;
}
if (traps->num_traps > ARRAY_LENGTH(stack_boxes)) {
boxes = _cairo_malloc_ab (traps->num_traps, sizeof(cairo_box_int_t));
if (boxes == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
box_count = 0;
*region = pixman_region_create ();
for (i = 0; i < traps->num_traps; i++) {
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);
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;
/* XXX: Sometimes we get degenerate trapezoids from the tesellator;
* skip these.
/* 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.
*/
if (x1 == x2 || y1 == y2)
continue;
if (width == 0 || height == 0)
continue;
boxes[box_count].p1.x = x1;
boxes[box_count].p1.y = y1;
boxes[box_count].p2.x = x2;
boxes[box_count].p2.y = y2;
box_count++;
if (pixman_region_union_rect (*region, *region,
x, y, width, height) != PIXMAN_REGION_STATUS_SUCCESS) {
pixman_region_destroy (*region);
return CAIRO_STATUS_NO_MEMORY;
}
}
status = _cairo_region_init_boxes (region, boxes, box_count);
if (boxes != stack_boxes)
free (boxes);
if (status)
_cairo_region_fini (region);
return status;
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,6 +75,8 @@ 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
@ -82,7 +84,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_t status = CAIRO_STATUS_NO_MEMORY;
cairo_truetype_font_t *font;
const cairo_scaled_font_backend_t *backend;
tt_head_t head;
@ -129,22 +131,16 @@ _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;
status = backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_name, 0, (unsigned char *) name,
&size);
if (status)
goto fail0;
backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_name, 0, (unsigned char *) name,
&size);
font = malloc (sizeof (cairo_truetype_font_t));
if (font == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
if (font == NULL)
goto fail0;
}
font->backend = backend;
font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs);
@ -153,21 +149,15 @@ _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));
status = _cairo_array_grow_by (&font->output, 4096);
if (status)
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
goto fail1;
font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t));
if (font->glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail1;
}
if (font->glyphs == NULL)
goto fail2;
font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int));
if (font->parent_to_subset == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail2;
}
if (font->parent_to_subset == NULL)
goto fail3;
font->base.num_glyphs = 0;
font->base.x_min = (int16_t) be16_to_cpu (head.x_min);
@ -208,11 +198,8 @@ _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) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail3;
}
if (font->base.base_font == NULL)
goto fail4;
snprintf(font->base.base_font, 30, "CairoFont-%u-%u",
scaled_font_subset->font_id,
scaled_font_subset->subset_id);
@ -226,15 +213,12 @@ _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) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail4;
}
if (font->base.widths == NULL)
goto fail5;
_cairo_array_init (&font->string_offsets, sizeof (unsigned long));
status = _cairo_array_grow_by (&font->string_offsets, 10);
if (status)
goto fail5;
if (_cairo_array_grow_by (&font->string_offsets, 10) != CAIRO_STATUS_SUCCESS)
goto fail6;
font->status = CAIRO_STATUS_SUCCESS;
@ -242,22 +226,21 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
return CAIRO_STATUS_SUCCESS;
fail5:
_cairo_array_fini (&font->string_offsets);
fail6:
free (font->base.widths);
fail4:
fail5:
free (font->base.base_font);
fail3:
fail4:
free (font->parent_to_subset);
fail2:
fail3:
free (font->glyphs);
fail1:
fail2:
_cairo_array_fini (&font->output);
fail1:
free (font);
fail0:
if (name)
free (name);
return status;
}
@ -339,27 +322,19 @@ cairo_truetype_font_align_output (cairo_truetype_font_t *font)
return aligned;
}
static cairo_status_t
static void
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)
{
status = _cairo_array_append (&font->string_offsets,
&font->last_boundary);
if (status)
return status;
_cairo_array_append(&font->string_offsets, &font->last_boundary);
font->last_offset = font->last_boundary;
}
font->last_boundary = boundary;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
static int
cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -385,12 +360,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 - 1); /* end count[0] */
cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 2); /* 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, 0x1000); /* delta[0] */
cairo_truetype_font_write_be16 (font, 0x1001); /* 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] */
@ -398,17 +373,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);
cairo_truetype_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1));
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);
cairo_truetype_font_write_be16 (font, i + 1);
return font->status;
}
static cairo_status_t
static int
cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -422,17 +397,11 @@ 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);
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;
/* XXX: Need to check status here. */
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, buffer, &size);
return 0;
}
static void
@ -469,10 +438,11 @@ cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
} while (has_more_components);
}
static cairo_status_t
static int
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;
@ -485,11 +455,8 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
} u;
size = sizeof (tt_head_t);
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;
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_head, 0, (unsigned char*) &header, &size);
if (be16_to_cpu (header.index_to_loc_format) == 0)
size = sizeof (int16_t) * (font->num_glyphs_in_face + 1);
@ -501,7 +468,6 @@ 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;
@ -523,23 +489,15 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
size = end - begin;
next = cairo_truetype_font_align_output (font);
font->status = cairo_truetype_font_check_boundary (font, next);
if (font->status)
break;
cairo_truetype_font_check_boundary (font, next);
font->glyphs[i].location = next - start_offset;
font->status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
if (font->status)
status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
if (status)
break;
if (size != 0) {
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_glyf, begin, buffer, &size);
if (font->status)
break;
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_glyf, begin, buffer, &size);
cairo_truetype_font_remap_composite_glyph (font, buffer);
}
}
@ -552,7 +510,7 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
return font->status;
}
static cairo_status_t
static int
cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -560,52 +518,36 @@ cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
unsigned long size;
size = 0;
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, NULL, &size);
if (font->status)
return font->status;
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, NULL, &size);
font->checksum_index = _cairo_array_num_elements (&font->output) + 8;
font->status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
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;
font->backend->load_truetype_table( font->scaled_font_subset->scaled_font,
tag, 0, buffer, &size);
/* set checkSumAdjustment to 0 for table checksum calcualtion */
*(uint32_t *)(buffer + 8) = 0;
return font->status;
}
static cairo_status_t
cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag)
static int 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);
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;
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, (unsigned char *) hhea, &size);
hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs));
return font->status;
}
static cairo_status_t
static int
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;
@ -615,22 +557,15 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
int num_hmetrics;
size = sizeof (tt_hhea_t);
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;
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hhea, 0, (unsigned char*) &hhea, &size);
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);
font->status = cairo_truetype_font_allocate_write_buffer (font, long_entry_size,
(unsigned char **) &p);
if (font->status)
return font->status;
status = cairo_truetype_font_allocate_write_buffer (font, long_entry_size,
(unsigned char **) &p);
if (font->glyphs[i].parent_index < num_hmetrics) {
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
@ -649,13 +584,11 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
return font->status;
}
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->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->base.widths[i] = be16_to_cpu (p[0]);
}
@ -663,7 +596,7 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
return font->status;
}
static cairo_status_t
static int
cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -672,11 +605,8 @@ cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
unsigned long size;
size = sizeof(tt_head_t);
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;
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_head, 0, (unsigned char*) &header, &size);
if (be16_to_cpu (header.index_to_loc_format) == 0)
{
@ -690,7 +620,7 @@ cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
return font->status;
}
static cairo_status_t
static int
cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -699,15 +629,39 @@ 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);
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;
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, (unsigned char *) maxp, &size);
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;
}
@ -715,7 +669,7 @@ cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
typedef struct table table_t;
struct table {
unsigned long tag;
cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag);
int (*write) (cairo_truetype_font_t *font, unsigned long tag);
int pos; /* position in the font directory */
};
@ -738,7 +692,8 @@ 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_prep, cairo_truetype_font_write_generic_table, 10 },
{ TT_TAG_post, cairo_truetype_font_write_post_table, 10 },
{ TT_TAG_prep, cairo_truetype_font_write_generic_table, 11 },
};
static cairo_status_t
@ -821,7 +776,6 @@ 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;
@ -841,12 +795,7 @@ 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);
status = cairo_truetype_font_check_boundary (font, next);
if (status) {
font->status = status;
goto fail;
}
cairo_truetype_font_check_boundary (font, next);
start = next;
}
@ -883,7 +832,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 = NULL;
cairo_truetype_font_t *font;
cairo_status_t status;
const char *data = NULL; /* squelch bogus compiler warning */
unsigned long length = 0; /* squelch bogus compiler warning */
@ -896,6 +845,10 @@ _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);
@ -907,22 +860,19 @@ _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) {
status = CAIRO_STATUS_NO_MEMORY;
if (truetype_subset->base_font == NULL)
goto fail1;
}
/* The widths array returned must contain only widths for the
* glyphs in font_subset. Any subglyphs appended after
* font_subset->num_glyphs are omitted. */
/* 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. */
truetype_subset->widths = calloc (sizeof (double),
font->scaled_font_subset->num_glyphs);
if (truetype_subset->widths == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
if (truetype_subset->widths == NULL)
goto fail2;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em;
truetype_subset->widths[i] = (double)font->base.widths[i + 1]/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;
@ -932,28 +882,19 @@ _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) {
status = CAIRO_STATUS_NO_MEMORY;
if (truetype_subset->data == NULL)
goto fail3;
}
memcpy (truetype_subset->data, data, length);
truetype_subset->data_length = length;
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;
}
offsets_length = num_strings * sizeof (unsigned long);
truetype_subset->string_offsets = malloc (offsets_length);
if (truetype_subset->string_offsets == NULL)
goto fail4;
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;
}
memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
truetype_subset->num_string_offsets = num_strings;
cairo_truetype_font_destroy (font);

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

@ -39,11 +39,6 @@
#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;
@ -95,7 +90,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);
@ -106,7 +101,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
&font_matrix,
&ctm,
&font_options);
if (font->type1_scaled_font->status)
if (font->type1_scaled_font == NULL)
goto fail;
_cairo_array_init (&font->contents, sizeof (unsigned char));
@ -161,9 +156,7 @@ 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,
cairo_charstring_type_t type)
charstring_encode_integer (cairo_array_t *data, int i)
{
cairo_status_t status;
int orig_size;
@ -181,19 +174,11 @@ charstring_encode_integer (cairo_array_t *data,
*p++ = (i >> 8)+ 251;
*p++ = i & 0xff;
} else {
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;
}
*p++ = 0xff;
*p++ = i >> 24;
*p++ = (i >> 16) & 0xff;
*p++ = (i >> 8) & 0xff;
*p++ = i & 0xff;
}
/* Ensure the array doesn't grow, which allows this function to
@ -208,7 +193,6 @@ charstring_encode_integer (cairo_array_t *data,
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
@ -225,8 +209,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, path_info->type);
charstring_encode_integer (path_info->data, dy, path_info->type);
charstring_encode_integer (path_info->data, dx);
charstring_encode_integer (path_info->data, dy);
path_info->current_x += dx;
path_info->current_y += dy;
@ -249,8 +233,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, path_info->type);
charstring_encode_integer (path_info->data, dy, path_info->type);
charstring_encode_integer (path_info->data, dx);
charstring_encode_integer (path_info->data, dy);
path_info->current_x += dx;
path_info->current_y += dy;
@ -279,12 +263,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, 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);
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);
path_info->current_x += dx1 + dx2 + dx3;
path_info->current_y += dy1 + dy2 + dy3;
charstring_encode_command (path_info->data, CHARSTRING_rcurveto);
@ -298,9 +282,6 @@ _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;
@ -328,7 +309,7 @@ charstring_encrypt (cairo_array_t *data)
}
static cairo_int_status_t
create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type)
create_notdef_charstring (cairo_array_t *data)
{
cairo_status_t status;
@ -339,15 +320,13 @@ create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type)
if (status)
return status;
if (type == CAIRO_CHARSTRING_TYPE1) {
charstring_encode_integer (data, 0, type);
charstring_encode_integer (data, 0, type);
charstring_encode_integer (data, 0);
charstring_encode_integer (data, 0);
/* The width and height is arbitrary. */
charstring_encode_integer (data, 500, type);
charstring_encode_integer (data, 500, type);
charstring_encode_command (data, CHARSTRING_sbw);
}
/* The width and height is arbitrary. */
charstring_encode_integer (data, 500);
charstring_encode_integer (data, 500);
charstring_encode_command (data, CHARSTRING_sbw);
charstring_encode_command (data, CHARSTRING_endchar);
@ -355,11 +334,10 @@ create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type)
}
static cairo_int_status_t
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_type1_font_create_charstring (cairo_type1_font_t *font,
int subset_index,
int glyph_index,
cairo_array_t *data)
{
cairo_int_status_t status;
cairo_scaled_glyph_t *scaled_glyph;
@ -391,29 +369,21 @@ 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->x_advance;
font->widths[subset_index] = metrics->width;
status = _cairo_array_grow_by (data, 30);
if (status)
return status;
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);
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);
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.type = type;
path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
status = _cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD,
_charstring_move_to,
@ -451,7 +421,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 = 1; i < font->scaled_font_subset->num_glyphs; i++) {
for (i = 0; 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);
@ -459,7 +429,6 @@ 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;
@ -479,7 +448,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, CAIRO_CHARSTRING_TYPE1);
status = create_notdef_charstring (&data);
if (status)
goto fail;
charstring_encrypt (&data);
@ -499,18 +468,28 @@ 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 [0.001 0 0 0.001 0 0] readonly def\n",
"/FontMatrix [%f %f %f %f 0 0] readonly def\n",
name,
name);
name,
matrix.xx,
matrix.yx,
matrix.xy,
matrix.yy);
/* We don't know the bbox values until after the charstrings have
* been generated. Reserve some space and fill in the bbox
@ -579,7 +558,6 @@ 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;
@ -619,10 +597,10 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
"dup /FontName get exch definefont pop\n"
"mark currentfile closefile\n");
fail:
status2 = _cairo_output_stream_destroy (encrypted_output);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
status = _cairo_output_stream_get_status (encrypted_output);
fail:
_cairo_output_stream_destroy (encrypted_output);
return status;
}
@ -694,18 +672,14 @@ cairo_type1_font_generate (cairo_type1_font_t *font, const char *name)
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
static void
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);
status = _cairo_output_stream_destroy (font->output);
_cairo_output_stream_destroy (font->output);
free (font);
return status;
}
static cairo_status_t
@ -771,14 +745,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;
return cairo_type1_font_destroy (font);
cairo_type1_font_destroy (font);
return CAIRO_STATUS_SUCCESS;
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;
@ -811,83 +785,3 @@ _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,8 +46,6 @@
#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;
@ -1135,6 +1133,9 @@ _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;
@ -1194,30 +1195,3 @@ _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;
}

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

@ -40,7 +40,9 @@
* Owen Taylor <otaylor@redhat.com>
*/
#include "cairoint.h"
#include <limits.h>
#include <cairoint.h>
#define UTF8_COMPUTE(Char, Mask, Len) \
if (Char < 128) \
@ -240,7 +242,7 @@ _cairo_utf8_to_ucs4 (const unsigned char *str,
in = UTF8_NEXT_CHAR (in);
}
str32 = _cairo_malloc_ab (n_chars + 1, sizeof (uint32_t));
str32 = malloc (sizeof (uint32_t) * (n_chars + 1));
if (!str32)
return CAIRO_STATUS_NO_MEMORY;
@ -307,7 +309,7 @@ _cairo_utf8_to_utf16 (const unsigned char *str,
in = UTF8_NEXT_CHAR (in);
}
str16 = _cairo_malloc_ab (n16 + 1, sizeof (uint16_t));
str16 = malloc (sizeof (uint16_t) * (n16 + 1));
if (!str16)
return CAIRO_STATUS_NO_MEMORY;

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

@ -64,12 +64,6 @@
# 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

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

@ -1,4 +1,3 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc
@ -33,8 +32,9 @@
* Contributor(s):
*/
#include <string.h>
#include <stdio.h>
#include "cairoint.h"
#include "cairo-win32-private.h"
#ifndef SPI_GETFONTSMOOTHINGTYPE
@ -245,6 +245,8 @@ _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,7 +285,6 @@ _win32_scaled_font_create (LOGFONTW *logfont,
f->em_square = 0;
f->scaled_hfont = NULL;
f->unscaled_hfont = NULL;
if (f->quality == logfont->lfQuality ||
(logfont->lfQuality == DEFAULT_QUALITY &&
options->antialias == CAIRO_ANTIALIAS_DEFAULT)) {
@ -300,13 +301,11 @@ _win32_scaled_font_create (LOGFONTW *logfont,
cairo_matrix_multiply (&scale, font_matrix, ctm);
_compute_transform (f, &scale);
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);
_cairo_scaled_font_init (&f->base, font_face,
font_matrix, ctm, options,
&cairo_win32_scaled_font_backend);
status = _cairo_win32_scaled_font_set_metrics (f);
if (status) {
cairo_scaled_font_destroy (&f->base);
return NULL;
@ -488,6 +487,8 @@ _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)
@ -630,8 +631,8 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
dx = NULL;
}
glyph_indices = _cairo_malloc_ab (buffer_size, sizeof (WCHAR));
dx = _cairo_malloc_ab (buffer_size, sizeof (int));
glyph_indices = malloc (sizeof (WCHAR) * buffer_size);
dx = malloc (sizeof (int) * buffer_size);
if (!glyph_indices || !dx) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL2;
@ -662,7 +663,7 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
}
*num_glyphs = gcp_results.nGlyphs;
*glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t));
*glyphs = malloc (sizeof (cairo_glyph_t) * gcp_results.nGlyphs);
if (!*glyphs) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL2;
@ -1470,14 +1471,16 @@ _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);
@ -1537,6 +1540,8 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face,
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.) &&
@ -1585,6 +1590,8 @@ 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);

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

@ -46,7 +46,11 @@
#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;
@ -71,11 +75,11 @@ typedef struct _cairo_win32_surface {
cairo_surface_t *image;
cairo_rectangle_int_t clip_rect;
cairo_rectangle_int16_t clip_rect;
HRGN saved_clip;
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents;
/* Surface DC flags */
uint32_t flags;
@ -105,4 +109,7 @@ _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,17 +44,12 @@
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
# define _WIN32_WINNT 0x0500
#endif
#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
#include <stdio.h>
#include "cairoint.h"
#include "cairo-clip-private.h"
#include "cairo-win32-private.h"
#undef DEBUG_COMPOSITE
@ -186,7 +181,7 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface,
}
if (num_palette > 2) {
bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER));
bitmap_info = malloc (sizeof (BITMAPINFOHEADER) + num_palette * sizeof (RGBQUAD));
if (!bitmap_info)
return CAIRO_STATUS_NO_MEMORY;
} else {
@ -332,6 +327,8 @@ _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);
@ -476,7 +473,12 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
status = CAIRO_INT_STATUS_UNSUPPORTED;
if ((local->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
/* 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) &&
BitBlt (local->dc,
0, 0,
width, height,
@ -547,9 +549,9 @@ _cairo_win32_surface_release_source_image (void *abstract_surf
static cairo_status_t
_cairo_win32_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void **image_extra)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -615,9 +617,9 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa
static void
_cairo_win32_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -736,7 +738,7 @@ static cairo_int_status_t
_cairo_win32_surface_composite_inner (cairo_win32_surface_t *src,
cairo_image_surface_t *src_image,
cairo_win32_surface_t *dst,
cairo_rectangle_int_t src_extents,
cairo_rectangle_int16_t src_extents,
cairo_rectangle_int32_t src_r,
cairo_rectangle_int32_t dst_r,
int alpha,
@ -844,7 +846,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
cairo_image_surface_t *src_image = NULL;
cairo_format_t src_format;
cairo_rectangle_int_t src_extents;
cairo_rectangle_int16_t src_extents;
cairo_rectangle_int32_t src_r = { src_x, src_y, width, height };
cairo_rectangle_int32_t dst_r = { dst_x, dst_y, width, height };
@ -1312,7 +1314,7 @@ static cairo_int_status_t
_cairo_win32_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int_t *rects,
cairo_rectangle_int16_t *rects,
int num_rects)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -1374,8 +1376,8 @@ _cairo_win32_surface_fill_rectangles (void *abstract_surface,
}
static cairo_int_status_t
_cairo_win32_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
_cairo_win32_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
cairo_win32_surface_t *surface = abstract_surface;
cairo_status_t status;
@ -1404,9 +1406,9 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
} else {
cairo_rectangle_int_t extents;
cairo_box_int_t *boxes;
int num_boxes;
pixman_box16_t *boxes = pixman_region_rects (region);
int num_boxes = pixman_region_num_rects (region);
pixman_box16_t *extents = pixman_region_extents (region);
RGNDATA *data;
size_t data_size;
RECT *rects;
@ -1415,36 +1417,28 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
/* Create a GDI region for the cairo region */
_cairo_region_get_extents (region, &extents);
if (_cairo_region_get_boxes (region, &num_boxes, &boxes) != CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_NO_MEMORY;
data_size = sizeof (RGNDATAHEADER) + num_boxes * sizeof (RECT);
data = malloc (data_size);
if (!data) {
_cairo_region_boxes_fini (region, boxes);
if (!data)
return CAIRO_STATUS_NO_MEMORY;
}
rects = (RECT *)data->Buffer;
data->rdh.dwSize = sizeof (RGNDATAHEADER);
data->rdh.iType = RDH_RECTANGLES;
data->rdh.nCount = num_boxes;
data->rdh.nRgnSize = num_boxes * sizeof (RECT);
data->rdh.rcBound.left = extents.x;
data->rdh.rcBound.top = extents.y;
data->rdh.rcBound.right = extents.x + extents.width;
data->rdh.rcBound.bottom = extents.y + extents.height;
data->rdh.rcBound.left = extents->x1;
data->rdh.rcBound.top = extents->y1;
data->rdh.rcBound.right = extents->x2;
data->rdh.rcBound.bottom = extents->y2;
for (i = 0; i < num_boxes; i++) {
rects[i].left = boxes[i].p1.x;
rects[i].top = boxes[i].p1.y;
rects[i].right = boxes[i].p2.x;
rects[i].bottom = boxes[i].p2.y;
rects[i].left = boxes[i].x1;
rects[i].top = boxes[i].y1;
rects[i].right = boxes[i].x2;
rects[i].bottom = boxes[i].y2;
}
_cairo_region_boxes_fini (region, boxes);
gdi_region = ExtCreateRegion (NULL, data_size, data);
free (data);
@ -1473,7 +1467,7 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
static cairo_int_status_t
_cairo_win32_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -1554,8 +1548,8 @@ _cairo_win32_surface_show_glyphs (void *surface,
SetBkMode(dst->dc, TRANSPARENT);
if (num_glyphs > STACK_GLYPH_SIZE) {
glyph_buf = (WORD *) _cairo_malloc_ab (num_glyphs, sizeof(WORD));
dxy_buf = (int *) _cairo_malloc_abc (num_glyphs, sizeof(int), 2);
glyph_buf = (WORD *)malloc(num_glyphs * sizeof(WORD));
dxy_buf = (int *)malloc(num_glyphs * 2 * sizeof(int));
}
/* It is vital that dx values for dxy_buf are calculated from the delta of
@ -1646,6 +1640,8 @@ 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) {
@ -1863,30 +1859,6 @@ 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,
@ -1917,12 +1889,70 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
NULL, /* fill */
_cairo_win32_surface_show_glyphs,
NULL, /* snapshot */
_cairo_win32_surface_is_similar,
_cairo_win32_surface_reset
NULL /* snapshot */
};
/*
* 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
@ -1936,33 +1966,3 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
* 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

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

@ -297,14 +297,14 @@ _CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
static cairo_status_t
_get_image_surface (cairo_xcb_surface_t *surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect)
cairo_rectangle_int16_t *image_rect)
{
cairo_image_surface_t *image;
xcb_get_image_reply_t *imagerep;
int bpp, bytes_per_line;
short x1, y1, x2, y2;
int x1, y1, x2, y2;
unsigned char *data;
cairo_format_masks_t masks;
cairo_format_t format;
@ -403,7 +403,7 @@ _get_image_surface (cairo_xcb_surface_t *surface,
bpp = _bits_per_pixel(surface->dpy, imagerep->depth);
bytes_per_line = _bytes_per_line(surface->dpy, surface->width, bpp);
data = _cairo_malloc_ab (surface->height, bytes_per_line);
data = malloc (bytes_per_line * surface->height);
if (data == NULL) {
free (imagerep);
return CAIRO_STATUS_NO_MEMORY;
@ -642,9 +642,9 @@ _cairo_xcb_surface_release_source_image (void *abstract_surfac
static cairo_status_t
_cairo_xcb_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect_out,
cairo_rectangle_int16_t *image_rect_out,
void **image_extra)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -663,9 +663,9 @@ _cairo_xcb_surface_acquire_dest_image (void *abstract_surface
static void
_cairo_xcb_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -742,17 +742,17 @@ _cairo_xcb_surface_set_matrix (cairo_xcb_surface_t *surface,
if (!surface->src_picture)
return CAIRO_STATUS_SUCCESS;
xtransform.matrix11 = _cairo_fixed_16_16_from_double (matrix->xx);
xtransform.matrix12 = _cairo_fixed_16_16_from_double (matrix->xy);
xtransform.matrix13 = _cairo_fixed_16_16_from_double (matrix->x0);
xtransform.matrix11 = _cairo_fixed_from_double (matrix->xx);
xtransform.matrix12 = _cairo_fixed_from_double (matrix->xy);
xtransform.matrix13 = _cairo_fixed_from_double (matrix->x0);
xtransform.matrix21 = _cairo_fixed_16_16_from_double (matrix->yx);
xtransform.matrix22 = _cairo_fixed_16_16_from_double (matrix->yy);
xtransform.matrix23 = _cairo_fixed_16_16_from_double (matrix->y0);
xtransform.matrix21 = _cairo_fixed_from_double (matrix->yx);
xtransform.matrix22 = _cairo_fixed_from_double (matrix->yy);
xtransform.matrix23 = _cairo_fixed_from_double (matrix->y0);
xtransform.matrix31 = 0;
xtransform.matrix32 = 0;
xtransform.matrix33 = 1 << 16;
xtransform.matrix33 = _cairo_fixed_from_double (1);
if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
{
@ -1246,14 +1246,11 @@ static cairo_int_status_t
_cairo_xcb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t * color,
cairo_rectangle_int_t *rects,
cairo_rectangle_int16_t *rects,
int num_rects)
{
cairo_xcb_surface_t *surface = abstract_surface;
xcb_render_color_t render_color;
xcb_rectangle_t static_xrects[16];
xcb_rectangle_t *xrects = static_xrects;
int i;
if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -1263,27 +1260,12 @@ _cairo_xcb_surface_fill_rectangles (void *abstract_surface,
render_color.blue = color->blue_short;
render_color.alpha = color->alpha_short;
if (num_rects > ARRAY_LENGTH(static_xrects)) {
xrects = _cairo_malloc_ab (num_rects, sizeof(xcb_rectangle_t));
if (xrects == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
for (i = 0; i < num_rects; i++) {
xrects[i].x = rects[i].x;
xrects[i].y = rects[i].y;
xrects[i].width = rects[i].width;
xrects[i].height = rects[i].height;
}
/* XXX: This xcb_rectangle_t cast is evil... it needs to go away somehow. */
_cairo_xcb_surface_ensure_dst_picture (surface);
xcb_render_fill_rectangles (surface->dpy,
_render_operator (op),
surface->dst_picture,
render_color, num_rects, xrects);
if (xrects != static_xrects)
free(xrects);
render_color, num_rects, (xcb_rectangle_t *) rects);
return CAIRO_STATUS_SUCCESS;
}
@ -1346,21 +1328,21 @@ _create_trapezoid_mask (cairo_xcb_surface_t *dst,
mask_picture = _create_a8_picture (dst, &transparent, width, height, FALSE);
solid_picture = _create_a8_picture (dst, &solid, width, height, TRUE);
offset_traps = _cairo_malloc_ab (num_traps, sizeof (xcb_render_trapezoid_t));
offset_traps = malloc (sizeof (xcb_render_trapezoid_t) * num_traps);
if (!offset_traps)
return XCB_NONE;
for (i = 0; i < num_traps; i++) {
offset_traps[i].top = _cairo_fixed_to_16_16(traps[i].top) - 0x10000 * dst_y;
offset_traps[i].bottom = _cairo_fixed_to_16_16(traps[i].bottom) - 0x10000 * dst_y;
offset_traps[i].left.p1.x = _cairo_fixed_to_16_16(traps[i].left.p1.x) - 0x10000 * dst_x;
offset_traps[i].left.p1.y = _cairo_fixed_to_16_16(traps[i].left.p1.y) - 0x10000 * dst_y;
offset_traps[i].left.p2.x = _cairo_fixed_to_16_16(traps[i].left.p2.x) - 0x10000 * dst_x;
offset_traps[i].left.p2.y = _cairo_fixed_to_16_16(traps[i].left.p2.y) - 0x10000 * dst_y;
offset_traps[i].right.p1.x = _cairo_fixed_to_16_16(traps[i].right.p1.x) - 0x10000 * dst_x;
offset_traps[i].right.p1.y = _cairo_fixed_to_16_16(traps[i].right.p1.y) - 0x10000 * dst_y;
offset_traps[i].right.p2.x = _cairo_fixed_to_16_16(traps[i].right.p2.x) - 0x10000 * dst_x;
offset_traps[i].right.p2.y = _cairo_fixed_to_16_16(traps[i].right.p2.y) - 0x10000 * dst_y;
offset_traps[i].top = traps[i].top - 0x10000 * dst_y;
offset_traps[i].bottom = traps[i].bottom - 0x10000 * dst_y;
offset_traps[i].left.p1.x = traps[i].left.p1.x - 0x10000 * dst_x;
offset_traps[i].left.p1.y = traps[i].left.p1.y - 0x10000 * dst_y;
offset_traps[i].left.p2.x = traps[i].left.p2.x - 0x10000 * dst_x;
offset_traps[i].left.p2.y = traps[i].left.p2.y - 0x10000 * dst_y;
offset_traps[i].right.p1.x = traps[i].right.p1.x - 0x10000 * dst_x;
offset_traps[i].right.p1.y = traps[i].right.p1.y - 0x10000 * dst_y;
offset_traps[i].right.p2.x = traps[i].right.p2.x - 0x10000 * dst_x;
offset_traps[i].right.p2.y = traps[i].right.p2.y - 0x10000 * dst_y;
}
xcb_render_trapezoids (dst->dpy, XCB_RENDER_PICT_OP_ADD,
@ -1488,41 +1470,14 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
dst_x, dst_y, width, height);
} else {
xcb_render_trapezoid_t xtraps_stack[16];
xcb_render_trapezoid_t *xtraps = xtraps_stack;
int i;
if (num_traps > ARRAY_LENGTH(xtraps_stack)) {
xtraps = _cairo_malloc_ab (num_traps, sizeof(xcb_render_trapezoid_t));
if (xtraps == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL;
}
}
for (i = 0; i < num_traps; i++) {
xtraps[i].top = _cairo_fixed_to_16_16(traps[i].top);
xtraps[i].bottom = _cairo_fixed_to_16_16(traps[i].bottom);
xtraps[i].left.p1.x = _cairo_fixed_to_16_16(traps[i].left.p1.x);
xtraps[i].left.p1.y = _cairo_fixed_to_16_16(traps[i].left.p1.y);
xtraps[i].left.p2.x = _cairo_fixed_to_16_16(traps[i].left.p2.x);
xtraps[i].left.p2.y = _cairo_fixed_to_16_16(traps[i].left.p2.y);
xtraps[i].right.p1.x = _cairo_fixed_to_16_16(traps[i].right.p1.x);
xtraps[i].right.p1.y = _cairo_fixed_to_16_16(traps[i].right.p1.y);
xtraps[i].right.p2.x = _cairo_fixed_to_16_16(traps[i].right.p2.x);
xtraps[i].right.p2.y = _cairo_fixed_to_16_16(traps[i].right.p2.y);
}
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
xcb_render_trapezoids (dst->dpy,
_render_operator (op),
src->src_picture, dst->dst_picture,
render_format->id,
render_src_x + attributes.x_offset,
render_src_y + attributes.y_offset,
num_traps, xtraps);
if (xtraps != xtraps_stack)
free(xtraps);
num_traps, (xcb_render_trapezoid_t *) traps);
}
BAIL:
@ -1532,8 +1487,8 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
}
static cairo_int_status_t
_cairo_xcb_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
_cairo_xcb_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -1554,31 +1509,27 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
xcb_render_change_picture (surface->dpy, surface->dst_picture,
XCB_RENDER_CP_CLIP_MASK, none);
} else {
cairo_box_int_t *boxes;
pixman_box16_t *boxes;
xcb_rectangle_t *rects = NULL;
int n_boxes, i;
if (_cairo_region_get_boxes (region, &n_boxes, &boxes) != CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_NO_MEMORY;
n_boxes = pixman_region_num_rects (region);
if (n_boxes > 0) {
rects = _cairo_malloc_ab (n_boxes, sizeof(xcb_rectangle_t));
if (rects == NULL) {
_cairo_region_boxes_fini (region, boxes);
rects = malloc (sizeof(xcb_rectangle_t) * n_boxes);
if (rects == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
} else {
rects = NULL;
}
for (i = 0; i < n_boxes; i++) {
rects[i].x = boxes[i].p1.x;
rects[i].y = boxes[i].p1.y;
rects[i].width = boxes[i].p2.x - boxes[i].p1.x;
rects[i].height = boxes[i].p2.y - boxes[i].p1.y;
}
boxes = pixman_region_rects (region);
_cairo_region_boxes_fini (region, boxes);
for (i = 0; i < n_boxes; i++) {
rects[i].x = boxes[i].x1;
rects[i].y = boxes[i].y1;
rects[i].width = boxes[i].x2 - boxes[i].x1;
rects[i].height = boxes[i].y2 - boxes[i].y1;
}
surface->have_clip_rects = TRUE;
surface->clip_rects = rects;
@ -1596,7 +1547,7 @@ _cairo_xcb_surface_set_clip_region (void *abstract_surface,
static cairo_int_status_t
_cairo_xcb_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -1626,39 +1577,6 @@ _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 = {
@ -1690,11 +1608,7 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
NULL, /* stroke */
NULL, /* fill */
_cairo_xcb_surface_show_glyphs,
NULL, /* snapshot */
_cairo_xcb_surface_is_similar,
_cairo_xcb_surface_reset
NULL /* snapshot */
};
/**
@ -2409,7 +2323,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
/* We make a copy of the glyphs so that we can elide any size-zero
* glyphs to workaround an X server bug, (present in at least Xorg
* 7.1 without EXA). */
output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
output_glyphs = malloc (num_glyphs * sizeof (cairo_glyph_t));
if (output_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -2430,8 +2344,7 @@ _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_CONTENT_COLOR);
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
src_pattern = &solid_pattern.base;
op = CAIRO_OPERATOR_DEST_OUT;
}

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

@ -35,97 +35,43 @@
#include "cairoint.h"
#include "cairo-xlib.h"
#include "cairo-freelist-private.h"
typedef struct _cairo_xlib_display cairo_xlib_display_t;
typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_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;
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;
void *key;
};
struct _cairo_xlib_screen_info {
cairo_xlib_screen_info_t *next;
unsigned int ref_count;
cairo_xlib_display_t *display;
Display *display;
Screen *screen;
cairo_bool_t has_render;
cairo_font_options_t font_options;
GC gc[9];
unsigned int gc_needs_clip_reset;
cairo_xlib_hook_t *close_display_hooks;
};
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_xlib_screen_info_t *
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info);
cairo_private cairo_bool_t
_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, void *key);
cairo_private void
_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);
_cairo_xlib_remove_close_display_hook (Display *display, void *key);
#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,13 +51,14 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "cairoint.h"
#include <stdlib.h>
#include <string.h>
#include "cairo-xlib-private.h"
#include <fontconfig/fontconfig.h>
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
#include <X11/extensions/Xrender.h>
static int
@ -132,7 +133,7 @@ get_integer_default (Display *dpy,
#endif
static void
_cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *info)
_cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
{
cairo_bool_t xft_hinting;
cairo_bool_t xft_antialias;
@ -142,23 +143,23 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in
cairo_subpixel_order_t subpixel_order;
cairo_hint_style_t hint_style;
if (!get_boolean_default (dpy, "antialias", &xft_antialias))
if (!get_boolean_default (info->display, "antialias", &xft_antialias))
xft_antialias = TRUE;
if (!get_boolean_default (dpy, "hinting", &xft_hinting))
if (!get_boolean_default (info->display, "hinting", &xft_hinting))
xft_hinting = TRUE;
if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
if (!get_integer_default (info->display, "hintstyle", &xft_hintstyle))
xft_hintstyle = FC_HINT_FULL;
if (!get_integer_default (dpy, "rgba", &xft_rgba))
if (!get_integer_default (info->display, "rgba", &xft_rgba))
{
xft_rgba = FC_RGBA_UNKNOWN;
#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
if (info->has_render)
{
int render_order = XRenderQuerySubpixelOrder (dpy,
int render_order = XRenderQuerySubpixelOrder (info->display,
XScreenNumberOfScreen (info->screen));
switch (render_order)
@ -236,183 +237,235 @@ _cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *in
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_xlib_screen_info_t *
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
{
if (info == NULL)
return NULL;
CAIRO_MUTEX_DECLARE(_xlib_screen_mutex);
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_display_t *display;
cairo_xlib_screen_info_t *info = NULL, **prev;
display = _cairo_xlib_display_get (dpy);
if (display == NULL)
return NULL;
CAIRO_MUTEX_LOCK (display->mutex);
if (display->closed) {
CAIRO_MUTEX_UNLOCK (display->mutex);
goto DONE;
}
for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
if (info->screen == screen) {
/*
* MRU the list
*/
if (prev != &display->screens) {
*prev = info->next;
info->next = display->screens;
display->screens = info;
}
break;
}
}
CAIRO_MUTEX_UNLOCK (display->mutex);
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;
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);
}
CAIRO_MUTEX_LOCK (display->mutex);
info->next = display->screens;
display->screens = info;
CAIRO_MUTEX_UNLOCK (display->mutex);
}
}
DONE:
_cairo_xlib_display_destroy (display);
return info;
}
static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
static int
depth_to_index (int depth)
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
{
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;
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;
}
GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
static void
_cairo_xlib_screen_info_reset (void)
{
GC gc;
cairo_xlib_screen_info_t *info, *next;
depth = depth_to_index (depth);
/*
* Delete everything in the list.
*/
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
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);
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);
}
return gc;
_cairo_xlib_screen_list = NULL;
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
}
cairo_status_t
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
static cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get_unlocked (Display *dpy, Screen *screen)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
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;
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);
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;
}
}
}
info->gc[depth] = gc;
if (reset_clip)
info->gc_needs_clip_reset |= 1 << depth;
else
info->gc_needs_clip_reset &= ~(1 << depth);
if (info)
return info;
return status;
if (screen == NULL)
return NULL;
info = malloc (sizeof (cairo_xlib_screen_info_t));
if (!info)
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;
return info;
}
cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
{
cairo_xlib_screen_info_t *info;
/* 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);
info = _cairo_xlib_screen_info_get_unlocked (dpy, screen);
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) {
/*
* MRU the list
*/
if (prev != &info->close_display_hooks) {
*prev = hook->next;
hook->next = info->close_display_hooks;
info->close_display_hooks = hook;
}
break;
}
}
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;
}
success = TRUE;
unlock:
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
return success;
}
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;
}
}
unlock:
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
}
void
_cairo_xlib_screen_reset_static_data (void)
{
_cairo_xlib_screen_info_reset ();
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -41,7 +41,6 @@
#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
* font backend and target device
* for 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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -51,10 +51,10 @@
* there.
*/
#include "cairoint.h"
#include "test-fallback-surface.h"
#include "cairoint.h"
typedef struct _test_fallback_surface {
cairo_surface_t base;
@ -80,7 +80,6 @@ _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;
}
@ -140,9 +139,9 @@ _test_fallback_surface_release_source_image (void *abstract_surface,
static cairo_status_t
_test_fallback_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect_out,
cairo_rectangle_int16_t *image_rect_out,
void **image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
@ -156,9 +155,9 @@ _test_fallback_surface_acquire_dest_image (void *abstract_surface,
static void
_test_fallback_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int_t *interest_rect,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
@ -170,29 +169,9 @@ _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_int_t *rectangle)
_test_fallback_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *rectangle)
{
test_fallback_surface_t *surface = abstract_surface;
@ -207,7 +186,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,
_test_fallback_surface_clone_similar,
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */

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

@ -45,10 +45,9 @@
* backend.
*/
#include "cairoint.h"
#include "test-meta-surface.h"
#include "cairoint.h"
#include "cairo-meta-surface-private.h"
typedef struct _test_meta_surface {
@ -144,14 +143,11 @@ 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;
status = _cairo_meta_surface_replay (surface->meta, surface->image);
if (status)
return status;
_cairo_meta_surface_replay (surface->meta, surface->image);
surface->image_reflects_meta = TRUE;
@ -174,7 +170,7 @@ _test_meta_surface_intersect_clip_path (void *abstract_surface,
static cairo_int_status_t
_test_meta_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
test_meta_surface_t *surface = abstract_surface;
@ -283,7 +279,6 @@ 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"
@ -300,23 +295,17 @@ _test_meta_surface_snapshot (void *abstract_other)
#if 0
return _cairo_surface_snapshot (other->meta);
#else
cairo_rectangle_int_t extents;
cairo_rectangle_int16_t extents;
cairo_surface_t *surface;
status = _cairo_surface_get_extents (other->image, &extents);
if (status)
return (cairo_surface_t*) &_cairo_surface_nil;
_cairo_surface_get_extents (other->image, &extents);
surface = cairo_surface_create_similar (other->image,
CAIRO_CONTENT_COLOR_ALPHA,
extents.width,
extents.height);
status = _cairo_meta_surface_replay (other->meta, surface);
if (status) {
cairo_surface_destroy (surface);
surface = (cairo_surface_t*) &_cairo_surface_nil;
}
_cairo_meta_surface_replay (other->meta, surface);
return surface;
#endif

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

@ -45,11 +45,11 @@
* backend.
*/
#include "cairoint.h"
#include "test-paginated-surface.h"
#include "cairo-paginated-private.h"
#include "cairoint.h"
#include "cairo-paginated-surface-private.h"
typedef struct _test_paginated_surface {
cairo_surface_t base;
@ -107,7 +107,7 @@ _test_paginated_surface_finish (void *abstract_surface)
static cairo_int_status_t
_test_paginated_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
pixman_region16_t *region)
{
test_paginated_surface_t *surface = abstract_surface;
@ -149,7 +149,7 @@ _test_paginated_surface_set_clip_region (void *abstract_surface,
static cairo_int_status_t
_test_paginated_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
cairo_rectangle_int16_t *rectangle)
{
test_paginated_surface_t *surface = abstract_surface;

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

@ -0,0 +1,19 @@
David R Bacon <dbacon@cis.ksu.edu> Fixes to compile on x86_64.
Billy Biggs <vektor@dumbterm.net> Fix to use stdint datatypes.
Dave Beckett <Dave.Beckett@bristol.ac.uk> Combined libpixregion, libic, and slim.
Jakub Bogusz <qboosh@pld-linux.org> Fixes for 64-bit machines.
Anders Carlsson <andersca@gnome.org> Build fixes. New accessor functions.
Richard Henderson <rth@twiddle.net> "slim" macros for better shared libraries
Owen Taylor <otaylor@redhat.com> Support for both transform and repeat
Keith Packard <keithp@keithp.com> The original implementation of the compositing code.
David Reveman <c99drn@cs.umu.se> Byte-order, clipping and format fixes.
Vladimir Vukicevic <vladimir@pobox.com> Bug fix.
Bryan Worth <bryan@theworths.org> Cleanups to not depend on X header files.
Carl Worth <carl@theworths.org> General maintenance. Original port from X server code.
Richard Worth <richard@theworths.org> Build fixes for cygwin.
and the "X Window System authors" (pixregion code)
(Please let us know if we have missed anyone. I would be interested in
having more precise attribution for the pixregion code if anyone knows
who wrote that.)

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

@ -0,0 +1,92 @@
libpixregion
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
----------------------------------------------------------------------
libic
Copyright © 2001 Keith Packard
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of Keith Packard not be used in
advertising or publicity pertaining to distribution of the software without
specific, written prior permission. Keith Packard makes no
representations about the suitability of this software for any purpose. It
is provided "as is" without express or implied warranty.
KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
----------------------------------------------------------------------
slim
slim is Copyright © 2003 Richard Henderson
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Richard Henderson not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission. Richard Henderson
makes no representations about the suitability of this software for
any purpose. It is provided "as is" without express or implied
warranty.
RICHARD HENDERSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
EVENT SHALL RICHARD HENDERSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

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

@ -1,234 +1,9 @@
Installation Instructions
*************************
This code uses automake, in order to generate the Makefiles use:
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006 Free Software Foundation, Inc.
$ autogen.sh
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
After that, standard build procedures apply:
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
$ make
# make install

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

@ -0,0 +1,135 @@
Snapshot 0.1.6 (2005-07-28 Carl Worth <cworth@cworth.org>)
==========================================================
Behavioral changes
------------------
Clips are changed to only affect destination operands, not
sources. This gives the desired behavior for cairo. If the X server's
Render implementation wants to use pixman it will have to select
source clipping, (presumably through a new API call that we can add at
that point).
Bug fixes
---------
Fix leak of the clip region associated with an image in
pixman_image_destroy.
Fix units for stride return to be FbStip-sized, (this bug was causing
non antialiased text in cairo to appear as garbage).
Other changes
-------------
The implementation has been merged considerably with xserver/fb. Most
of the merge was just name changes, but there were likely some bug
fixes or performance improvements in there as well.
Snapshot 0.1.5 (2005-05-18 Carl Worth <cworth@cworth.org>)
==========================================================
Bug fixes
---------
Fix confusion of depth and bpp which was causing cairo to crash on
some X servers.
Properly declare pixman_fixed16_16_t as int32_t which fixes
compilation failures on some platforms.
Fix to find inttypes.h on AIX.
Fix bug in compositing when the source image has no alpha channel.
Some fixes to the clipping code.
Fix memory leak when asked to draw a degenerate trapezoid list.
Snapshot 0.1.4 (2005-03-07 Carl Worth <cworth@cworth.org>)
==========================================================
API Addition
------------
Add new function:
void
pixman_add_trapezoids (pixman_image_t *dst,
int x_off,
int y_off,
const pixman_trapezoid_t *traps,
int ntraps);
Performance improvement
-----------------------
Restrict size of intermediate surface used while compositing
trapezoids based on the bounds of the desination surface.
Bug fixes
---------
Fix rendering on 64-bit platforms.
Snapshot 0.1.3 (2005-01-21 Carl Worth <cworth@cworth.org>)
==========================================================
Performance improvements
------------------------
Solid fills are now much faster, (thanks to Alexander Larsson).
Bug fixes
---------
Fixed to quiet warnings in newer versions of gcc.
Don't divide-by-zero if given an image of size 0x0.
Fixed several corner cases where values outside a trapezoid would be
drawn with alpha 1/255 (in the 8-bit case).
Internal changes
----------------
Imported the newer point-sampling trapezoid rasterization code that
Keith Packard wrote for the X server. This provide pixel-perfect
matching with the Render extension as well as code that is simpler,
more robust, and easier to maintain.
Snapshot 0.1.2 (2004-10-27 Carl Worth <cworth@cworth.org>)
==========================================================
New functionality
-----------------
Added three new functions:
pixman_image_set_component_alpha
pixman_format_get_masks
pixman_image_get_format
The first enables component-alpha compositing which can be used for
optimizing sub-pixel rendering of text and other geometry. This is
useful when the geometrical relationship of the sub-pixel components
of the display device are known, (eg. with flat-panel monitors rather
than CRTs).
The other two functions are simple query functions that were missing.
Bug fixes
---------
Enabling both transform and repeat simultaneously now works.
Some byte-order fixes.
Clipping fixes: pixman now takes a copy of the client clipping region
client clipping is now actually used, it wasn't earlier.
Snapshot 0.1.1 (2004-04-16 Carl Worth <cworth@east.isi.edu>)
============================================================
Build fixes for cygwin
----------------------
This snapshot adds the -no-undefined flag during compilation which is
necessart for building a shared library under cygwin.
Cleanup of the public API
-------------------------
We recently noticed that there were a coupld of bugs in the script
that renamed libic to libpixman. Fixing this requires the following
changes in the public API:
PIXMAN_FORMAT_AR_GB32 -> PIXMAN_FORMAT_ARGB32
PIXMAN_FORMAT_RG_B24 -> PIXMAN_FORMAT_RGB24
While we're changing that, we also normalized the names of structure
tags, for example:
struct _pixman_region16_t -> struct pixman_region16
etc.
but users are expected to use typedefs such as pixman_region16_t
anyway.

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

@ -0,0 +1,47 @@
libpixman - Pixel manipulation library
libpixman is a merge of libpixregion and libic.
It also includes the slim headers.
----------------------------------------------------------------------
libpixregion - Pixel region Library
libpixregion is a generic library for manipulating pixel regions. A
PixRegion is a set of Y-X banded rectangles that cover the desired
region.
The original code for libxregion was part of the reference X server
implementation of the X Window System. A modified copy of the code
also exists in the Xlib client library. libpixregion was formed so
that both the X server and client libraries could share common code
for region manipulation.
libpixregion is also intended to be applicable outside of the X Window
System. The public interface of libpixregion does not depend on any
part of the X Window System.
----------------------------------------------------------------------
libic - Image compositing library
libic is a generic image compositing library. libic provides
Porter/Duff compositing of images and implicit mask generation for
geometric primitives including trapezoids, triangles, and rectangles.
The semantics of libic are designed to precisely match the
specification of the X Render extension. In fact, the initial
implementation of libic was lifted from the reference implementation
of RENDER from the X server.
However, libic is intended to be useful independent of the X Window
System. The public interface exported by libic does not contain any
X-specific data structures.
Carl Worth
cworth@isi.edu
Keith Packard (keithp@keithp.com) originally wrote all the original
RENDER code that was yanked out to become libic. Keith also provided
impetus and guidance in the development of libic.
----------------------------------------------------------------------
slim - Shared Library Interface Macros

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

@ -1,139 +1,10 @@
- Go through things marked FIXME
Need to finish up libpixman to the point where there X server can use
it in place of its original copy of all this code (eg. in fb). This
means merging features that have happened in either tree since the
birth of libpixman. Off-hand I can think of the following things that
have happened:
- Add calls to prepare and finish access where necessary. grep for
ACCESS_MEM, and make sure they are correctly wrapped in prepare
and finish.
- restore READ/WRITE in the fbcompose combiners since they sometimes
store directly to destination drawables.
- It probably makes sense to move the more strange X region API
into pixman as well, but guarded with PIXMAN_XORG_COMPATIBILITY
- Reinstate the FbBits typedef? At the moment we don't
even have the FbBits type; we just use uint32_t everywhere.
Keith says in bug 2335:
The 64-bit code in fb (pixman) is probably broken; it hasn't been
used in quite some time as PCI (and AGP) is 32-bits wide, so
doing things 64-bits at a time is a net loss. To quickly fix
this, I suggest just using 32-bit datatypes by setting
IC_SHIFT to 5 for all machines.
- Consider whether calling regions region16 is really such a great
idea Vlad wants 32 bit regions for Cairo. This will break X server
ABI, but should otherwise be mostly harmless, though a
pixman_region_get_boxes16() may be useful.
- Make source clipping optional.
- done: source clipping happens through an indirection.
still needs to make the indirection settable. (And call it
from X)
- Consider optimizing the 8/16 bit solid fills in pixman-util.c by
storing more than one value at a time.
- Add an image cache to prevent excessive malloc/free. Note that pixman
needs to be thread safe when used from cairo.
- Review the pixman_format_code_t enum to make sure it will support
future formats. Some formats we will probably need:
ARGB/ABGR with 16/32/64 bit integer/floating channels
YUV2,
YV12
Also we may need the ability to distinguish between PICT_c8 and
PICT_x4c4. (This could be done by interpreting the A channel as
the depth for TYPE_COLOR and TYPE_GRAY formats).
A possibility may be to reserve the two top bits and make them
encode "number of places to shift the channel widths given" Since
these bits are 00 at the moment everything will continue to work,
but these additional widths will be allowed:
All even widths between 18-32
All multiples of four widths between 33 and 64
All multiples of eight between 64 and 128
This means things like r21g22b21 won't work - is that worth
worrying about? I don't think so. And of course the bpp field
can't handle a depth of over 256, so > 64 bit channels arent'
really all that useful.
We could reserve one extra bit to indicate floating point, but
we may also just add
PIXMAN_TYPE_ARGB_FLOAT
PIXMAN_TYPE_BGRA_FLOAT
PIXMAN_TYPE_A_FLOAT
image types. With five bits we can support up to 32 different
format types, which should be enough for everybody, even if we
decide to support all the various video formats here:
http://www.fourcc.org/yuv.php
It may make sense to have a PIXMAN_TYPE_YUV, and then use the
channel bits to specify the exact subtype.
What about color spaces such a linear vs. srGB etc.?
done:
- Run cairo test suite; fix bugs
- one bug in source-scale-clip
- Remove the warning suppression in the ACCESS_MEM macro and fix the
warnings that are real
- irrelevant now.
- make the wrapper functions global instead of image specific
- this won't work since pixman is linked to both fb and wfb
- Add non-mmx solid fill
- Make sure the endian-ness macros are defined correctly.
- The rectangles in a region probably shouldn't be returned const as
the X server will be changing them.
- Right now we _always_ have a clip region, which is empty by default.
Why does this work at all? It probably doesn't. The server
distinguishes two cases, one where nothing is clipped (CT_NONE), and
one where there is a clip region (CT_REGION).
- Default clip region should be the full image
- Test if pseudo color still works. It does, but it also shows that
copying a pixman_indexed_t on every composite operation is not
going to fly. So, for now set_indexed() does not copy the
indexed table.
Also just the malloc() to allocate a pixman image shows up pretty
high.
Options include
- Make all the setters not copy their arguments
- Possibly combined with going back to the stack allocated
approach that we already use for regions.
- Keep a cached pixman_image_t around for every picture. It would
have to be kept uptodate every time something changes about the
picture.
- Break the X server ABI and simply have the relevant parameter
stored in the pixman image. This would have the additional benefits
that:
- We can get rid of the annoying repeat field which is duplicated
elsewhere.
- We can use pixman_color_t and pixman_gradient_stop_t
etc. instead of the types that are defined in
renderproto.h
* libpixman has fix for transform + repeat
* X server has some (MMX? SSE?) optimized compositing code
But see the logs for more details.

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

@ -21,7 +21,6 @@
# Contributor(s):
# Brian Ryner <bryner@brianryner.com>
# Stuart Parmenter <pavlov@pavlov.net>
# Vladimir Vukicevic <vladimir@pobox.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
@ -64,25 +63,33 @@ endif
endif
CSRCS = \
pixman-compose-accessors.c \
pixman-compose-noaccessors.c \
pixman-compute-region.c \
pixman-edge-accessors.c \
pixman-edge-noaccessors.c \
pixman-image.c \
pixman-pict.c \
pixman-region.c \
pixman-trap.c \
pixman-utils.c \
fbcompose.c \
fbedge.c \
fbpict.c \
fbtrap.c \
icblt.c \
icbltone.c \
iccolor.c \
icformat.c \
icimage.c \
icpixels.c \
icrect.c \
icstipple.c \
ictransform.c \
ictrap.c \
ictri.c \
icutil.c \
pixregion.c \
renderedge.c \
$(NULL)
ifdef MOZ_X11
#CSRCS += pixman-mmx.c
#CSRCS += fbmmx.c
#DEFINES += -DUSE_MMX
endif
ifdef _MSC_VER
CSRCS += pixman-mmx.c
CSRCS += fbmmx.c
DEFINES += -DUSE_MMX
endif
@ -96,8 +103,6 @@ FORCE_USE_PIC = 1
include $(topsrcdir)/config/rules.mk
CFLAGS += -DPACKAGE="mozpixman" -D_USE_MATH_DEFINES
ifdef MOZ_X11
#CFLAGS += -mmmx -msse -Winline --param inline-unit-growth=10000 --param large-function-growth=10000
endif

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

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

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

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

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

@ -0,0 +1,236 @@
/*
* $Id: fbtrap.c,v 1.21 2007-07-24 19:24:27 vladimir%pobox.com Exp $
*
* Copyright © 2004 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "pixman-xserver-compat.h"
#ifdef RENDER
/* XXX: Haven't added addTraps to libpixman yet. */
#if 0
void
fbAddTraps (PicturePtr pPicture,
INT16 x_off,
INT16 y_off,
int ntrap,
xTrap *traps)
{
FbBits *buf;
int bpp;
int width;
int stride;
int height;
int pxoff, pyoff;
xFixed x_off_fixed;
xFixed y_off_fixed;
RenderEdge l, r;
xFixed t, b;
fbGetDrawable (pPicture->pDrawable, buf, stride, bpp, pxoff, pyoff);
width = pPicture->pDrawable->width;
height = pPicture->pDrawable->height;
x_off += pxoff;
y_off += pyoff;
x_off_fixed = IntToxFixed(y_off);
y_off_fixed = IntToxFixed(y_off);
while (ntrap--)
{
t = traps->top.y + y_off_fixed;
if (t < 0)
t = 0;
t = RenderSampleCeilY (t, bpp);
b = traps->bot.y + y_off_fixed;
if (xFixedToInt (b) >= height)
b = IntToxFixed (height) - 1;
b = RenderSampleFloorY (b, bpp);
if (b >= t)
{
/* initialize edge walkers */
RenderEdgeInit (&l, bpp, t,
traps->top.l + x_off_fixed,
traps->top.y + y_off_fixed,
traps->bot.l + x_off_fixed,
traps->bot.y + y_off_fixed);
RenderEdgeInit (&r, bpp, t,
traps->top.r + x_off_fixed,
traps->top.y + y_off_fixed,
traps->bot.r + x_off_fixed,
traps->bot.y + y_off_fixed);
fbRasterizeEdges (buf, bpp, width, stride, &l, &r, t, b);
}
traps++;
}
}
#endif
void
fbRasterizeTrapezoid (PicturePtr pPicture,
const xTrapezoid *trap,
int x_off,
int y_off)
{
FbBits *buf;
int bpp;
int width;
int stride;
int height;
int pxoff, pyoff;
xFixed x_off_fixed;
xFixed y_off_fixed;
RenderEdge l, r;
xFixed t, b;
fbGetDrawable (pPicture->pDrawable, buf, stride, bpp, pxoff, pyoff);
width = pPicture->pDrawable->width;
height = pPicture->pDrawable->height;
x_off += pxoff;
y_off += pyoff;
x_off_fixed = IntToxFixed(x_off);
y_off_fixed = IntToxFixed(y_off);
t = trap->top + y_off_fixed;
if (t < 0)
t = 0;
t = RenderSampleCeilY (t, bpp);
b = trap->bottom + y_off_fixed;
if (xFixedToInt (b) >= height)
b = IntToxFixed (height) - 1;
b = RenderSampleFloorY (b, bpp);
if (b >= t)
{
/* initialize edge walkers */
RenderLineFixedEdgeInit (&l, bpp, t, &trap->left, x_off, y_off);
RenderLineFixedEdgeInit (&r, bpp, t, &trap->right, x_off, y_off);
fbRasterizeEdges (buf, bpp, width, stride, &l, &r, t, b);
}
}
/* XXX: Haven't add addTriangles to libpixman yet. */
#if 0
static int
_GreaterY (xPointFixed *a, xPointFixed *b)
{
if (a->y == b->y)
return a->x > b->x;
return a->y > b->y;
}
/*
* Note that the definition of this function is a bit odd because
* of the X coordinate space (y increasing downwards).
*/
static int
_Clockwise (xPointFixed *ref, xPointFixed *a, xPointFixed *b)
{
xPointFixed ad, bd;
ad.x = a->x - ref->x;
ad.y = a->y - ref->y;
bd.x = b->x - ref->x;
bd.y = b->y - ref->y;
return ((xFixed_32_32) bd.y * ad.x - (xFixed_32_32) ad.y * bd.x) < 0;
}
/* FIXME -- this could be made more efficient */
void
fbAddTriangles (PicturePtr pPicture,
INT16 x_off,
INT16 y_off,
int ntri,
xTriangle *tris)
{
xPointFixed *top, *left, *right, *tmp;
xTrapezoid trap;
for (; ntri; ntri--, tris++)
{
top = &tris->p1;
left = &tris->p2;
right = &tris->p3;
if (_GreaterY (top, left)) {
tmp = left; left = top; top = tmp;
}
if (_GreaterY (top, right)) {
tmp = right; right = top; top = tmp;
}
if (_Clockwise (top, right, left)) {
tmp = right; right = left; left = tmp;
}
/*
* Two cases:
*
* + +
* / \ / \
* / \ / \
* / + + \
* / -- -- \
* / -- -- \
* / --- --- \
* +-- --+
*/
trap.top = top->y;
trap.left.p1 = *top;
trap.left.p2 = *left;
trap.right.p1 = *top;
trap.right.p2 = *right;
if (right->y < left->y)
trap.bottom = right->y;
else
trap.bottom = left->y;
fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
if (right->y < left->y)
{
trap.top = right->y;
trap.bottom = left->y;
trap.right.p1 = *right;
trap.right.p2 = *left;
}
else
{
trap.top = left->y;
trap.bottom = right->y;
trap.left.p1 = *left;
trap.left.p2 = *right;
}
fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off);
}
}
#endif
#endif /* RENDER */

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