This commit is contained in:
vladimir@pobox.com 2007-08-01 23:58:46 -07:00
Родитель 837921103c
Коммит 24adcacb7a
90 изменённых файлов: 8126 добавлений и 5908 удалений

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

@ -7,7 +7,8 @@ http://www.cairographics.org/.
VERSIONS:
cairo (1.4.2)
cairo (1.5.x - c0a7d33ac6c81dd74ee2a9daaa3749a346ef4897)
pixman (0.9.3 - 0c80a0cd84f30616563cef5910df9deb4f8ed687)
glitz 0.5.2 (cvs - 2006-01-10)
***** NOTE FOR VISUAL C++ 6.0 *****
@ -16,7 +17,8 @@ VC6 is not supported. Please upgrade to VC8.
==== Patches ====
All patches in the cairo tree are surrounded by "MOZILLA_CAIRO_NOT_DEFINED" (which should NOT be defined).
All patches in the cairo tree are surrounded by "MOZILLA_CAIRO_NOT_DEFINED"
(which should obviously not be defined).
Some specific things:

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

@ -81,7 +81,6 @@ CSRCS = \
cairo-debug.c \
cairo-deflate-stream.c \
cairo-fixed.c \
cairo-font.c \
cairo-font-options.c \
cairo-freelist.c \
cairo-gstate.c \
@ -91,6 +90,7 @@ CSRCS = \
cairo-lzw.c \
cairo-matrix.c \
cairo-meta-surface.c \
cairo-mutex.c \
cairo-operator.c \
cairo-output-stream.c \
cairo-paginated-surface.c \
@ -165,7 +165,8 @@ endif
ifdef MOZ_X11
CSRCS += cairo-xlib-surface.c \
cairo-xlib-screen.c
cairo-xlib-screen.c \
cairo-xlib-display.c
EXPORTS += cairo-xlib.h cairo-xlib-xrender.h
endif

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

@ -1,4 +1,4 @@
/* $Id: cairo-analysis-surface-private.h,v 1.10 2007/07/24 19:24:27 vladimir%pobox.com Exp $
/* $Id: cairo-analysis-surface-private.h,v 1.11 2007/08/02 06:58:47 vladimir%pobox.com Exp $
*
* Copyright © 2005 Keith Packard
*
@ -43,10 +43,10 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
int width,
int height);
cairo_private pixman_region16_t *
cairo_private cairo_region_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *surface);
cairo_private pixman_region16_t *
cairo_private cairo_region_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-surface-private.h"
#include "cairo-paginated-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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_analysis_surface_t *surface = abstract_surface;
@ -234,14 +234,14 @@ FAIL:
return NULL;
}
cairo_private pixman_region16_t *
cairo_private cairo_region_t *
_cairo_analysis_surface_get_supported (cairo_surface_t *abstract_surface)
{
/* XXX */
return NULL;
}
cairo_private pixman_region16_t *
cairo_private cairo_region_t *
_cairo_analysis_surface_get_unsupported (cairo_surface_t *abstract_surface)
{
/* XXX */

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

@ -34,6 +34,8 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include "cairoint.h"
#include "cairo-arc-private.h"
/* Spline deviation from the circle in radius would be given by:
@ -85,7 +87,7 @@ _arc_max_angle_for_tolerance_normalized (double tolerance)
{ M_PI / 10.0, 1.73863223499021216974e-08 },
{ M_PI / 11.0, 9.81410988043554039085e-09 },
};
int table_size = (sizeof (table) / sizeof (table[0]));
int table_size = ARRAY_LENGTH (table);
for (i = 0; i < table_size; i++)
if (table[i].error < tolerance)

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

@ -34,11 +34,10 @@
* Calum Robinson <calumr@mac.com>
*/
#include <stdlib.h>
#include <math.h>
#include "cairo-atsui.h"
#include "cairoint.h"
#include "cairo.h"
#include "cairo-atsui.h"
#include "cairo-quartz-private.h"
/*
@ -117,8 +116,7 @@ _cairo_atsui_font_face_scaled_font_create (void *abstract_face,
ATSUStyle style;
err = ATSUCreateStyle (&style);
err = ATSUSetAttributes(style,
sizeof(styleTags) / sizeof(styleTags[0]),
err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
styleTags, styleSizes, styleValues);
return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
@ -131,6 +129,19 @@ static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
_cairo_atsui_font_face_scaled_font_create
};
/**
* cairo_atsui_font_face_create_for_atsu_font_id
* @font_id: an ATSUFontID for the font.
*
* Creates a new font for the ATSUI font backend based on an
* #ATSUFontID. This font can then be used with
* cairo_set_font_face() or cairo_scaled_font_create().
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
*
* Since: 1.4
**/
cairo_font_face_t *
cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
{
@ -149,14 +160,6 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
return &font_face->base;
}
static CGAffineTransform
CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale)
{
return CGAffineTransformMake(scale->xx, scale->yx,
scale->xy, scale->yy,
0, 0);
}
static ATSUStyle
CreateSizedCopyOfStyle(ATSUStyle inStyle,
const Fixed *theSize,
@ -232,8 +235,13 @@ _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
if (font == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
&cairo_atsui_scaled_font_backend);
status = _cairo_scaled_font_init (&font->base,
font_face, font_matrix, ctm, options,
&cairo_atsui_scaled_font_backend);
if (status) {
free (font);
return status;
}
_cairo_matrix_compute_scale_factors (&font->base.scale,
&xscale, &yscale, 1);
@ -374,8 +382,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
ByteCount styleSizes[] =
{ sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
err = ATSUSetAttributes(style,
sizeof(styleTags) / sizeof(styleTags[0]),
err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
styleTags, styleSizes, styleValues);
}
@ -397,50 +404,6 @@ _cairo_atsui_font_fini(void *abstract_font)
ATSUDisposeStyle(font->unscaled_style);
}
static
OSStatus _move_to_for_metrics (const Float32Point *point, void *callback_data)
{
CGMutablePathRef path = callback_data;
CGPathMoveToPoint (path, &CGAffineTransformIdentity,
point->x, point->y);
return noErr;
}
static
OSStatus _line_to_for_metrics(const Float32Point *point, void *callback_data)
{
CGMutablePathRef path = callback_data;
CGPathAddLineToPoint (path, &CGAffineTransformIdentity,
point->x, point->y);
return noErr;
}
static
OSStatus _curve_to_for_metrics (const Float32Point *point1,
const Float32Point *point2,
const Float32Point *point3,
void *callback_data)
{
CGMutablePathRef path = callback_data;
CGPathAddCurveToPoint (path, &CGAffineTransformIdentity,
point1->x, point1->y,
point2->x, point2->y,
point3->x, point3->y);
return noErr;
}
static
OSStatus _close_path_for_metrics(void *callback_data)
{
CGMutablePathRef path = callback_data;
CGPathCloseSubpath (path);
return noErr;
}
static GlyphID
_cairo_atsui_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
@ -454,16 +417,10 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
OSStatus err, callback_err;
OSStatus err;
ATSGlyphScreenMetrics metricsH;
static ATSCubicMoveToUPP moveProc = NULL;
static ATSCubicLineToUPP lineProc = NULL;
static ATSCubicCurveToUPP curveProc = NULL;
static ATSCubicClosePathUPP closePathProc = NULL;
CGMutablePathRef path;
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
double xscale, yscale;
CGRect rect;
if (theGlyph == kATSDeletedGlyphcode) {
_cairo_scaled_glyph_set_metrics (scaled_glyph,
@ -490,40 +447,14 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
extents.x_advance = metricsH.deviceAdvance.x * xscale;
extents.y_advance = 0;
if (moveProc == NULL) {
moveProc = NewATSCubicMoveToUPP (_move_to_for_metrics);
lineProc = NewATSCubicLineToUPP (_line_to_for_metrics);
curveProc = NewATSCubicCurveToUPP (_curve_to_for_metrics);
closePathProc = NewATSCubicClosePathUPP (_close_path_for_metrics);
}
path = CGPathCreateMutable ();
/* The callback error contains any error our functions returned.
* Its only meaningful if err != noErr, and we don't currently
* use it for anything.
*/
err = ATSUGlyphGetCubicPaths (scaled_font->style, theGlyph,
moveProc, lineProc, curveProc, closePathProc,
(void *)path, &callback_err);
if (err != noErr) {
CGPathRelease (path);
return CAIRO_STATUS_NO_MEMORY;
}
rect = CGPathGetBoundingBox (path);
extents.x_bearing = rect.origin.x * xscale;
extents.y_bearing = rect.origin.y * yscale;
extents.width = rect.size.width * xscale;
extents.height = rect.size.height * yscale;
extents.x_bearing = metricsH.topLeft.x * xscale;
extents.y_bearing = -metricsH.topLeft.y * yscale;
extents.width = metricsH.width * xscale;
extents.height = metricsH.height * yscale;
_cairo_scaled_glyph_set_metrics (scaled_glyph,
&scaled_font->base,
&extents);
CGPathRelease (path);
return CAIRO_STATUS_SUCCESS;
}
@ -667,6 +598,7 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
CGContextRef drawingContext;
cairo_image_surface_t *surface;
cairo_format_t format;
cairo_status_t status;
ATSFontRef atsFont;
CGFontRef cgFont;
@ -683,8 +615,10 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
if (theGlyph == kATSDeletedGlyphcode) {
surface = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
if (!surface)
return CAIRO_STATUS_NO_MEMORY;
status = cairo_surface_status ((cairo_surface_t *)surface);
if (status)
return status;
_cairo_scaled_glyph_set_surface (scaled_glyph,
&base,
surface);
@ -698,6 +632,12 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
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.
@ -743,8 +683,9 @@ _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
/* create the glyph mask surface */
surface = (cairo_image_surface_t *)cairo_image_surface_create (format, bbox.size.width, bbox.size.height);
if (!surface)
return CAIRO_STATUS_NO_MEMORY;
status = cairo_surface_status ((cairo_surface_t *)surface);
if (status)
return status;
/* Create a CGBitmapContext for the dest surface for drawing into */
{
@ -868,7 +809,7 @@ _cairo_atsui_font_text_to_glyphs (void *abstract_font,
*num_glyphs = glyphCount - 1;
*glyphs =
(cairo_glyph_t *) malloc(*num_glyphs * (sizeof (cairo_glyph_t)));
(cairo_glyph_t *) _cairo_malloc_ab(*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,6 +137,7 @@ typedef struct _cairo_bo_sweep_line {
int32_t current_y;
} cairo_bo_sweep_line_t;
static inline int
_cairo_bo_point32_compare (cairo_bo_point32_t const *a,
cairo_bo_point32_t const *b)
@ -692,13 +693,16 @@ _cairo_bo_event_init (cairo_bo_event_t *event,
event->point = point;
}
static void
static cairo_status_t
_cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
cairo_bo_event_t *event)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
/* Don't insert if there's already an equivalent intersection event in the queue. */
_cairo_skip_list_insert (&queue->intersection_queue, event,
event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION);
if (_cairo_skip_list_insert (&queue->intersection_queue, event,
event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) == NULL)
status = CAIRO_STATUS_NO_MEMORY;
return status;
}
static void
@ -750,16 +754,14 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
* or stop events, so this allocation is safe. XXX: make the
* event type a union so it doesn't always contain the skip
* elt? */
events = malloc (num_events * sizeof(cairo_bo_event_t));
sorted_event_ptrs = malloc (num_events * sizeof(cairo_bo_event_t*));
if (!events || !sorted_event_ptrs) {
if (events) free(events);
if (sorted_event_ptrs) free(sorted_event_ptrs);
events = _cairo_malloc_ab (num_events, sizeof (cairo_bo_event_t) + sizeof(cairo_bo_event_t*));
if (events == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
sorted_event_ptrs = (cairo_bo_event_t **) (events + num_events);
event_queue->startstop_events = events;
event_queue->sorted_startstop_event_ptrs = sorted_event_ptrs;
event_queue->num_startstop_events = (unsigned)(num_events);
event_queue->num_startstop_events = num_events;
event_queue->next_startstop_event_index = 0;
for (i = 0; i < num_edges; i++) {
@ -792,11 +794,9 @@ _cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
_cairo_skip_list_fini (&event_queue->intersection_queue);
if (event_queue->startstop_events)
free (event_queue->startstop_events);
if (event_queue->sorted_startstop_event_ptrs)
free (event_queue->sorted_startstop_event_ptrs);
}
static void
static cairo_status_t
_cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t *event_queue,
cairo_bo_edge_t *left,
cairo_bo_edge_t *right)
@ -806,7 +806,7 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
cairo_bo_event_t event;
if (left == NULL || right == NULL)
return;
return CAIRO_STATUS_SUCCESS;
/* The names "left" and "right" here are correct descriptions of
* the order of the two edges within the active edge list. So if a
@ -814,13 +814,13 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
* that the intersection of these two segments has oalready
* occurred before the current sweep line position. */
if (_slope_compare (left, right) < 0)
return;
return CAIRO_STATUS_SUCCESS;
status = _cairo_bo_edge_intersect (left, right, &intersection);
if (status == CAIRO_BO_STATUS_PARALLEL ||
status == CAIRO_BO_STATUS_NO_INTERSECTION)
{
return;
return CAIRO_STATUS_SUCCESS;
}
_cairo_bo_event_init (&event,
@ -828,7 +828,7 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
left, right,
intersection);
_cairo_bo_event_queue_insert (event_queue, &event);
return _cairo_bo_event_queue_insert (event_queue, &event);
}
static void
@ -848,7 +848,7 @@ _cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
_cairo_skip_list_fini (&sweep_line->active_edges);
}
static void
static cairo_status_t
_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
cairo_bo_edge_t *edge)
{
@ -858,6 +858,8 @@ _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
sweep_line_elt = _cairo_skip_list_insert (&sweep_line->active_edges, &edge,
1 /* unique inserts*/);
if (sweep_line_elt == NULL)
return CAIRO_STATUS_NO_MEMORY;
next_elt = sweep_line_elt->elt.next[0];
if (next_elt)
@ -876,6 +878,8 @@ _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
*next_of_prev = edge;
edge->sweep_line_elt = sweep_line_elt;
return CAIRO_STATUS_SUCCESS;
}
static void
@ -1057,7 +1061,6 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
cairo_bo_traps_t *bo_traps)
{
cairo_fixed_t fixed_top, fixed_bot;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_bo_trap_t *trap = left->deferred_trap;
cairo_bo_edge_t *right;
@ -1099,11 +1102,11 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
left_bot.x != right_bot.x ||
left_bot.y != right_bot.y)
{
status = _cairo_traps_add_trap_from_points (bo_traps->traps,
fixed_top,
fixed_bot,
left_top, left_bot,
right_top, right_bot);
_cairo_traps_add_trap_from_points (bo_traps->traps,
fixed_top,
fixed_bot,
left_top, left_bot,
right_top, right_bot);
#if DEBUG_PRINT_STATE
printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) "
@ -1117,7 +1120,8 @@ _cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
_cairo_freelist_free (&bo_traps->freelist, trap);
left->deferred_trap = NULL;
return status;
return _cairo_traps_status (bo_traps->traps);
}
/* Start a new trapezoid at the given top y coordinate, whose edges
@ -1254,7 +1258,7 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
cairo_fixed_t ymax,
int *num_intersections)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_status_t status;
int intersection_count = 0;
cairo_bo_event_queue_t event_queue;
cairo_bo_sweep_line_t sweep_line;
@ -1264,7 +1268,10 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
cairo_bo_edge_t *left, *right;
cairo_bo_edge_t *edge1, *edge2;
_cairo_bo_event_queue_init (&event_queue, edges, num_edges);
status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
if (status)
return status;
_cairo_bo_sweep_line_init (&sweep_line);
_cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
@ -1296,7 +1303,9 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
case CAIRO_BO_EVENT_TYPE_START:
edge = event->e1;
_cairo_bo_sweep_line_insert (&sweep_line, edge);
status = _cairo_bo_sweep_line_insert (&sweep_line, edge);
if (status)
goto unwind;
/* Cache the insert position for use in pass 2.
event->e2 = Sortlist::prev (sweep_line, edge);
*/
@ -1304,9 +1313,13 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
left = edge->prev;
right = edge->next;
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge);
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge);
if (status)
goto unwind;
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
if (status)
goto unwind;
#if DEBUG_PRINT_STATE
print_state ("After processing start", &event_queue, &sweep_line);
@ -1326,7 +1339,9 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
if (status)
goto unwind;
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
if (status)
goto unwind;
#if DEBUG_PRINT_STATE
print_state ("After processing stop", &event_queue, &sweep_line);
@ -1354,11 +1369,15 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_edge_t *edges,
/* after the swap e2 is left of e1 */
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
left, edge2);
if (status)
goto unwind;
_cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
edge1, right);
if (status)
goto unwind;
#if DEBUG_PRINT_STATE
print_state ("After processing intersection", &event_queue, &sweep_line);
@ -1402,6 +1421,7 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
{
int intersections;
cairo_status_t status;
cairo_bo_edge_t stack_edges[CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_bo_edge_t)];
cairo_bo_edge_t *edges;
cairo_fixed_t xmin = 0x7FFFFFFF;
cairo_fixed_t ymin = 0x7FFFFFFF;
@ -1413,9 +1433,13 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
if (0 == polygon->num_edges)
return CAIRO_STATUS_SUCCESS;
edges = malloc (polygon->num_edges * sizeof (cairo_bo_edge_t));
if (edges == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
edges = stack_edges;
} else {
edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t));
if (edges == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
/* Figure out the bounding box of the input coordinates and
* validate that we're not given invalid polygon edges. */
@ -1495,7 +1519,8 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
xmin, ymin, xmax, ymax,
&intersections);
free (edges);
if (edges != stack_edges)
free (edges);
return status;
}
@ -1732,7 +1757,7 @@ run_test (const char *test_name,
while (intersections) {
int num_edges = _cairo_array_num_elements (&intersected_edges);
passes++;
edges = malloc (num_edges * sizeof (cairo_bo_edge_t));
edges = _cairo_malloc_ab (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);
@ -1771,7 +1796,7 @@ main (void)
unsigned int i, num_random;
test_t *test;
for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i++) {
for (i = 0; i < ARRAY_LENGTH (tests); i++) {
test = &tests[i];
run_test (test->name, test->edges, test->num_edges);
}

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

@ -39,7 +39,7 @@
#ifndef CAIRO_CACHE_PRIVATE_H
#define CAIRO_CACHE_PRIVATE_H
typedef struct _cairo_cache cairo_cache_t;
#include "cairo-types-private.h"
/**
* cairo_cache_entry_t:

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

@ -38,17 +38,6 @@
#include "cairoint.h"
struct _cairo_cache {
cairo_hash_table_t *hash_table;
cairo_destroy_func_t entry_destroy;
unsigned long max_size;
unsigned long size;
int freeze_count;
};
static void
_cairo_cache_remove (cairo_cache_t *cache,
cairo_cache_entry_t *entry);

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

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

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

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

@ -1,3 +1,4 @@
/* -*- 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
@ -61,28 +62,13 @@ _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
clip->serial = 0;
clip->region = NULL;
_cairo_region_init (&clip->region);
clip->has_region = FALSE;
clip->path = NULL;
}
void
_cairo_clip_fini (cairo_clip_t *clip)
{
cairo_surface_destroy (clip->surface);
clip->surface = NULL;
clip->serial = 0;
if (clip->region)
pixman_region_destroy (clip->region);
clip->region = NULL;
_cairo_clip_path_destroy (clip->path);
clip->path = NULL;
}
void
cairo_status_t
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
{
clip->mode = other->mode;
@ -92,17 +78,27 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
clip->serial = other->serial;
if (other->region == NULL) {
clip->region = other->region;
_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;
} else {
clip->region = pixman_region_create ();
pixman_region_copy (clip->region, other->region);
clip->has_region = FALSE;
}
clip->path = _cairo_clip_path_reference (other->path);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
void
_cairo_clip_reset (cairo_clip_t *clip)
{
/* destroy any existing clip-region artifacts */
@ -111,25 +107,29 @@ _cairo_clip_reset (cairo_clip_t *clip)
clip->serial = 0;
if (clip->region)
pixman_region_destroy (clip->region);
clip->region = NULL;
if (clip->has_region) {
/* _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;
}
_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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
while (clip_path) {
cairo_status_t status;
cairo_traps_t traps;
cairo_box_t extents;
cairo_rectangle_int16_t extents_rect;
cairo_rectangle_int_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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
if (!clip)
return CAIRO_STATUS_SUCCESS;
@ -170,27 +170,22 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
return status;
}
if (clip->region) {
pixman_region16_t *intersection;
if (clip->has_region) {
cairo_status_t status = CAIRO_STATUS_SUCCESS;
pixman_region_status_t pixman_status;
cairo_region_t intersection;
intersection = _cairo_region_create_from_rectangle (rectangle);
if (intersection == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_region_init_rect (&intersection, rectangle);
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;
status = _cairo_region_intersect (&intersection, &clip->region,
&intersection);
pixman_region_destroy (intersection);
if (!status)
_cairo_region_get_extents (&intersection, rectangle);
if (status)
return status;
_cairo_region_fini (&intersection);
if (status)
return status;
}
if (clip->surface)
@ -201,8 +196,10 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_status_t
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
pixman_region16_t *region)
cairo_region_t *region)
{
cairo_status_t status;
if (!clip)
return CAIRO_STATUS_SUCCESS;
@ -210,30 +207,25 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
/* Intersect clip path into region. */
}
if (clip->region)
pixman_region_intersect (region, clip->region, region);
if (clip->surface) {
pixman_region16_t *clip_rect;
pixman_region_status_t pixman_status;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
if (clip_rect == NULL)
return CAIRO_STATUS_NO_MEMORY;
pixman_status = pixman_region_intersect (region,
clip_rect,
region);
if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
status = CAIRO_STATUS_NO_MEMORY;
pixman_region_destroy (clip_rect);
if (clip->has_region) {
status = _cairo_region_intersect (region, &clip->region, region);
if (status)
return status;
}
if (clip->surface) {
cairo_region_t clip_rect;
_cairo_region_init_rect (&clip_rect, &clip->surface_rect);
status = _cairo_region_intersect (region, &clip_rect, region);
_cairo_region_fini (&clip_rect);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}
@ -247,7 +239,7 @@ _cairo_clip_combine_to_surface (cairo_clip_t *clip,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int16_t *extents)
const cairo_rectangle_int_t *extents)
{
cairo_pattern_union_t pattern;
cairo_status_t status;
@ -329,42 +321,44 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
free (clip_path);
}
static cairo_status_t
static cairo_int_status_t
_cairo_clip_intersect_region (cairo_clip_t *clip,
cairo_traps_t *traps,
cairo_surface_t *target)
{
pixman_region16_t *region;
cairo_status_t status;
cairo_region_t region;
cairo_int_status_t status;
if (clip->mode != CAIRO_CLIP_MODE_REGION)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_traps_extract_region (traps, &region);
if (status)
return status;
if (region == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = CAIRO_STATUS_SUCCESS;
if (clip->region == NULL) {
clip->region = region;
} else {
pixman_region16_t *intersection = pixman_region_create();
if (pixman_region_intersect (intersection,
clip->region, region)
== PIXMAN_REGION_STATUS_SUCCESS) {
pixman_region_destroy (clip->region);
clip->region = intersection;
} else {
status = CAIRO_STATUS_NO_MEMORY;
}
pixman_region_destroy (region);
if (!clip->has_region) {
status = _cairo_region_copy (&clip->region, &region);
if (status == CAIRO_STATUS_SUCCESS)
clip->has_region = TRUE;
} else {
cairo_region_t intersection;
_cairo_region_init (&intersection);
status = _cairo_region_intersect (&intersection,
&clip->region,
&region);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_region_copy (&clip->region, &intersection);
_cairo_region_fini (&intersection);
}
clip->serial = _cairo_surface_allocate_clip_serial (target);
_cairo_region_fini (&region);
return status;
}
@ -377,7 +371,7 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
{
cairo_pattern_union_t pattern;
cairo_box_t extents;
cairo_rectangle_int16_t surface_rect, target_rect;
cairo_rectangle_int_t surface_rect, target_rect;
cairo_surface_t *surface;
cairo_status_t status;
@ -402,14 +396,16 @@ _cairo_clip_intersect_mask (cairo_clip_t *clip,
CAIRO_CONTENT_ALPHA,
surface_rect.width,
surface_rect.height,
CAIRO_COLOR_WHITE);
CAIRO_COLOR_WHITE,
NULL);
if (surface->status)
return CAIRO_STATUS_NO_MEMORY;
/* Render the new clipping path into the new mask surface. */
_cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
&pattern.base,
@ -509,8 +505,8 @@ _cairo_clip_translate (cairo_clip_t *clip,
cairo_fixed_t tx,
cairo_fixed_t ty)
{
if (clip->region) {
pixman_region_translate (clip->region,
if (clip->has_region) {
_cairo_region_translate (&clip->region,
_cairo_fixed_integer_part (tx),
_cairo_fixed_integer_part (ty));
}
@ -549,7 +545,7 @@ _cairo_clip_path_reapply_clip_path (cairo_clip_t *clip,
clip_path->antialias);
}
void
cairo_status_t
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
cairo_clip_t *other,
cairo_surface_t *target)
@ -560,18 +556,22 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
/* We should reapply the original clip path in this case, and let
* whatever the right handling is happen */
} else {
if (other->region) {
clip->region = pixman_region_create ();
pixman_region_copy (clip->region, other->region);
if (other->has_region) {
if (_cairo_region_copy (&clip->region, &other->region) !=
CAIRO_STATUS_SUCCESS)
goto BAIL;
clip->has_region = TRUE;
}
if (other->surface) {
_cairo_surface_clone_similar (target, other->surface,
if (_cairo_surface_clone_similar (target, other->surface,
other->surface_rect.x,
other->surface_rect.y,
other->surface_rect.width,
other->surface_rect.height,
&clip->surface);
&clip->surface) !=
CAIRO_STATUS_SUCCESS)
goto BAIL;
clip->surface_rect = other->surface_rect;
}
@ -579,6 +579,16 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
_cairo_clip_path_reapply_clip_path (clip, other->path);
}
}
return CAIRO_STATUS_SUCCESS;
BAIL:
if (clip->has_region)
_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 =
@ -587,19 +597,24 @@ static const cairo_rectangle_list_t _cairo_rectangles_not_representable =
{ CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, NULL, 0 };
static cairo_bool_t
_cairo_clip_rect_to_user (cairo_gstate_t *gstate,
double x, double y, double width, double height,
cairo_rectangle_t *rectangle)
_cairo_clip_int_rect_to_user (cairo_gstate_t *gstate,
cairo_rectangle_int_t *clip_rect,
cairo_rectangle_t *user_rect)
{
double x2 = x + width;
double y2 = y + height;
cairo_bool_t is_tight;
_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;
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;
return is_tight;
}
@ -607,42 +622,51 @@ 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;
cairo_rectangle_t *rectangles = NULL;
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;
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;
if (clip->has_region) {
cairo_box_int_t *boxes;
int i;
boxes = pixman_region_rects (clip->region);
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;
}
for (i = 0; i < n_boxes; ++i) {
if (!_cairo_clip_rect_to_user(gstate, boxes[i].x1, boxes[i].y1,
boxes[i].x2 - boxes[i].x1,
boxes[i].y2 - boxes[i].y1,
&rectangles[i])) {
free (rectangles);
return (cairo_rectangle_list_t*)
&_cairo_rectangles_not_representable;
}
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;
}
}
} else {
cairo_rectangle_int16_t extents;
_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents);
if (!_cairo_clip_rect_to_user(gstate, extents.x, extents.y,
extents.width, extents.height,
rectangles)) {
free (rectangles);
return (cairo_rectangle_list_t*)
&_cairo_rectangles_not_representable;
}
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;
}
}
list = malloc (sizeof (cairo_rectangle_list_t));

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

@ -160,3 +160,13 @@ _cairo_color_get_rgba_premultiplied (cairo_color_t *color,
*blue = color->blue * color->alpha;
*alpha = color->alpha;
}
cairo_bool_t
_cairo_color_equal (const cairo_color_t *color_a,
const cairo_color_t *color_b)
{
return color_a->red_short == color_b->red_short &&
color_a->green_short == color_b->green_short &&
color_a->blue_short == color_b->blue_short &&
color_a->alpha_short == color_b->alpha_short;
}

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

@ -59,13 +59,11 @@
void
cairo_debug_reset_static_data (void)
{
#if CAIRO_HAS_XLIB_SURFACE
_cairo_xlib_screen_reset_static_data ();
#endif
_cairo_font_reset_static_data ();
#if CAIRO_HAS_FT_FONT
_cairo_ft_font_reset_static_data ();
#endif
_cairo_pattern_reset_static_data ();
}

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

@ -119,7 +119,7 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output)
stream = malloc (sizeof (cairo_deflate_stream_t));
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
_cairo_output_stream_init (&stream->base,
_cairo_deflate_stream_write,
@ -130,8 +130,10 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output)
stream->zlib_stream.zfree = Z_NULL;
stream->zlib_stream.opaque = Z_NULL;
if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK) {
free (stream);
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
}
stream->zlib_stream.next_in = stream->input_buf;
stream->zlib_stream.avail_in = 0;

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

@ -35,10 +35,9 @@
* Claudio Ciccani <klan@users.sf.net>
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "cairoint.h"
#include "cairo-directfb.h"
#include <directfb.h>
@ -47,9 +46,6 @@
#include <direct/memcpy.h>
#include <direct/util.h>
#include "cairo-directfb.h"
#include "cairoint.h"
/*
* Rectangle causes problems (see bugs 361377, 359553, 359243 in Gnome BTS).
@ -324,9 +320,9 @@ _directfb_buffer_surface_create (IDirectFB *dfb,
static cairo_status_t
_directfb_acquire_surface (cairo_directfb_surface_t *surface,
cairo_rectangle_int16_t *intrest_rec,
cairo_rectangle_int_t *intrest_rec,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect_out,
cairo_rectangle_int_t *image_rect_out,
void **image_extra,
DFBSurfaceLockFlags lock_flags)
{
@ -337,7 +333,7 @@ _directfb_acquire_surface (cairo_directfb_surface_t *surface,
cairo_format_t cairo_format;
cairo_format = surface->format;
if (surface->format == -1) {
if (surface->format == (cairo_format_t) -1) {
if( intrest_rec ) {
source_rect.x = intrest_rec->x;
source_rect.y = intrest_rec->y;
@ -503,9 +499,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_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect_out,
cairo_rectangle_int_t *image_rect_out,
void **image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
@ -519,9 +515,9 @@ _cairo_directfb_surface_acquire_dest_image (void *abstract_sur
static void
_cairo_directfb_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
cairo_directfb_surface_t *surface = abstract_surface;
@ -915,7 +911,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_int16_t *rects,
cairo_rectangle_int_t *rects,
int n_rects)
{
cairo_directfb_surface_t *dst = abstract_surface;
@ -1099,8 +1095,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,
pixman_region16_t *region)
_cairo_directfb_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
{
cairo_directfb_surface_t *surface = abstract_surface;
@ -1109,16 +1105,19 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface,
__FUNCTION__, surface, region);
if (region) {
pixman_box16_t *boxes = pixman_region_rects (region);
int n_boxes = pixman_region_num_rects (region);
int i;
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;
if (surface->n_clips != n_boxes) {
if( surface->clips )
free (surface->clips);
surface->clips = malloc (n_boxes * sizeof(DFBRegion));
surface->clips = _cairo_malloc_ab (n_boxes, sizeof(DFBRegion));
if (!surface->clips) {
_cairo_region_boxes_fini (region, boxes);
surface->n_clips = 0;
return CAIRO_STATUS_NO_MEMORY;
}
@ -1127,11 +1126,13 @@ _cairo_directfb_surface_set_clip_region (void *abstract_surface,
}
for (i = 0; i < n_boxes; i++) {
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;
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;
}
_cairo_region_boxes_fini (region, boxes);
}
else {
if (surface->clips) {
@ -1146,7 +1147,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_directfb_surface_t *surface = abstract_surface;
@ -1515,6 +1516,17 @@ _cairo_directfb_surface_show_glyphs ( void *abstract_dst,
#endif /* DFB_SHOW_GLYPHS */
static cairo_bool_t
_cairo_directfb_surface_is_similar (void *surface_a,
void *surface_b,
cairo_content_t content)
{
cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
return a->dfb == b->dfb;
}
static cairo_surface_backend_t cairo_directfb_surface_backend = {
CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/
_cairo_directfb_surface_create_similar,/*create_similar*/
@ -1564,7 +1576,9 @@ static cairo_surface_backend_t cairo_directfb_surface_backend = {
#else
NULL, /* show_glyphs */
#endif
NULL /* snapshot */
NULL, /* snapshot */
_cairo_directfb_surface_is_similar,
NULL /* reset */
};

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

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

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

@ -52,10 +52,10 @@
#endif
#define CAIRO_VERSION_MAJOR 1
#define CAIRO_VERSION_MINOR 4
#define CAIRO_VERSION_MICRO 2
#define CAIRO_VERSION_MINOR 5
#define CAIRO_VERSION_MICRO 1
#define CAIRO_VERSION_STRING "1.4.2"
#define CAIRO_VERSION_STRING "1.5.1"
@PS_SURFACE_FEATURE@

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

@ -36,102 +36,4 @@
#include "cairoint.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);
}
#include "cairo-fixed-private.h"

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

@ -36,7 +36,7 @@
#include "cairoint.h"
static const cairo_font_options_t cairo_font_options_nil = {
static const cairo_font_options_t _cairo_font_options_nil = {
CAIRO_ANTIALIAS_DEFAULT,
CAIRO_SUBPIXEL_ORDER_DEFAULT,
CAIRO_HINT_STYLE_DEFAULT,
@ -52,7 +52,7 @@ static const cairo_font_options_t cairo_font_options_nil = {
void
_cairo_font_options_init_default (cairo_font_options_t *options)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
return;
options->antialias = CAIRO_ANTIALIAS_DEFAULT;
@ -89,7 +89,7 @@ cairo_font_options_create (void)
cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
if (!options)
return (cairo_font_options_t *)&cairo_font_options_nil;
return (cairo_font_options_t *)&_cairo_font_options_nil;
_cairo_font_options_init_default (options);
@ -113,10 +113,14 @@ slim_hidden_def (cairo_font_options_create);
cairo_font_options_t *
cairo_font_options_copy (const cairo_font_options_t *original)
{
cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
cairo_font_options_t *options;
if (original == &_cairo_font_options_nil)
return (cairo_font_options_t *)&_cairo_font_options_nil;
options = malloc (sizeof (cairo_font_options_t));
if (!options)
return (cairo_font_options_t *)&cairo_font_options_nil;
return (cairo_font_options_t *)&_cairo_font_options_nil;
_cairo_font_options_init_copy (options, original);
@ -133,7 +137,7 @@ cairo_font_options_copy (const cairo_font_options_t *original)
void
cairo_font_options_destroy (cairo_font_options_t *options)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
return;
free (options);
@ -152,11 +156,12 @@ slim_hidden_def (cairo_font_options_destroy);
cairo_status_t
cairo_font_options_status (cairo_font_options_t *options)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
return CAIRO_STATUS_NO_MEMORY;
else
return CAIRO_STATUS_SUCCESS;
}
slim_hidden_def (cairo_font_options_status);
/**
* cairo_font_options_merge:
@ -172,7 +177,7 @@ void
cairo_font_options_merge (cairo_font_options_t *options,
const cairo_font_options_t *other)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
return;
if (other->antialias != CAIRO_ANTIALIAS_DEFAULT)
@ -240,7 +245,7 @@ void
cairo_font_options_set_antialias (cairo_font_options_t *options,
cairo_antialias_t antialias)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
return;
options->antialias = antialias;
@ -276,7 +281,7 @@ void
cairo_font_options_set_subpixel_order (cairo_font_options_t *options,
cairo_subpixel_order_t subpixel_order)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
return;
options->subpixel_order = subpixel_order;
@ -312,7 +317,7 @@ void
cairo_font_options_set_hint_style (cairo_font_options_t *options,
cairo_hint_style_t hint_style)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
return;
options->hint_style = hint_style;
@ -348,7 +353,7 @@ void
cairo_font_options_set_hint_metrics (cairo_font_options_t *options,
cairo_hint_metrics_t hint_metrics)
{
if (options == (cairo_font_options_t *)&cairo_font_options_nil)
if (options == (cairo_font_options_t *)&_cairo_font_options_nil)
return;
options->hint_metrics = hint_metrics;

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

@ -1,516 +0,0 @@
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2002 University of Southern California
* Copyright © 2005 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
*/
#include "cairoint.h"
/* Forward declare so we can use it as an arbitrary backend for
* _cairo_font_face_nil.
*/
static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
/* cairo_font_face_t */
const cairo_font_face_t _cairo_font_face_nil = {
{ 0 }, /* hash_entry */
CAIRO_STATUS_NO_MEMORY, /* status */
CAIRO_REF_COUNT_INVALID, /* ref_count */
{ 0, 0, 0, NULL }, /* user_data */
&_cairo_toy_font_face_backend
};
void
_cairo_font_face_init (cairo_font_face_t *font_face,
const cairo_font_face_backend_t *backend)
{
font_face->status = CAIRO_STATUS_SUCCESS;
font_face->ref_count = 1;
font_face->backend = backend;
_cairo_user_data_array_init (&font_face->user_data);
}
/* This mutex protects both cairo_toy_font_hash_table as well as
reference count manipulations for all cairo_font_face_t. */
CAIRO_MUTEX_DECLARE (_cairo_font_face_mutex);
/**
* cairo_font_face_reference:
* @font_face: a #cairo_font_face_t, (may be %NULL in which case this
* function does nothing).
*
* Increases the reference count on @font_face by one. This prevents
* @font_face from being destroyed until a matching call to
* cairo_font_face_destroy() is made.
*
* The number of references to a #cairo_font_face_t can be get using
* cairo_font_face_get_reference_count().
*
* Return value: the referenced #cairo_font_face_t.
**/
cairo_font_face_t *
cairo_font_face_reference (cairo_font_face_t *font_face)
{
if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
return font_face;
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
/* We would normally assert (font_face->ref_count >0) here but we
* can't get away with that due to the zombie case as documented
* in _cairo_ft_font_face_destroy. */
font_face->ref_count++;
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
return font_face;
}
slim_hidden_def (cairo_font_face_reference);
/**
* cairo_font_face_destroy:
* @font_face: a #cairo_font_face_t
*
* Decreases the reference count on @font_face by one. If the result
* is zero, then @font_face and all associated resources are freed.
* See cairo_font_face_reference().
**/
void
cairo_font_face_destroy (cairo_font_face_t *font_face)
{
if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
return;
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
assert (font_face->ref_count > 0);
if (--(font_face->ref_count) > 0) {
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
return;
}
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
font_face->backend->destroy (font_face);
/* We allow resurrection to deal with some memory management for the
* FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
* need to effectively mutually reference each other
*/
if (font_face->ref_count > 0)
return;
_cairo_user_data_array_fini (&font_face->user_data);
free (font_face);
}
slim_hidden_def (cairo_font_face_destroy);
/**
* cairo_font_face_get_type:
* @font_face: a font face
*
* This function returns the type of the backend used to create
* a font face. See #cairo_font_type_t for available types.
*
* Return value: The type of @font_face.
*
* Since: 1.2
**/
cairo_font_type_t
cairo_font_face_get_type (cairo_font_face_t *font_face)
{
return font_face->backend->type;
}
/**
* cairo_font_face_get_reference_count:
* @font_face: a #cairo_font_face_t
*
* Returns the current reference count of @font_face.
*
* Return value: the current reference count of @font_face. If the
* object is a nil object, 0 will be returned.
*
* Since: 1.4
**/
unsigned int
cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
{
if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID)
return 0;
return font_face->ref_count;
}
/**
* cairo_font_face_status:
* @font_face: a #cairo_font_face_t
*
* Checks whether an error has previously occurred for this
* font face
*
* Return value: %CAIRO_STATUS_SUCCESS or another error such as
* %CAIRO_STATUS_NO_MEMORY.
**/
cairo_status_t
cairo_font_face_status (cairo_font_face_t *font_face)
{
return font_face->status;
}
/**
* cairo_font_face_get_user_data:
* @font_face: a #cairo_font_face_t
* @key: the address of the #cairo_user_data_key_t the user data was
* attached to
*
* Return user data previously attached to @font_face using the specified
* key. If no user data has been attached with the given key this
* function returns %NULL.
*
* Return value: the user data previously attached or %NULL.
**/
void *
cairo_font_face_get_user_data (cairo_font_face_t *font_face,
const cairo_user_data_key_t *key)
{
return _cairo_user_data_array_get_data (&font_face->user_data,
key);
}
/**
* cairo_font_face_set_user_data:
* @font_face: a #cairo_font_face_t
* @key: the address of a #cairo_user_data_key_t to attach the user data to
* @user_data: the user data to attach to the font face
* @destroy: a #cairo_destroy_func_t which will be called when the
* font face is destroyed or when new user data is attached using the
* same key.
*
* Attach user data to @font_face. To remove user data from a font face,
* call this function with the key that was used to set it and %NULL
* for @data.
*
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
* slot could not be allocated for the user data.
**/
cairo_status_t
cairo_font_face_set_user_data (cairo_font_face_t *font_face,
const cairo_user_data_key_t *key,
void *user_data,
cairo_destroy_func_t destroy)
{
if (font_face->ref_count == CAIRO_REF_COUNT_INVALID)
return CAIRO_STATUS_NO_MEMORY;
return _cairo_user_data_array_set_data (&font_face->user_data,
key, user_data, destroy);
}
static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
static int
_cairo_toy_font_face_keys_equal (const void *key_a,
const void *key_b);
/* We maintain a hash table from family/weight/slant =>
* cairo_font_face_t for cairo_toy_font_t. The primary purpose of
* this mapping is to provide unique cairo_font_face_t values so that
* our cache and mapping from cairo_font_face_t => cairo_scaled_font_t
* works. Once the corresponding cairo_font_face_t objects fall out of
* downstream caches, we don't need them in this hash table anymore.
*
* Modifications to this hash table are protected by
* _cairo_font_face_mutex.
*/
static cairo_hash_table_t *cairo_toy_font_face_hash_table = NULL;
static cairo_hash_table_t *
_cairo_toy_font_face_hash_table_lock (void)
{
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
if (cairo_toy_font_face_hash_table == NULL)
{
cairo_toy_font_face_hash_table =
_cairo_hash_table_create (_cairo_toy_font_face_keys_equal);
if (cairo_toy_font_face_hash_table == NULL) {
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
return NULL;
}
}
return cairo_toy_font_face_hash_table;
}
static void
_cairo_toy_font_face_hash_table_unlock (void)
{
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
}
/**
* _cairo_toy_font_face_init_key:
*
* Initialize those portions of cairo_toy_font_face_t needed to use
* it as a hash table key, including the hash code buried away in
* font_face->base.hash_entry. No memory allocation is performed here
* so that no fini call is needed. We do this to make it easier to use
* an automatic cairo_toy_font_face_t variable as a key.
**/
static void
_cairo_toy_font_face_init_key (cairo_toy_font_face_t *key,
const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
unsigned long hash;
key->family = family;
key->owns_family = FALSE;
key->slant = slant;
key->weight = weight;
/* 1607 and 1451 are just a couple of arbitrary primes. */
hash = _cairo_hash_string (family);
hash += ((unsigned long) slant) * 1607;
hash += ((unsigned long) weight) * 1451;
key->base.hash_entry.hash = hash;
}
static cairo_status_t
_cairo_toy_font_face_init (cairo_toy_font_face_t *font_face,
const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
char *family_copy;
family_copy = strdup (family);
if (family_copy == NULL)
return CAIRO_STATUS_NO_MEMORY;
_cairo_toy_font_face_init_key (font_face, family_copy,
slant, weight);
font_face->owns_family = TRUE;
_cairo_font_face_init (&font_face->base, &_cairo_toy_font_face_backend);
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_toy_font_face_fini (cairo_toy_font_face_t *font_face)
{
/* We assert here that we own font_face->family before casting
* away the const qualifer. */
assert (font_face->owns_family);
free ((char*) font_face->family);
}
static int
_cairo_toy_font_face_keys_equal (const void *key_a,
const void *key_b)
{
const cairo_toy_font_face_t *face_a = key_a;
const cairo_toy_font_face_t *face_b = key_b;
return (strcmp (face_a->family, face_b->family) == 0 &&
face_a->slant == face_b->slant &&
face_a->weight == face_b->weight);
}
/**
* _cairo_toy_font_face_create:
* @family: a font family name, encoded in UTF-8
* @slant: the slant for the font
* @weight: the weight for the font
*
* Creates a font face from a triplet of family, slant, and weight.
* These font faces are used in implementation of the the #cairo_t "toy"
* font API.
*
* Return value: a newly created #cairo_font_face_t, destroy with
* cairo_font_face_destroy()
**/
cairo_font_face_t *
_cairo_toy_font_face_create (const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
cairo_status_t status;
cairo_toy_font_face_t key, *font_face;
cairo_hash_table_t *hash_table;
hash_table = _cairo_toy_font_face_hash_table_lock ();
if (hash_table == NULL)
goto UNWIND;
_cairo_toy_font_face_init_key (&key, family, slant, weight);
/* Return existing font_face if it exists in the hash table. */
if (_cairo_hash_table_lookup (hash_table,
&key.base.hash_entry,
(cairo_hash_entry_t **) &font_face))
{
/* We increment the reference count here manually to avoid
double-locking. */
font_face->base.ref_count++;
_cairo_toy_font_face_hash_table_unlock ();
return &font_face->base;
}
/* Otherwise create it and insert into hash table. */
font_face = malloc (sizeof (cairo_toy_font_face_t));
if (font_face == NULL)
goto UNWIND_HASH_TABLE_LOCK;
status = _cairo_toy_font_face_init (font_face, family, slant, weight);
if (status)
goto UNWIND_FONT_FACE_MALLOC;
status = _cairo_hash_table_insert (hash_table, &font_face->base.hash_entry);
if (status)
goto UNWIND_FONT_FACE_INIT;
_cairo_toy_font_face_hash_table_unlock ();
return &font_face->base;
UNWIND_FONT_FACE_INIT:
UNWIND_FONT_FACE_MALLOC:
free (font_face);
UNWIND_HASH_TABLE_LOCK:
_cairo_toy_font_face_hash_table_unlock ();
UNWIND:
return (cairo_font_face_t*) &_cairo_font_face_nil;
}
static void
_cairo_toy_font_face_destroy (void *abstract_face)
{
cairo_toy_font_face_t *font_face = abstract_face;
cairo_hash_table_t *hash_table;
if (font_face == NULL)
return;
hash_table = _cairo_toy_font_face_hash_table_lock ();
/* All created objects must have been mapped in the hash table. */
assert (hash_table != NULL);
_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
_cairo_toy_font_face_hash_table_unlock ();
_cairo_toy_font_face_fini (font_face);
}
static cairo_status_t
_cairo_toy_font_face_scaled_font_create (void *abstract_font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_scaled_font_t **scaled_font)
{
cairo_toy_font_face_t *font_face = abstract_font_face;
const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
return backend->create_toy (font_face,
font_matrix, ctm, options, scaled_font);
}
static const cairo_font_face_backend_t _cairo_toy_font_face_backend = {
CAIRO_FONT_TYPE_TOY,
_cairo_toy_font_face_destroy,
_cairo_toy_font_face_scaled_font_create
};
void
_cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font,
const cairo_unscaled_font_backend_t *backend)
{
unscaled_font->ref_count = 1;
unscaled_font->backend = backend;
}
cairo_unscaled_font_t *
_cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
{
if (unscaled_font == NULL)
return NULL;
unscaled_font->ref_count++;
return unscaled_font;
}
void
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
{
if (unscaled_font == NULL)
return;
if (--(unscaled_font->ref_count) > 0)
return;
unscaled_font->backend->destroy (unscaled_font);
free (unscaled_font);
}
void
_cairo_font_reset_static_data (void)
{
_cairo_scaled_font_map_destroy ();
/* We manually acquire the lock rather than calling
* cairo_toy_font_face_hash_table_lock simply to avoid
* creating the table only to destroy it again. */
CAIRO_MUTEX_LOCK (_cairo_font_face_mutex);
_cairo_hash_table_destroy (cairo_toy_font_face_hash_table);
cairo_toy_font_face_hash_table = NULL;
CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex);
}

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

@ -26,8 +26,6 @@
#include <stddef.h>
/* Opaque implementation types. */
struct _cairo_freelist;
struct _cairo_freelist_node;
typedef struct _cairo_freelist cairo_freelist_t;
typedef struct _cairo_freelist_node cairo_freelist_node_t;

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

@ -19,8 +19,9 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "cairoint.h"
#include "cairo-freelist-private.h"
void

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

@ -37,10 +37,12 @@
* Carl Worth <cworth@cworth.org>
*/
#include <float.h>
#include "cairoint.h"
#include "cairo-ft-private.h"
#include <float.h>
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
@ -62,12 +64,6 @@
*/
#define MAX_OPEN_FACES 10
#ifndef MOZILLA_CAIRO_NOT_DEFINED
/* This is the maximum font size we allow to be passed to FT_Set_Char_Size
*/
#define MAX_FONT_SIZE 1000
#endif /* !MOZILLA_CAIRO_NOT_DEFINED */
/*
* The simple 2x2 matrix is converted into separate scale and shape
* factors so that hinting works right
@ -156,8 +152,6 @@ typedef struct _cairo_ft_unscaled_font_map {
static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
CAIRO_MUTEX_DECLARE(_cairo_ft_unscaled_font_map_mutex);
static void
_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
cairo_ft_unscaled_font_t *unscaled)
@ -261,6 +255,7 @@ _cairo_ft_unscaled_font_map_lock (void)
if (cairo_ft_unscaled_font_map == NULL) {
CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
}
@ -333,14 +328,16 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
unscaled->face = NULL;
filename_copy = strdup (filename);
if (filename_copy == NULL)
if (filename_copy == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);
}
unscaled->have_scale = FALSE;
CAIRO_MUTEX_INIT (&unscaled->mutex);
CAIRO_MUTEX_INIT (unscaled->mutex);
unscaled->lock_count = 0;
unscaled->faces = NULL;
@ -375,7 +372,7 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
unscaled->filename = NULL;
}
CAIRO_MUTEX_FINI (&unscaled->mutex);
CAIRO_MUTEX_FINI (unscaled->mutex);
}
static int
@ -419,8 +416,8 @@ _cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
(cairo_hash_entry_t **) &unscaled))
{
_cairo_ft_unscaled_font_map_unlock ();
_cairo_unscaled_font_reference (&unscaled->base);
_cairo_ft_unscaled_font_map_unlock ();
return unscaled;
}
@ -556,6 +553,7 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
&face) != FT_Err_Ok)
{
CAIRO_MUTEX_UNLOCK (unscaled->mutex);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
@ -614,7 +612,7 @@ _compute_transform (cairo_ft_font_transform_t *sf,
/* Temporarily scales an unscaled font to the give scale. We catch
* scaling to the same size, since changing a FT_Face is expensive.
*/
static void
static cairo_status_t
_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
cairo_matrix_t *scale)
{
@ -629,7 +627,7 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
scale->yx == unscaled->current_scale.yx &&
scale->xy == unscaled->current_scale.xy &&
scale->yy == unscaled->current_scale.yy)
return;
return CAIRO_STATUS_SUCCESS;
unscaled->have_scale = TRUE;
unscaled->current_scale = *scale;
@ -658,27 +656,14 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
FT_Set_Transform(unscaled->face, &mat, NULL);
if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
#ifndef MOZILLA_CAIRO_NOT_DEFINED
double x_scale = sf.x_scale;
double y_scale = sf.y_scale;
if (x_scale > MAX_FONT_SIZE) {
x_scale = MAX_FONT_SIZE;
}
if (y_scale > MAX_FONT_SIZE) {
y_scale = MAX_FONT_SIZE;
}
error = FT_Set_Char_Size (unscaled->face,
sf.x_scale * 64.0,
sf.y_scale * 64.0,
0, 0);
#else
error = FT_Set_Char_Size (unscaled->face,
x_scale * 64.0,
y_scale * 64.0,
0, 0);
#endif /* MOZCAIRO */
assert (error == 0);
if (error) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
} else {
double min_distance = DBL_MAX;
int i;
@ -707,8 +692,13 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
error = FT_Set_Pixel_Sizes (unscaled->face,
unscaled->face->available_sizes[best_i].width,
unscaled->face->available_sizes[best_i].height);
assert (error == 0);
if (error) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
}
return CAIRO_STATUS_SUCCESS;
}
/* Empirically-derived subpixel filtering values thanks to Keith
@ -752,9 +742,11 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
data = bitmap->buffer;
assert (stride == bitmap->pitch);
} else {
data = malloc (stride * height);
if (!data)
data = _cairo_malloc_ab (height, stride);
if (!data) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
if (stride == bitmap->pitch) {
memcpy (data, bitmap->buffer, stride * height);
@ -800,9 +792,11 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
if (own_buffer) {
data = bitmap->buffer;
} else {
data = malloc (stride * height);
if (!data)
data = _cairo_malloc_ab (height, stride);
if (!data) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
memcpy (data, bitmap->buffer, stride * height);
}
format = CAIRO_FORMAT_A8;
@ -841,6 +835,12 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
stride = bitmap->pitch;
stride_rgba = (width_rgba * 4 + 3) & ~3;
data_rgba = calloc (1, stride_rgba * height);
if (data_rgba == NULL) {
if (own_buffer)
free (bitmap->buffer);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
os = 1;
switch (font_options->subpixel_order) {
@ -905,6 +905,9 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
case FT_PIXEL_MODE_GRAY4:
/* These could be triggered by very rare types of TrueType fonts */
default:
if (own_buffer)
free (bitmap->buffer);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
@ -1035,6 +1038,7 @@ _render_glyph_outline (FT_Face face,
bitmap.buffer = calloc (1, stride * bitmap.rows);
if (bitmap.buffer == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
@ -1042,6 +1046,7 @@ _render_glyph_outline (FT_Face face,
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
free (bitmap.buffer);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
@ -1079,8 +1084,10 @@ _render_glyph_bitmap (FT_Face face,
* we avoid the FT_LOAD_NO_RECURSE flag.
*/
error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
if (error)
if (error) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
if (status)
@ -1178,24 +1185,33 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
/* Initialize it to empty
*/
_cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
0, 0,
width, height);
status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
0, 0,
width, height);
if (status) {
cairo_surface_destroy (image);
return status;
}
/* Draw the original bitmap transformed into the new bitmap
*/
_cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
_cairo_surface_composite (CAIRO_OPERATOR_OVER,
&pattern.base, NULL, image,
0, 0, 0, 0, 0, 0,
width,
height);
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
&pattern.base, NULL, image,
0, 0, 0, 0, 0, 0,
width,
height);
_cairo_pattern_fini (&pattern.base);
if (status) {
cairo_surface_destroy (image);
return status;
}
/* Now update the cache entry for the new bitmap, recomputing
* the origin based on the final transform.
*/
@ -1445,6 +1461,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
FT_Face face;
FT_Size_Metrics *metrics;
cairo_font_extents_t fs_metrics;
cairo_status_t status;
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
@ -1453,6 +1470,7 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
scaled_font = malloc (sizeof(cairo_ft_scaled_font_t));
if (scaled_font == NULL) {
_cairo_ft_unscaled_font_unlock_face (unscaled);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
@ -1465,13 +1483,26 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
_cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
_cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
_cairo_scaled_font_init (&scaled_font->base,
font_face,
font_matrix, ctm, options,
&cairo_ft_scaled_font_backend);
status = _cairo_scaled_font_init (&scaled_font->base,
font_face,
font_matrix, ctm, options,
&cairo_ft_scaled_font_backend);
if (status) {
free (scaled_font);
_cairo_unscaled_font_destroy (&unscaled->base);
_cairo_ft_unscaled_font_unlock_face (unscaled);
return NULL;
}
status = _cairo_ft_unscaled_font_set_scale (unscaled,
&scaled_font->base.scale);
if (status) {
free (scaled_font);
_cairo_unscaled_font_destroy (&unscaled->base);
_cairo_ft_unscaled_font_unlock_face (unscaled);
return NULL;
}
_cairo_ft_unscaled_font_set_scale (unscaled,
&scaled_font->base.scale);
metrics = &face->size->metrics;
@ -1549,8 +1580,10 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
unsigned char *family = (unsigned char*) toy_face->family;
pattern = FcPatternCreate ();
if (!pattern)
if (!pattern) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
switch (toy_face->weight)
{
@ -1620,6 +1653,7 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
*font = new_font;
return CAIRO_STATUS_SUCCESS;
} else {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
}
@ -1644,8 +1678,10 @@ _move_to (FT_Vector *to, void *closure)
x = _cairo_fixed_from_26_6 (to->x);
y = _cairo_fixed_from_26_6 (to->y);
_cairo_path_fixed_close_path (path);
_cairo_path_fixed_move_to (path, x, y);
if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
return 1;
if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
return 1;
return 0;
}
@ -1659,7 +1695,8 @@ _line_to (FT_Vector *to, void *closure)
x = _cairo_fixed_from_26_6 (to->x);
y = _cairo_fixed_from_26_6 (to->y);
_cairo_path_fixed_line_to (path, x, y);
if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
return 1;
return 0;
}
@ -1675,7 +1712,9 @@ _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
cairo_fixed_t x3, y3;
cairo_point_t conic;
_cairo_path_fixed_get_current_point (path, &x0, &y0);
if (_cairo_path_fixed_get_current_point (path, &x0, &y0) !=
CAIRO_STATUS_SUCCESS)
return 1;
conic.x = _cairo_fixed_from_26_6 (control->x);
conic.y = _cairo_fixed_from_26_6 (control->y);
@ -1689,10 +1728,11 @@ _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
x2 = x3 + 2.0/3.0 * (conic.x - x3);
y2 = y3 + 2.0/3.0 * (conic.y - y3);
_cairo_path_fixed_curve_to (path,
x1, y1,
x2, y2,
x3, y3);
if (_cairo_path_fixed_curve_to (path,
x1, y1,
x2, y2,
x3, y3) != CAIRO_STATUS_SUCCESS)
return 1;
return 0;
}
@ -1715,10 +1755,11 @@ _cubic_to (FT_Vector *control1, FT_Vector *control2,
x2 = _cairo_fixed_from_26_6 (to->x);
y2 = _cairo_fixed_from_26_6 (to->y);
_cairo_path_fixed_curve_to (path,
x0, y0,
x1, y1,
x2, y2);
if (_cairo_path_fixed_curve_to (path,
x0, y0,
x1, y1,
x2, y2) != CAIRO_STATUS_SUCCESS)
return 1;
return 0;
}
@ -1743,6 +1784,7 @@ _decompose_glyph_outline (FT_Face face,
FT_GlyphSlot glyph;
cairo_path_fixed_t *path;
cairo_status_t status;
path = _cairo_path_fixed_create ();
if (!path)
@ -1752,9 +1794,17 @@ _decompose_glyph_outline (FT_Face face,
/* Font glyphs have an inverted Y axis compared to cairo. */
FT_Outline_Transform (&glyph->outline, &invert_y);
FT_Outline_Decompose (&glyph->outline, &outline_funcs, path);
if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
_cairo_path_fixed_destroy (path);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_path_fixed_close_path (path);
status = _cairo_path_fixed_close_path (path);
if (status) {
_cairo_path_fixed_destroy (path);
return status;
}
*pathp = path;
@ -1798,14 +1848,16 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
FT_Glyph_Metrics *metrics;
double x_factor, y_factor;
cairo_bool_t vertical_layout = FALSE;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_status_t status;
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
_cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
&scaled_font->base.scale);
status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
&scaled_font->base.scale);
if (status)
goto FAIL;
/* Ignore global advance unconditionally */
load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
@ -1951,9 +2003,12 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
} else {
status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
&surface);
if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape)
if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape) {
status = _transform_glyph_bitmap (&unscaled->current_shape,
&surface);
if (status)
cairo_surface_destroy (&surface->base);
}
}
if (status)
goto FAIL;
@ -1977,6 +2032,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
if (error) {
_cairo_ft_unscaled_font_unlock_face (unscaled);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
@ -2186,10 +2242,12 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
&font_face->base,
font_matrix, ctm,
options, ft_options);
if (*scaled_font)
if (*scaled_font) {
return CAIRO_STATUS_SUCCESS;
else
} else {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
}
static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
@ -2202,23 +2260,32 @@ static cairo_font_face_t *
_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
cairo_ft_options_t *ft_options)
{
cairo_ft_font_face_t *font_face;
cairo_ft_font_face_t *font_face, **prev_font_face;
/* Looked for an existing matching font face */
for (font_face = unscaled->faces;
for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
font_face;
font_face = font_face->next)
prev_font_face = &font_face->next, font_face = font_face->next)
{
if (font_face->ft_options.load_flags == ft_options->load_flags &&
font_face->ft_options.extra_flags == ft_options->extra_flags &&
cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
return cairo_font_face_reference (&font_face->base);
{
if (! font_face->base.status)
return cairo_font_face_reference (&font_face->base);
/* The font_face has been left in an error state, abandon it. */
*prev_font_face = font_face->next;
break;
}
}
/* No match found, create a new one */
font_face = malloc (sizeof (cairo_ft_font_face_t));
if (!font_face)
if (!font_face) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
font_face->unscaled = unscaled;
_cairo_unscaled_font_reference (&unscaled->base);
@ -2376,10 +2443,8 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
if (font_face)
return font_face;
else {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
else
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
}
/**
@ -2429,12 +2494,10 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face,
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
_cairo_unscaled_font_destroy (&unscaled->base);
if (font_face) {
if (font_face)
return font_face;
} else {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
else
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
}
/**
@ -2472,6 +2535,7 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
{
cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
FT_Face face;
cairo_status_t status;
if (scaled_font->base.status)
return NULL;
@ -2482,8 +2546,13 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
return NULL;
}
_cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
&scaled_font->base.scale);
status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
&scaled_font->base.scale);
if (status) {
_cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
_cairo_scaled_font_set_error (&scaled_font->base, status);
return NULL;
}
/* NOTE: We deliberately release the unscaled font's mutex here,
* so that we are not holding a lock across two separate calls to

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

@ -33,7 +33,8 @@ typedef struct _cairo_glitz_surface {
glitz_surface_t *surface;
glitz_format_t *format;
pixman_region16_t *clip;
cairo_bool_t has_clip;
cairo_region_t clip;
} cairo_glitz_surface_t;
static const cairo_surface_backend_t *
@ -44,10 +45,9 @@ _cairo_glitz_surface_finish (void *abstract_surface)
{
cairo_glitz_surface_t *surface = abstract_surface;
if (surface->clip)
{
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
pixman_region_destroy (surface->clip);
if (surface->has_clip) {
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
_cairo_region_fini (&surface->clip);
}
glitz_surface_destroy (surface->surface);
@ -110,19 +110,90 @@ _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_int16_t *interest,
cairo_rectangle_int_t *interest,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *rect_out)
cairo_rectangle_int_t *rect_out)
{
cairo_image_surface_t *image;
int x1, y1, x2, y2;
int width, height;
unsigned char *pixels;
cairo_format_masks_t format;
cairo_format_masks_t masks;
glitz_buffer_t *buffer;
glitz_pixel_format_t pf;
cairo_format_t format;
x1 = 0;
y1 = 0;
@ -160,44 +231,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) {
format.bpp = 32;
masks.bpp = 32;
if (surface->format->color.alpha_size > 0)
format.alpha_mask = 0xff000000;
masks.alpha_mask = 0xff000000;
else
format.alpha_mask = 0x0;
masks.alpha_mask = 0x0;
format.red_mask = 0xff0000;
format.green_mask = 0xff00;
format.blue_mask = 0xff;
masks.red_mask = 0xff0000;
masks.green_mask = 0xff00;
masks.blue_mask = 0xff;
} else {
format.bpp = 8;
format.blue_mask = format.green_mask = format.red_mask = 0x0;
format.alpha_mask = 0xff;
masks.bpp = 8;
masks.blue_mask = masks.green_mask = masks.red_mask = 0x0;
masks.alpha_mask = 0xff;
}
} else {
format.bpp = 32;
format.alpha_mask = 0xff000000;
format.red_mask = 0xff0000;
format.green_mask = 0xff00;
format.blue_mask = 0xff;
masks.bpp = 32;
masks.alpha_mask = 0xff000000;
masks.red_mask = 0xff0000;
masks.green_mask = 0xff00;
masks.blue_mask = 0xff;
}
pf.fourcc = GLITZ_FOURCC_RGB;
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.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.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 * format.bpp) / 8) + 3) & -4;
pf.bytes_per_line = (((width * masks.bpp) / 8) + 3) & -4;
pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;
pixels = malloc (height * pf.bytes_per_line);
pixels = _cairo_malloc_ab (height, pf.bytes_per_line);
if (!pixels)
return CAIRO_STATUS_NO_MEMORY;
@ -208,7 +279,7 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
}
/* clear out the glitz clip; the clip affects glitz_get_pixels */
if (surface->clip)
if (surface->has_clip)
glitz_surface_set_clip_region (surface->surface,
0, 0, NULL, 0);
@ -221,24 +292,49 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
glitz_buffer_destroy (buffer);
/* restore the clip, if any */
if (surface->clip) {
if (surface->has_clip) {
glitz_box_t *box;
int n;
int n;
box = _cairo_glitz_get_boxes_from_region (&surface->clip, &n);
if (box == NULL && n != 0) {
free (pixels);
return CAIRO_STATUS_NO_MEMORY;
}
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);
}
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;
/*
* 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;
}
_cairo_image_surface_assume_ownership_of_data (image);
@ -246,6 +342,47 @@ _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
@ -261,15 +398,10 @@ _cairo_glitz_surface_set_image (void *abstract_surface,
cairo_glitz_surface_t *surface = abstract_surface;
glitz_buffer_t *buffer;
glitz_pixel_format_t pf;
pixman_format_t *format;
unsigned int bpp, am, rm, gm, bm;
uint32_t bpp, am, rm, gm, bm;
char *data;
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);
cairo_format_get_masks (image->format, &bpp, &am, &rm, &gm, &bm);
pf.fourcc = GLITZ_FOURCC_RGB;
pf.masks.bpp = bpp;
@ -331,9 +463,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_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect_out,
cairo_rectangle_int_t *image_rect_out,
void **image_extra)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -353,9 +485,9 @@ _cairo_glitz_surface_acquire_dest_image (void *abstract_surfa
static void
_cairo_glitz_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -392,8 +524,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_int16_t image_extent;
cairo_rectangle_int16_t extent;
cairo_rectangle_int_t image_extent;
cairo_rectangle_int_t extent;
content = _cairo_content_from_format (image_src->format);
@ -590,7 +722,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
(cairo_gradient_pattern_t *) pattern;
char *data;
glitz_fixed16_16_t *params;
int n_params;
unsigned int n_params;
unsigned int *pixels;
unsigned int i, n_base_params;
glitz_buffer_t *buffer;
@ -627,8 +759,22 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
n_params = gradient->n_stops * 3 + n_base_params;
data = malloc (sizeof (glitz_fixed16_16_t) * n_params +
sizeof (unsigned int) * gradient->n_stops);
/* 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);
}
if (!data)
return CAIRO_STATUS_NO_MEMORY;
@ -668,7 +814,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
}
glitz_set_pixels (src->surface, 0, 0, gradient->n_stops, 1,
&format, buffer);
(glitz_pixel_format_t *)&format, buffer);
glitz_buffer_destroy (buffer);
@ -676,22 +822,22 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
{
cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern;
params[0] = grad->gradient.p1.x;
params[1] = grad->gradient.p1.y;
params[2] = grad->gradient.p2.x;
params[3] = grad->gradient.p2.y;
params[0] = grad->p1.x;
params[1] = grad->p1.y;
params[2] = grad->p2.x;
params[3] = grad->p2.y;
attr->filter = GLITZ_FILTER_LINEAR_GRADIENT;
}
else
{
cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern;
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;
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;
attr->filter = GLITZ_FILTER_RADIAL_GRADIENT;
}
@ -822,11 +968,16 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
combined = src_solid->color;
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
_cairo_pattern_init_solid (&tmp.solid, &combined);
_cairo_pattern_init_solid (&tmp.solid, &combined,
CAIRO_COLOR_IS_OPAQUE (&combined) ?
CAIRO_CONTENT_COLOR :
CAIRO_CONTENT_COLOR_ALPHA);
mask = NULL;
} else {
_cairo_pattern_init_copy (&tmp.base, src);
status = _cairo_pattern_init_copy (&tmp.base, src);
if (status)
return status;
}
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
@ -841,7 +992,9 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
if (mask)
{
_cairo_pattern_init_copy (&tmp.base, mask);
status = _cairo_pattern_init_copy (&tmp.base, mask);
if (status)
return status;
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
mask_x, mask_y,
@ -957,7 +1110,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_int16_t *rects,
cairo_rectangle_int_t *rects,
int n_rects)
{
cairo_glitz_surface_t *dst = abstract_dst;
@ -1002,7 +1155,8 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
_cairo_surface_create_similar_solid (&dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
1, 1,
(cairo_color_t *) color);
(cairo_color_t *) color,
NULL);
if (src->base.status)
return CAIRO_STATUS_NO_MEMORY;
@ -1071,7 +1225,9 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
{
_cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
status = _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
if (status)
return status;
status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base,
dst,
@ -1216,7 +1372,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
}
pixman_add_trapezoids (image->pixman_image, -dst_x, -dst_y,
(pixman_trapezoid_t *) traps, n_traps);
n_traps, (pixman_trapezoid_t *) traps);
mask = (cairo_glitz_surface_t *)
_cairo_surface_create_similar_scratch (&dst->base,
@ -1274,35 +1430,47 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
static cairo_int_status_t
_cairo_glitz_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
cairo_region_t *region);
{
cairo_glitz_surface_t *surface = abstract_surface;
if (region)
{
glitz_box_t *box;
int n;
if (!surface->clip)
{
surface->clip = pixman_region_create ();
if (!surface->clip)
return CAIRO_STATUS_NO_MEMORY;
}
pixman_region_copy (surface->clip, region);
if (!surface->has_clip) {
_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;
}
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->clip)
pixman_region_destroy (surface->clip);
surface->clip = NULL;
if (surface->has_clip) {
_cairo_region_fini (&surface->clip);
surface->has_clip = FALSE;
}
}
return CAIRO_STATUS_SUCCESS;
@ -1310,7 +1478,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_glitz_surface_t *surface = abstract_surface;
@ -1812,7 +1980,6 @@ _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;
@ -1849,10 +2016,6 @@ _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,
@ -1872,7 +2035,7 @@ _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface,
return CAIRO_STATUS_NO_MEMORY;
}
pixman_format_get_masks (format, &bpp, &am, &rm, &gm, &bm);
cairo_format_get_masks (glyph_surface->format, &bpp, &am, &rm, &gm, &bm);
pf.fourcc = GLITZ_FOURCC_RGB;
pf.masks.bpp = bpp;
@ -1976,9 +2139,19 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
if (num_glyphs > N_STACK_BUF)
{
char *data;
size_t size1, size2;
data = malloc (num_glyphs * sizeof (void *) +
num_glyphs * sizeof (glitz_float_t) * 16);
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);
if (!data)
goto FAIL1;
@ -2172,6 +2345,33 @@ _cairo_glitz_surface_flush (void *abstract_surface)
return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t
_cairo_glitz_surface_is_similar (void *surface_a,
void *surface_b,
cairo_content_t content)
{
cairo_glitz_surface_t *a = (cairo_glitz_surface_t *) surface_a;
cairo_glitz_surface_t *b = (cairo_glitz_surface_t *) surface_b;
glitz_drawable_t *drawable_a = glitz_surface_get_drawable (a->surface);
glitz_drawable_t *drawable_b = glitz_surface_get_drawable (b->surface);
return drawable_a == drawable_b;
}
static cairo_status_t
_cairo_glitz_surface_reset (void *abstract_surface)
{
cairo_glitz_surface_t *surface = abstract_surface;
cairo_status_t status;
status = _cairo_glitz_surface_set_clip_region (surface, NULL);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
CAIRO_SURFACE_TYPE_GLITZ,
_cairo_glitz_surface_create_similar,
@ -2194,7 +2394,18 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
_cairo_glitz_surface_flush,
NULL, /* mark_dirty_rectangle */
_cairo_glitz_surface_scaled_font_fini,
_cairo_glitz_surface_scaled_glyph_fini
_cairo_glitz_surface_scaled_glyph_fini,
NULL, /* paint */
NULL, /* mask */
NULL, /* stroke */
NULL, /* fill */
NULL, /* show_glyphs */
NULL, /* snapshot */
_cairo_glitz_surface_is_similar,
_cairo_glitz_surface_reset
};
static const cairo_surface_backend_t *
@ -2240,9 +2451,9 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
glitz_surface_reference (surface);
crsurface->surface = surface;
crsurface->format = format;
crsurface->clip = NULL;
crsurface->surface = surface;
crsurface->format = format;
crsurface->has_clip = FALSE;
return (cairo_surface_t *) crsurface;
}

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

@ -35,8 +35,6 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include <stdlib.h>
#include "cairoint.h"
#include "cairo-clip-private.h"
@ -64,6 +62,8 @@ cairo_status_t
_cairo_gstate_init (cairo_gstate_t *gstate,
cairo_surface_t *target)
{
gstate->next = NULL;
gstate->op = CAIRO_GSTATE_OPERATOR_DEFAULT;
gstate->tolerance = CAIRO_GSTATE_TOLERANCE_DEFAULT;
@ -91,13 +91,12 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
_cairo_gstate_identity_matrix (gstate);
gstate->source_ctm_inverse = gstate->ctm_inverse;
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK,
CAIRO_CONTENT_COLOR);
if (gstate->source->status)
return CAIRO_STATUS_NO_MEMORY;
gstate->next = NULL;
return CAIRO_STATUS_SUCCESS;
return target ? target->status : CAIRO_STATUS_NULL_POINTER;
}
/**
@ -131,7 +130,9 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
_cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
_cairo_clip_init_copy (&gstate->clip, &other->clip);
status = _cairo_clip_init_copy (&gstate->clip, &other->clip);
if (status)
return status;
gstate->target = cairo_surface_reference (other->target);
/* parent_target is always set to NULL; it's only ever set by redirect_target */
@ -160,7 +161,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
_cairo_clip_fini (&gstate->clip);
_cairo_clip_reset (&gstate->clip);
cairo_surface_destroy (gstate->target);
gstate->target = NULL;
@ -175,7 +176,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
gstate->source = NULL;
}
void
static void
_cairo_gstate_destroy (cairo_gstate_t *gstate)
{
if (gstate == NULL)
@ -197,7 +198,7 @@ _cairo_gstate_destroy (cairo_gstate_t *gstate)
* Return value: a new cairo_gstate_t or NULL if there is insufficient
* memory.
**/
cairo_gstate_t*
static cairo_gstate_t*
_cairo_gstate_clone (cairo_gstate_t *other)
{
cairo_status_t status;
@ -218,6 +219,55 @@ _cairo_gstate_clone (cairo_gstate_t *other)
return gstate;
}
/**
* _cairo_gstate_save:
* @gstate: input/output gstate pointer
*
* Makes a copy of the current state of @gstate and saves it
* to @gstate->next, then put the address of the newly allcated
* copy into @gstate. _cairo_gstate_restore() reverses this.
**/
cairo_status_t
_cairo_gstate_save (cairo_gstate_t **gstate)
{
cairo_gstate_t *top;
top = _cairo_gstate_clone (*gstate);
if (top == NULL) {
return CAIRO_STATUS_NO_MEMORY;
}
top->next = *gstate;
*gstate = top;
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_gstate_restore:
* @gstate: input/output gstate pointer
*
* Reverses the effects of one _cairo_gstate_save() call.
**/
cairo_status_t
_cairo_gstate_restore (cairo_gstate_t **gstate)
{
cairo_gstate_t *top;
top = *gstate;
if (top->next == NULL) {
return CAIRO_STATUS_INVALID_RESTORE;
}
*gstate = top->next;
_cairo_gstate_destroy (top);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate,
cairo_clip_path_t *cpath)
@ -252,9 +302,11 @@ _cairo_gstate_recursive_apply_clip_path (cairo_gstate_t *gstate,
* original #cairo_t target, the clip will be INVALID after this call,
* and the caller should either recreate or reset the clip.
**/
void
cairo_status_t
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
{
cairo_status_t status;
/* If this gstate is already redirected, this is an error; we need a
* new gstate to be able to redirect */
assert (gstate->parent_target == NULL);
@ -269,14 +321,18 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
* since its ref is now owned by gstate->parent_target */
gstate->target = cairo_surface_reference (child);
_cairo_clip_fini (&gstate->clip);
_cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
_cairo_clip_reset (&gstate->clip);
status = _cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
if (status)
return status;
/* The clip is in surface backend coordinates for the previous target;
* translate it into the child's backend coordinates. */
_cairo_clip_translate (&gstate->clip,
_cairo_fixed_from_double (child->device_transform.x0 - gstate->parent_target->device_transform.x0),
_cairo_fixed_from_double (child->device_transform.y0 - gstate->parent_target->device_transform.y0));
return CAIRO_STATUS_SUCCESS;
}
/**
@ -356,7 +412,7 @@ _cairo_gstate_set_source (cairo_gstate_t *gstate,
if (source->status)
return source->status;
cairo_pattern_reference (source);
source = cairo_pattern_reference (source);
cairo_pattern_destroy (gstate->source);
gstate->source = source;
gstate->source_ctm_inverse = gstate->ctm_inverse;
@ -474,7 +530,7 @@ _cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dash
return CAIRO_STATUS_SUCCESS;
}
gstate->stroke_style.dash = malloc (gstate->stroke_style.num_dashes * sizeof (double));
gstate->stroke_style.dash = _cairo_malloc_ab (gstate->stroke_style.num_dashes, sizeof (double));
if (gstate->stroke_style.dash == NULL) {
gstate->stroke_style.num_dashes = 0;
return CAIRO_STATUS_NO_MEMORY;
@ -507,6 +563,24 @@ _cairo_gstate_set_dash (cairo_gstate_t *gstate, const double *dash, int num_dash
return CAIRO_STATUS_SUCCESS;
}
void
_cairo_gstate_get_dash (cairo_gstate_t *gstate,
double *dashes,
int *num_dashes,
double *offset)
{
if (dashes)
memcpy (dashes,
gstate->stroke_style.dash,
sizeof (double) * gstate->stroke_style.num_dashes);
if (num_dashes)
*num_dashes = gstate->stroke_style.num_dashes;
if (offset)
*offset = gstate->stroke_style.dash_offset;
}
cairo_status_t
_cairo_gstate_set_miter_limit (cairo_gstate_t *gstate, double limit)
{
@ -583,13 +657,16 @@ _cairo_gstate_transform (cairo_gstate_t *gstate,
const cairo_matrix_t *matrix)
{
cairo_matrix_t tmp;
cairo_status_t status;
_cairo_gstate_unset_scaled_font (gstate);
tmp = *matrix;
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
cairo_matrix_invert (&tmp);
status = cairo_matrix_invert (&tmp);
if (status)
return status;
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
return CAIRO_STATUS_SUCCESS;
@ -613,49 +690,39 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate,
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
void
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
{
_cairo_gstate_unset_scaled_font (gstate);
cairo_matrix_init_identity (&gstate->ctm);
cairo_matrix_init_identity (&gstate->ctm_inverse);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
void
_cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm, x, y);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
void
_cairo_gstate_user_to_device_distance (cairo_gstate_t *gstate,
double *dx, double *dy)
{
cairo_matrix_transform_distance (&gstate->ctm, dx, dy);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
void
_cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
void
_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate,
double *dx, double *dy)
{
cairo_matrix_transform_distance (&gstate->ctm_inverse, dx, dy);
return CAIRO_STATUS_SUCCESS;
}
void
@ -697,7 +764,7 @@ _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
}
*/
static void
static cairo_status_t
_cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_pattern_t *original,
@ -705,8 +772,12 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
{
cairo_surface_pattern_t *surface_pattern;
cairo_surface_t *surface;
cairo_status_t status;
status = _cairo_pattern_init_copy (pattern, original);
if (status)
return status;
_cairo_pattern_init_copy (pattern, original);
_cairo_pattern_transform (pattern, ctm_inverse);
if (cairo_pattern_get_type (original) == CAIRO_PATTERN_TYPE_SURFACE) {
@ -716,25 +787,26 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
_cairo_pattern_transform (pattern, &surface->device_transform);
}
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
_cairo_gstate_copy_transformed_source (cairo_gstate_t *gstate,
cairo_pattern_t *pattern)
{
_cairo_gstate_copy_transformed_pattern (gstate, pattern,
gstate->source,
&gstate->source_ctm_inverse);
return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
gstate->source,
&gstate->source_ctm_inverse);
}
static void
static cairo_status_t
_cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_pattern_t *mask)
{
_cairo_gstate_copy_transformed_pattern (gstate, pattern,
mask,
&gstate->ctm_inverse);
return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
mask,
&gstate->ctm_inverse);
}
cairo_status_t
@ -750,7 +822,9 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
if (status)
return status;
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
if (status)
return status;
status = _cairo_surface_paint (gstate->target,
gstate->op,
@ -857,16 +931,22 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
if (status)
return status;
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
_cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
if (status)
return status;
status = _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
if (status)
goto CLEANUP_SOURCE;
status = _cairo_surface_mask (gstate->target,
gstate->op,
&source_pattern.base,
&mask_pattern.base);
_cairo_pattern_fini (&source_pattern.base);
_cairo_pattern_fini (&mask_pattern.base);
CLEANUP_SOURCE:
_cairo_pattern_fini (&source_pattern.base);
return status;
}
@ -887,7 +967,10 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (status)
return status;
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
status = _cairo_gstate_copy_transformed_source (gstate,
&source_pattern.base);
if (status)
return status;
status = _cairo_surface_stroke (gstate->target,
gstate->op,
@ -954,7 +1037,9 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
if (status)
return status;
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
if (status)
return status;
status = _cairo_surface_fill (gstate->target,
gstate->op,
@ -1001,29 +1086,13 @@ BAIL:
cairo_status_t
_cairo_gstate_copy_page (cairo_gstate_t *gstate)
{
cairo_int_status_t status;
status = _cairo_surface_copy_page (gstate->target);
/* It's fine if some surfaces just don't support this. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
return CAIRO_STATUS_SUCCESS;
return status;
return _cairo_surface_copy_page (gstate->target);
}
cairo_status_t
_cairo_gstate_show_page (cairo_gstate_t *gstate)
{
cairo_int_status_t status;
status = _cairo_surface_show_page (gstate->target);
/* It's fine if some surfaces just don't support this. */
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
return CAIRO_STATUS_SUCCESS;
return status;
return _cairo_surface_show_page (gstate->target);
}
static void
@ -1125,7 +1194,9 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
cairo_status_t
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
{
return _cairo_clip_reset (&gstate->clip);
_cairo_clip_reset (&gstate->clip);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -1143,7 +1214,7 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
double *x2,
double *y2)
{
cairo_rectangle_int16_t extents;
cairo_rectangle_int_t extents;
cairo_status_t status;
status = _cairo_surface_get_extents (gstate->target, &extents);
@ -1190,12 +1261,15 @@ _cairo_gstate_select_font_face (cairo_gstate_t *gstate,
cairo_font_weight_t weight)
{
cairo_font_face_t *font_face;
cairo_status_t status;
font_face = _cairo_toy_font_face_create (family, slant, weight);
if (font_face->status)
return font_face->status;
_cairo_gstate_set_font_face (gstate, font_face);
status = _cairo_gstate_set_font_face (gstate, font_face);
if (status)
return status;
cairo_font_face_destroy (font_face);
return CAIRO_STATUS_SUCCESS;
@ -1230,15 +1304,13 @@ _cairo_gstate_get_font_matrix (cairo_gstate_t *gstate,
*matrix = gstate->font_matrix;
}
cairo_status_t
void
_cairo_gstate_set_font_options (cairo_gstate_t *gstate,
const cairo_font_options_t *options)
{
_cairo_gstate_unset_scaled_font (gstate);
gstate->font_options = *options;
return CAIRO_STATUS_SUCCESS;
}
void
@ -1357,17 +1429,19 @@ _cairo_gstate_get_scaled_font (cairo_gstate_t *gstate,
static cairo_status_t
_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
{
if (!gstate->font_face) {
cairo_font_face_t *font_face;
cairo_font_face_t *font_face;
font_face = _cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
CAIRO_FONT_SLANT_DEFAULT,
CAIRO_FONT_WEIGHT_DEFAULT);
if (font_face->status)
return font_face->status;
else
gstate->font_face = font_face;
}
if (gstate->font_face != NULL)
return gstate->font_face->status;
font_face = _cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
CAIRO_FONT_SLANT_DEFAULT,
CAIRO_FONT_WEIGHT_DEFAULT);
if (font_face->status)
return font_face->status;
gstate->font_face = font_face;
return CAIRO_STATUS_SUCCESS;
}
@ -1377,9 +1451,10 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_font_options_t options;
cairo_scaled_font_t *scaled_font;
if (gstate->scaled_font)
return CAIRO_STATUS_SUCCESS;
if (gstate->scaled_font != NULL)
return gstate->scaled_font->status;
status = _cairo_gstate_ensure_font_face (gstate);
if (status)
@ -1388,13 +1463,16 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate)
cairo_surface_get_font_options (gstate->target, &options);
cairo_font_options_merge (&options, &gstate->font_options);
gstate->scaled_font = cairo_scaled_font_create (gstate->font_face,
&gstate->font_matrix,
&gstate->ctm,
&options);
scaled_font = cairo_scaled_font_create (gstate->font_face,
&gstate->font_matrix,
&gstate->ctm,
&options);
if (!gstate->scaled_font)
return CAIRO_STATUS_NO_MEMORY;
status = cairo_scaled_font_status (scaled_font);
if (status)
return status;
gstate->scaled_font = scaled_font;
return CAIRO_STATUS_SUCCESS;
}
@ -1409,7 +1487,7 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
cairo_scaled_font_extents (gstate->scaled_font, extents);
return CAIRO_STATUS_SUCCESS;
return cairo_scaled_font_status (gstate->scaled_font);
}
cairo_status_t
@ -1426,13 +1504,8 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
if (status)
return status;
status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
utf8, glyphs, num_glyphs);
if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs))
return status;
return CAIRO_STATUS_SUCCESS;
return _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
utf8, glyphs, num_glyphs);
}
cairo_status_t
@ -1468,7 +1541,7 @@ _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
glyphs, num_glyphs,
extents);
return CAIRO_STATUS_SUCCESS;
return cairo_scaled_font_status (gstate->scaled_font);
}
#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t)))
@ -1497,7 +1570,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
if (num_glyphs <= STACK_GLYPHS_LEN) {
transformed_glyphs = stack_transformed_glyphs;
} else {
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
@ -1505,7 +1578,9 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs);
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
if (status)
goto CLEANUP_GLYPHS;
status = _cairo_surface_show_glyphs (gstate->target,
gstate->op,
@ -1516,6 +1591,7 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
_cairo_pattern_fini (&source_pattern.base);
CLEANUP_GLYPHS:
if (transformed_glyphs != stack_transformed_glyphs)
free (transformed_glyphs);
@ -1539,7 +1615,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
if (num_glyphs < STACK_GLYPHS_LEN)
transformed_glyphs = stack_transformed_glyphs;
else
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;

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

@ -39,51 +39,13 @@
#ifndef CAIRO_HASH_PRIVATE_H
#define CAIRO_HASH_PRIVATE_H
#include "cairo-types-private.h"
/* XXX: I'd like this file to be self-contained in terms of
* includeability, but that's not really possible with the current
* monolithic cairoint.h. So, for now, just include cairoint.h instead
* if you want to include this file. */
typedef struct _cairo_hash_table cairo_hash_table_t;
/**
* cairo_hash_entry_t:
*
* A #cairo_hash_entry_t contains both a key and a value for
* cairo_hash_table_t. User-derived types for cairo_hash_entry_t must
* be type-compatible with this structure (eg. they must have an
* unsigned long as the first parameter. The easiest way to get this
* is to use:
*
* typedef _my_entry {
* cairo_hash_entry_t base;
* ... Remainder of key and value fields here ..
* } my_entry_t;
*
* which then allows a pointer to my_entry_t to be passed to any of
* the cairo_hash_table functions as follows without requiring a cast:
*
* _cairo_hash_table_insert (hash_table, &my_entry->base);
*
* IMPORTANT: The caller is reponsible for initializing
* my_entry->base.hash with a hash code derived from the key. The
* essential property of the hash code is that keys_equal must never
* return TRUE for two keys that have different hashes. The best hash
* code will reduce the frequency of two keys with the same code for
* which keys_equal returns FALSE.
*
* Which parts of the entry make up the "key" and which part make up
* the value are entirely up to the caller, (as determined by the
* computation going into base.hash as well as the keys_equal
* function). A few of the cairo_hash_table functions accept an entry
* which will be used exclusively as a "key", (indicated by a
* parameter name of key). In these cases, the value-related fields of
* the entry need not be initialized if so desired.
**/
typedef struct _cairo_hash_entry {
unsigned long hash;
} cairo_hash_entry_t;
typedef cairo_bool_t
(*cairo_hash_keys_equal_func_t) (const void *key_a, const void *key_b);

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

@ -115,7 +115,7 @@ static const cairo_hash_table_arrangement_t hash_table_arrangements [] = {
{ 268435456, 590559793, 590559791 }
};
#define NUM_HASH_TABLE_ARRANGEMENTS ((int)(sizeof(hash_table_arrangements)/sizeof(hash_table_arrangements[0])))
#define NUM_HASH_TABLE_ARRANGEMENTS ARRAY_LENGTH (hash_table_arrangements)
struct _cairo_hash_table {
cairo_hash_keys_equal_func_t keys_equal;
@ -481,8 +481,12 @@ _cairo_hash_table_insert (cairo_hash_table_t *hash_table,
hash_table->live_entries++;
status = _cairo_hash_table_resize (hash_table);
if (status)
if (status) {
/* abort the insert... */
*entry = DEAD_ENTRY;
hash_table->live_entries--;
return status;
}
return CAIRO_STATUS_SUCCESS;
}
@ -561,6 +565,9 @@ _cairo_hash_table_foreach (cairo_hash_table_t *hash_table,
* the table may need resizing. Just do this every time
* as the check is inexpensive.
*/
if (--hash_table->iterating == 0)
if (--hash_table->iterating == 0) {
/* Should we fail to shrink the hash table, it is left unaltered,
* and we don't need to propagate the error status. */
_cairo_hash_table_resize (hash_table);
}
}

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

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

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

@ -1,3 +1,4 @@
/* -*- 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
@ -36,7 +37,7 @@
#include "cairoint.h"
const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
{
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
@ -82,23 +83,6 @@ 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)
@ -129,75 +113,47 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
return &surface->base;
}
/* 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)
static cairo_bool_t
_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
{
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) {
/* 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) {
case 32:
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;
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 16:
if (am == 0x0 &&
rm == 0xf800 &&
gm == 0x07e0 &&
bm == 0x001f)
return CAIRO_FORMAT_RGB16_565;
break;
case 8:
if (am == 0xff &&
rm == 0x0 &&
gm == 0x0 &&
bm == 0x0)
return CAIRO_FORMAT_A8;
if (masks->alpha_mask == 0xff)
{
*format = CAIRO_FORMAT_A8;
return TRUE;
}
break;
case 1:
if (am == 0x1 &&
rm == 0x0 &&
gm == 0x0 &&
bm == 0x0)
return CAIRO_FORMAT_A1;
if (masks->alpha_mask == 0x1)
{
*format = CAIRO_FORMAT_A1;
return TRUE;
}
break;
}
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;
return FALSE;
}
/* XXX: This function really should be eliminated. We don't really
@ -206,63 +162,46 @@ _cairo_format_from_pixman_format (pixman_format_t *pixman_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 *format,
cairo_format_masks_t *masks,
int width,
int height,
int stride)
{
cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
cairo_format_t cairo_format;
cairo_format_t 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);
if (!_CAIRO_MASK_FORMAT (masks, &format)) {
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
return (cairo_surface_t*) &_cairo_surface_nil;
}
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;
return cairo_image_surface_create_for_data (data,
format,
width,
height,
stride);
}
static pixman_format_t *
_create_pixman_format (cairo_format_t format)
static pixman_format_code_t
_cairo_format_to_pixman_format_code (cairo_format_t format)
{
int ret = 0;
switch (format) {
case CAIRO_FORMAT_A1:
return pixman_format_create (PIXMAN_FORMAT_NAME_A1);
ret = PIXMAN_a1;
break;
case CAIRO_FORMAT_A8:
return pixman_format_create (PIXMAN_FORMAT_NAME_A8);
ret = PIXMAN_a8;
break;
case CAIRO_FORMAT_RGB24:
return pixman_format_create (PIXMAN_FORMAT_NAME_RGB24);
ret = PIXMAN_x8r8g8b8;
break;
case CAIRO_FORMAT_ARGB32:
default:
return pixman_format_create (PIXMAN_FORMAT_NAME_ARGB32);
ret = PIXMAN_a8r8g8b8;
break;
}
assert (ret);
return ret;
}
/**
@ -290,31 +229,28 @@ cairo_image_surface_create (cairo_format_t format,
int width,
int height)
{
cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
cairo_surface_t *surface;
pixman_format_code_t pixman_format;
pixman_image_t *pixman_image;
if (! CAIRO_FORMAT_VALID (format)) {
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
}
pixman_format = _create_pixman_format (format);
if (pixman_format == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
pixman_image = pixman_image_create (pixman_format, width, height);
pixman_format_destroy (pixman_format);
pixman_format = _cairo_format_to_pixman_format_code (format);
pixman_image = pixman_image_create_bits (pixman_format, width, height,
NULL, -1);
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;
}
@ -369,25 +305,17 @@ cairo_image_surface_create_for_data (unsigned char *data,
int height,
int stride)
{
cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
cairo_surface_t *surface;
pixman_format_code_t pixman_format;
pixman_image_t *pixman_image;
if (! CAIRO_FORMAT_VALID (format))
return (cairo_surface_t*) &_cairo_surface_nil;
pixman_format = _create_pixman_format (format);
if (pixman_format == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
pixman_format = _cairo_format_to_pixman_format_code (format);
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
width, height,
_cairo_format_bpp (format),
stride);
pixman_format_destroy (pixman_format);
pixman_image = pixman_image_create_bits (pixman_format, width, height,
(uint32_t *) data, stride);
if (pixman_image == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -395,6 +323,9 @@ cairo_image_surface_create_for_data (unsigned char *data,
}
surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
if (cairo_surface_status (surface)) {
pixman_image_unref (pixman_image);
}
return surface;
}
@ -567,7 +498,7 @@ _cairo_content_from_format (cairo_format_t format)
case CAIRO_INTERNAL_FORMAT_ABGR32:
return CAIRO_CONTENT_COLOR_ALPHA;
case CAIRO_FORMAT_RGB24:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_INTERNAL_FORMAT_RGB16_565:
case CAIRO_INTERNAL_FORMAT_BGR24:
return CAIRO_CONTENT_COLOR;
case CAIRO_FORMAT_A8:
@ -597,7 +528,7 @@ _cairo_image_surface_finish (void *abstract_surface)
cairo_image_surface_t *surface = abstract_surface;
if (surface->pixman_image) {
pixman_image_destroy (surface->pixman_image);
pixman_image_unref (surface->pixman_image);
surface->pixman_image = NULL;
}
@ -635,9 +566,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_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect_out,
cairo_rectangle_int_t *image_rect_out,
void **image_extra)
{
cairo_image_surface_t *surface = abstract_surface;
@ -655,9 +586,9 @@ _cairo_image_surface_acquire_dest_image (void *abstract_surfa
static void
_cairo_image_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
}
@ -690,7 +621,8 @@ _cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
_cairo_matrix_to_pixman_matrix (matrix, &pixman_transform);
pixman_image_set_transform (surface->pixman_image, &pixman_transform);
if (!pixman_image_set_transform (surface->pixman_image, &pixman_transform))
return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
}
@ -726,7 +658,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);
pixman_image_set_filter (surface->pixman_image, pixman_filter, NULL, 0);
return CAIRO_STATUS_SUCCESS;
}
@ -766,43 +698,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_operator_t
static pixman_op_t
_pixman_operator (cairo_operator_t op)
{
switch (op) {
case CAIRO_OPERATOR_CLEAR:
return PIXMAN_OPERATOR_CLEAR;
return PIXMAN_OP_CLEAR;
case CAIRO_OPERATOR_SOURCE:
return PIXMAN_OPERATOR_SRC;
return PIXMAN_OP_SRC;
case CAIRO_OPERATOR_OVER:
return PIXMAN_OPERATOR_OVER;
return PIXMAN_OP_OVER;
case CAIRO_OPERATOR_IN:
return PIXMAN_OPERATOR_IN;
return PIXMAN_OP_IN;
case CAIRO_OPERATOR_OUT:
return PIXMAN_OPERATOR_OUT;
return PIXMAN_OP_OUT;
case CAIRO_OPERATOR_ATOP:
return PIXMAN_OPERATOR_ATOP;
return PIXMAN_OP_ATOP;
case CAIRO_OPERATOR_DEST:
return PIXMAN_OPERATOR_DST;
return PIXMAN_OP_DST;
case CAIRO_OPERATOR_DEST_OVER:
return PIXMAN_OPERATOR_OVER_REVERSE;
return PIXMAN_OP_OVER_REVERSE;
case CAIRO_OPERATOR_DEST_IN:
return PIXMAN_OPERATOR_IN_REVERSE;
return PIXMAN_OP_IN_REVERSE;
case CAIRO_OPERATOR_DEST_OUT:
return PIXMAN_OPERATOR_OUT_REVERSE;
return PIXMAN_OP_OUT_REVERSE;
case CAIRO_OPERATOR_DEST_ATOP:
return PIXMAN_OPERATOR_ATOP_REVERSE;
return PIXMAN_OP_ATOP_REVERSE;
case CAIRO_OPERATOR_XOR:
return PIXMAN_OPERATOR_XOR;
return PIXMAN_OP_XOR;
case CAIRO_OPERATOR_ADD:
return PIXMAN_OPERATOR_ADD;
return PIXMAN_OP_ADD;
case CAIRO_OPERATOR_SATURATE:
return PIXMAN_OPERATOR_SATURATE;
return PIXMAN_OP_SATURATE;
default:
return PIXMAN_OPERATOR_OVER;
return PIXMAN_OP_OVER;
}
}
@ -847,28 +779,28 @@ _cairo_image_surface_composite (cairo_operator_t op,
if (status)
goto CLEANUP_SURFACES;
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);
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);
}
else
{
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);
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);
}
if (!_cairo_operator_bounded_by_source (op))
@ -890,29 +822,60 @@ _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_int16_t *rects,
cairo_rectangle_int_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;
/* XXX: The pixman_rectangle_t cast is evil... it needs to go away somehow. */
pixman_fill_rectangles (_pixman_operator(op), surface->pixman_image,
&pixman_color, (pixman_rectangle_t *) rects, num_rects);
if (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;
}
return CAIRO_STATUS_SUCCESS;
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;
}
#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,
@ -932,10 +895,33 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
cairo_image_surface_t *src;
cairo_int_status_t status;
pixman_image_t *mask;
pixman_format_t *format;
pixman_bits_t *mask_data;
int mask_stride;
int mask_bpp;
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);
}
/* Special case adding trapezoids onto a mask surface; we want to avoid
* creating an intermediate temporary mask unecessarily.
@ -957,8 +943,9 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
antialias != CAIRO_ANTIALIAS_NONE)
{
pixman_add_trapezoids (dst->pixman_image, 0, 0,
(pixman_trapezoid_t *) traps, num_traps);
return CAIRO_STATUS_SUCCESS;
num_traps, pixman_traps);
status = CAIRO_STATUS_SUCCESS;
goto finish;
}
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
@ -966,7 +953,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
(cairo_surface_t **) &src,
&attributes);
if (status)
return status;
goto finish;
status = _cairo_image_surface_set_attributes (src, &attributes);
if (status)
@ -974,54 +961,50 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
switch (antialias) {
case CAIRO_ANTIALIAS_NONE:
format = pixman_format_create (PIXMAN_FORMAT_NAME_A1);
mask_stride = (width + 31)/8;
format = PIXMAN_a1;
ret = 1;
assert (ret);
mask_stride = ((width + 31) / 8) & ~0x03;
mask_bpp = 1;
break;
case CAIRO_ANTIALIAS_GRAY:
case CAIRO_ANTIALIAS_SUBPIXEL:
case CAIRO_ANTIALIAS_DEFAULT:
default:
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
format = PIXMAN_a8;
ret = 1;
assert (ret);
mask_stride = (width + 3) & ~3;
mask_bpp = 8;
break;
}
if (!format) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_SOURCE;
}
/* The image must be initially transparent */
mask_data = calloc (1, mask_stride * height);
if (!mask_data) {
if (mask_data == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
pixman_format_destroy (format);
goto CLEANUP_SOURCE;
}
mask = pixman_image_create_for_data (mask_data, format, width, height,
mask_bpp, mask_stride);
pixman_format_destroy (format);
if (!mask) {
mask = pixman_image_create_bits (format, width, height,
mask_data, mask_stride);
if (mask == NULL) {
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,
(pixman_trapezoid_t *) traps, num_traps);
num_traps, pixman_traps);
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);
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);
if (!_cairo_operator_bounded_by_mask (op))
status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
@ -1030,7 +1013,7 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
src_x, src_y,
0, 0,
dst_x, dst_y, width, height);
pixman_image_destroy (mask);
pixman_image_unref (mask);
CLEANUP_IMAGE_DATA:
free (mask_data);
@ -1038,16 +1021,23 @@ _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,
pixman_region16_t *region)
cairo_region_t *region)
{
cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
pixman_image_set_clip_region (surface->pixman_image, region);
if (!pixman_image_set_clip_region (surface->pixman_image, &region->rgn))
return CAIRO_STATUS_NO_MEMORY;
surface->has_clip = region != NULL;
@ -1056,7 +1046,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_image_surface_t *surface = abstract_surface;
@ -1068,6 +1058,28 @@ _cairo_image_surface_get_extents (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_image_surface_get_font_options (void *abstract_surface,
cairo_font_options_t *options)
{
_cairo_font_options_init_default (options);
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
}
static cairo_status_t
_cairo_image_surface_reset (void *abstract_surface)
{
cairo_image_surface_t *surface = abstract_surface;
cairo_status_t status;
status = _cairo_image_surface_set_clip_region (surface, NULL);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_surface_is_image:
* @surface: a #cairo_surface_t
@ -1099,7 +1111,22 @@ const cairo_surface_backend_t cairo_image_surface_backend = {
_cairo_image_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_image_surface_get_extents,
NULL /* old_show_glyphs */
NULL, /* old_show_glyphs */
_cairo_image_surface_get_font_options,
NULL, /* flush */
NULL, /* mark_dirty_rectangle */
NULL, //* font_fini */
NULL, //* glyph_fini */
NULL, /* paint */
NULL, /* mask */
NULL, /* stroke */
NULL, /* fill */
NULL, /* show_glyphs */
NULL, /* snapshot */
NULL, /* is_similar */
_cairo_image_surface_reset
};
/* A convenience function for when one needs to coerce an image

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

@ -35,7 +35,6 @@
*/
#define _GNU_SOURCE
#include <stdlib.h>
#include "cairoint.h"
@ -198,7 +197,7 @@ slim_hidden_def(cairo_matrix_init_scale);
* @sx: scale factor in the X direction
* @sy: scale factor in the Y direction
*
* Applies scaling by @tx, @ty to the transformation in @matrix. The
* Applies scaling by @sx, @sy to the transformation in @matrix. The
* effect of the new transformation is to first scale the coordinates
* by @sx and @sy, then apply the original transformation to the coordinates.
**/
@ -476,6 +475,10 @@ 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);
@ -496,7 +499,7 @@ _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,
}
/* Compute the amount that each basis vector is scaled by. */
cairo_status_t
void
_cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
double *sx, double *sy, int x_major)
{
@ -536,8 +539,6 @@ _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,
*sy = major;
}
}
return CAIRO_STATUS_SUCCESS;
}
cairo_bool_t
@ -735,13 +736,13 @@ _cairo_matrix_to_pixman_matrix (const cairo_matrix_t *matrix,
*pixman_transform = pixman_identity_transform;
}
else {
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[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[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[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[2][0] = 0;
pixman_transform->matrix[2][1] = 0;

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

@ -212,7 +212,11 @@ static cairo_status_t
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
_cairo_pattern_init_copy (pattern, other);
cairo_status_t status;
status = _cairo_pattern_init_copy (pattern, other);
if (status)
return status;
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern =
@ -435,7 +439,7 @@ _cairo_meta_surface_show_glyphs (void *abstract_surface,
if (status)
goto CLEANUP_COMMAND;
command->glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
command->glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (command->glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_SOURCE;
@ -552,7 +556,7 @@ _cairo_meta_surface_intersect_clip_path (void *dst,
*/
static cairo_int_status_t
_cairo_meta_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_meta_surface_t *surface = abstract_surface;
@ -648,6 +652,9 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_matrix_t *device_transform = &target->device_transform;
cairo_path_fixed_t path_copy, *dev_path;
if (surface->status)
return surface->status;
meta = (cairo_meta_surface_t *) surface;
status = CAIRO_STATUS_SUCCESS;
@ -668,7 +675,9 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
dev_path = _cairo_command_get_path (command);
if (dev_path && has_device_transform) {
_cairo_path_fixed_init_copy (&path_copy, dev_path);
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
if (status)
break;
_cairo_path_fixed_device_transform (&path_copy, device_transform);
dev_path = &path_copy;
}
@ -726,7 +735,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
int i, num_glyphs = command->show_glyphs.num_glyphs;
if (has_device_transform) {
dev_glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (dev_glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
break;
@ -754,7 +763,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
/* XXX Meta surface clipping is broken and requires some
* cairo-gstate.c rewriting. Work around it for now. */
if (dev_path == NULL)
status = _cairo_clip_reset (&clip);
_cairo_clip_reset (&clip);
else
status = _cairo_clip_clip (&clip, dev_path,
command->intersect_clip_path.fill_rule,
@ -773,7 +782,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
}
_cairo_clip_fini (&clip);
_cairo_clip_reset (&clip);
return status;
}

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

@ -35,8 +35,12 @@
* Peter Weilbacher <mozilla@Weilbacher.org>
*/
#include <stdlib.h>
#include <stdio.h>
#include "cairoint.h"
#include "cairo-os2-private.h"
#include <fontconfig/fontconfig.h>
#include <float.h>
#ifdef BUILD_CAIRO_DLL
# define INCL_WIN
@ -49,9 +53,6 @@
# include <emx/startup.h>
# endif
#endif
#include "cairoint.h"
#include "cairo-os2-private.h"
#include "fontconfig/fontconfig.h"
/*
* Here comes the extra API for the OS/2 platform. Currently it consists
@ -68,14 +69,6 @@
/* Initialization counter: */
static int cairo_os2_initialization_count = 0;
/* The mutex semaphores Cairo uses all around: */
HMTX _cairo_scaled_font_map_mutex = 0;
HMTX _global_image_glyph_cache_mutex = 0;
HMTX _cairo_font_face_mutex = 0;
#ifdef CAIRO_HAS_FT_FONT
HMTX _cairo_ft_unscaled_font_map_mutex = 0;
#endif
static void inline
DisableFPUException (void)
{
@ -103,20 +96,10 @@ cairo_os2_init (void)
DisableFPUException ();
/* Create the mutex semaphores we'll use! */
/* cairo-font.c: */
DosCreateMutexSem (NULL, &_cairo_scaled_font_map_mutex, 0, FALSE);
DosCreateMutexSem (NULL, &_global_image_glyph_cache_mutex, 0, FALSE);
DosCreateMutexSem (NULL, &_cairo_font_face_mutex, 0, FALSE);
#ifdef CAIRO_HAS_FT_FONT
/* cairo-ft-font.c: */
DosCreateMutexSem (NULL, &_cairo_ft_unscaled_font_map_mutex, 0, FALSE);
#endif
/* Initialize FontConfig */
FcInit ();
CAIRO_MUTEX_INITIALIZE ();
}
cairo_public void
@ -137,28 +120,7 @@ cairo_os2_fini (void)
_cairo_ft_font_reset_static_data ();
#endif
/* Destroy the mutex semaphores we've created! */
/* cairo-font.c: */
if (_cairo_scaled_font_map_mutex) {
DosCloseMutexSem (_cairo_scaled_font_map_mutex);
_cairo_scaled_font_map_mutex = 0;
}
if (_global_image_glyph_cache_mutex) {
DosCloseMutexSem (_global_image_glyph_cache_mutex);
_global_image_glyph_cache_mutex = 0;
}
if (_cairo_font_face_mutex) {
DosCloseMutexSem (_cairo_font_face_mutex);
_cairo_font_face_mutex = 0;
}
#ifdef CAIRO_HAS_FT_FONT
/* cairo-ft-font.c: */
if (_cairo_ft_unscaled_font_map_mutex) {
DosCloseMutexSem (_cairo_ft_unscaled_font_map_mutex);
_cairo_ft_unscaled_font_map_mutex = 0;
}
#endif
CAIRO_MUTEX_FINALIZE ();
/* Uninitialize FontConfig */
FcFini ();
@ -334,8 +296,9 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
ULONG ulPixels;
/* allocate temporary pixel buffer */
pchPixBuf = (unsigned char *) malloc (3 * surface->bitmap_info.cx *
surface->bitmap_info.cy);
pchPixBuf = (unsigned char *) _cairo_malloc_abc (surface->bitmap_info.cy,
surface->bitmap_info.cx,
3);
pchPixSource = surface->pixels; /* start at beginning of pixel buffer */
pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */
@ -554,9 +517,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_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void **image_extra)
{
cairo_os2_surface_t *local_os2_surface;
@ -589,9 +552,9 @@ _cairo_os2_surface_acquire_dest_image (void *abstract_surfac
static void
_cairo_os2_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
cairo_os2_surface_t *local_os2_surface;
@ -665,7 +628,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_os2_surface_t *local_os2_surface;
@ -751,7 +714,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 *) malloc (width * height * 4);
local_os2_surface->pixels = (unsigned char *) _cairo_malloc_abc (height, width, 4);
if (!(local_os2_surface->pixels)) {
/* Not enough memory for the pixels! */
DosCloseEventSem (local_os2_surface->hev_pixel_array_came_back);
@ -821,7 +784,7 @@ cairo_os2_surface_set_size (cairo_surface_t *surface,
}
/* Allocate memory for new stuffs */
pchNewPixels = (unsigned char *) malloc (new_width * new_height * 4);
pchNewPixels = (unsigned char *) _cairo_malloc_abc (new_height, new_width, 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
typedef struct _cairo_output_stream cairo_output_stream_t;
#include "cairo-types-private.h"
typedef cairo_status_t (*cairo_output_stream_write_func_t) (cairo_output_stream_t *output_stream,
const unsigned char *data,
@ -53,7 +53,7 @@ struct _cairo_output_stream {
cairo_bool_t closed;
};
extern const cairo_private cairo_output_stream_t cairo_output_stream_nil;
extern const cairo_private cairo_output_stream_t _cairo_output_stream_nil;
cairo_private void
_cairo_output_stream_init (cairo_output_stream_t *stream,
@ -107,7 +107,7 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
const char *data,
size_t length);
cairo_private int
cairo_private void
_cairo_dtostr (char *buffer, size_t size, double d);
cairo_private void

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

@ -34,11 +34,12 @@
* Kristian Høgsberg <krh@redhat.com>
*/
#include <stdio.h>
#include "cairoint.h"
#include "cairo-output-stream-private.h"
#include <locale.h>
#include <ctype.h>
#include "cairoint.h"
#include "cairo-output-stream-private.h"
#ifdef _MSC_VER
#define snprintf _snprintf
@ -63,7 +64,7 @@ _cairo_output_stream_fini (cairo_output_stream_t *stream)
return _cairo_output_stream_close (stream);
}
const cairo_output_stream_t cairo_output_stream_nil = {
const cairo_output_stream_t _cairo_output_stream_nil = {
NULL, /* write_func */
NULL, /* close_func */
0, /* position */
@ -71,7 +72,7 @@ const cairo_output_stream_t cairo_output_stream_nil = {
FALSE /* closed */
};
static const cairo_output_stream_t cairo_output_stream_nil_write_error = {
static const cairo_output_stream_t _cairo_output_stream_nil_write_error = {
NULL, /* write_func */
NULL, /* close_func */
0, /* position */
@ -119,7 +120,7 @@ _cairo_output_stream_create (cairo_write_func_t write_func,
stream = malloc (sizeof (cairo_output_stream_with_closure_t));
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
_cairo_output_stream_init (&stream->base, closure_write, closure_close);
stream->write_func = write_func;
@ -137,8 +138,8 @@ _cairo_output_stream_close (cairo_output_stream_t *stream)
if (stream->closed)
return stream->status;
if (stream == &cairo_output_stream_nil ||
stream == &cairo_output_stream_nil_write_error)
if (stream == &_cairo_output_stream_nil ||
stream == &_cairo_output_stream_nil_write_error)
{
return stream->status;
}
@ -214,52 +215,49 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
* has been relicensed under the LGPL/MPL dual license for inclusion
* into cairo (see COPYING). -- Kristian Høgsberg <krh@redhat.com>
*/
int
void
_cairo_dtostr (char *buffer, size_t size, double d)
{
struct lconv *locale_data;
const char *decimal_point;
int decimal_point_len;
char *p;
int decimal_len;
struct lconv *locale_data;
const char *decimal_point;
int decimal_point_len;
char *p;
int decimal_len;
/* Omit the minus sign from negative zero. */
if (d == 0.0)
d = 0.0;
/* Omit the minus sign from negative zero. */
if (d == 0.0)
d = 0.0;
snprintf (buffer, size, "%f", d);
snprintf (buffer, size, "%f", d);
locale_data = localeconv ();
decimal_point = locale_data->decimal_point;
decimal_point_len = strlen (decimal_point);
locale_data = localeconv ();
decimal_point = locale_data->decimal_point;
decimal_point_len = strlen (decimal_point);
assert (decimal_point_len != 0);
p = buffer;
assert (decimal_point_len != 0);
p = buffer;
if (*p == '+' || *p == '-')
p++;
if (*p == '+' || *p == '-')
p++;
while (isdigit (*p))
p++;
while (isdigit (*p))
p++;
if (strncmp (p, decimal_point, decimal_point_len) == 0) {
*p = '.';
decimal_len = strlen (p + decimal_point_len);
memmove (p + 1, p + decimal_point_len, decimal_len);
p[1 + decimal_len] = 0;
if (strncmp (p, decimal_point, decimal_point_len) == 0) {
*p = '.';
decimal_len = strlen (p + decimal_point_len);
memmove (p + 1, p + decimal_point_len, decimal_len);
p[1 + decimal_len] = 0;
/* Remove trailing zeros and decimal point if possible. */
for (p = p + decimal_len; *p == '0'; p--)
*p = 0;
/* Remove trailing zeros and decimal point if possible. */
for (p = p + decimal_len; *p == '0'; p--)
*p = 0;
if (*p == '.') {
*p = 0;
p--;
}
}
return p + 1 - buffer;
if (*p == '.') {
*p = 0;
p--;
}
}
}
enum {
@ -278,10 +276,13 @@ void
_cairo_output_stream_vprintf (cairo_output_stream_t *stream,
const char *fmt, va_list ap)
{
char buffer[512], single_fmt[32];
char *p, *end;
#define SINGLE_FMT_BUFFER_SIZE 32
char buffer[512], single_fmt[SINGLE_FMT_BUFFER_SIZE];
int single_fmt_length;
char *p;
const char *f, *start;
int length_modifier;
int length_modifier, width;
cairo_bool_t var_width;
if (stream->status)
return;
@ -305,10 +306,14 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
if (*f == '0')
f++;
if (isdigit (*f)) {
strtol (f, &end, 10);
f = end;
}
var_width = FALSE;
if (*f == '*') {
var_width = TRUE;
f++;
}
while (isdigit (*f))
f++;
length_modifier = 0;
if (*f == 'l') {
@ -316,9 +321,15 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
f++;
}
/* The only format strings exist in the cairo implementation
* itself. So there's an internal consistency problem if any
* of them is larger than our format buffer size. */
single_fmt_length = f - start + 1;
assert (single_fmt_length + 1 <= SINGLE_FMT_BUFFER_SIZE);
/* Reuse the format string for this conversion. */
memcpy (single_fmt, start, f + 1 - start);
single_fmt[f + 1 - start] = '\0';
memcpy (single_fmt, start, single_fmt_length);
single_fmt[single_fmt_length] = '\0';
/* Flush contents of buffer before snprintf()'ing into it. */
_cairo_output_stream_write (stream, buffer, p - buffer);
@ -337,15 +348,27 @@ _cairo_output_stream_vprintf (cairo_output_stream_t *stream,
case 'o':
case 'x':
case 'X':
snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
if (var_width) {
width = va_arg (ap, int);
snprintf (buffer, sizeof buffer,
single_fmt, width, va_arg (ap, int));
} else {
snprintf (buffer, sizeof buffer, single_fmt, va_arg (ap, int));
}
break;
case 'd' | LENGTH_MODIFIER_LONG:
case 'u' | LENGTH_MODIFIER_LONG:
case 'o' | LENGTH_MODIFIER_LONG:
case 'x' | LENGTH_MODIFIER_LONG:
case 'X' | LENGTH_MODIFIER_LONG:
snprintf (buffer, sizeof buffer,
single_fmt, va_arg (ap, long int));
if (var_width) {
width = va_arg (ap, int);
snprintf (buffer, sizeof buffer,
single_fmt, width, va_arg (ap, long int));
} else {
snprintf (buffer, sizeof buffer,
single_fmt, va_arg (ap, long int));
}
break;
case 's':
snprintf (buffer, sizeof buffer,
@ -446,11 +469,11 @@ _cairo_output_stream_create_for_file (FILE *file)
stdio_stream_t *stream;
if (file == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
stream = malloc (sizeof *stream);
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
_cairo_output_stream_init (&stream->base, stdio_write, stdio_flush);
stream->file = file;
@ -466,12 +489,12 @@ _cairo_output_stream_create_for_filename (const char *filename)
file = fopen (filename, "wb");
if (file == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil_write_error;
return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error;
stream = malloc (sizeof *stream);
if (stream == NULL) {
fclose (file);
return (cairo_output_stream_t *) &cairo_output_stream_nil;
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
}
_cairo_output_stream_init (&stream->base, stdio_write, stdio_close);
@ -512,7 +535,7 @@ _cairo_memory_stream_create (void)
stream = malloc (sizeof *stream);
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
_cairo_output_stream_init (&stream->base, memory_write, memory_close);
_cairo_array_init (&stream->array, 1);

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

@ -36,106 +36,37 @@
#ifndef CAIRO_PAGINATED_SURFACE_H
#define CAIRO_PAGINATED_SURFACE_H
#include "cairoint.h"
#include "cairo.h"
typedef enum {
CAIRO_PAGINATED_MODE_ANALYZE, /* analyze page regions */
CAIRO_PAGINATED_MODE_RENDER /* render page contents */
} cairo_paginated_mode_t;
#include "cairo-surface-private.h"
typedef struct _cairo_paginated_surface_backend {
/* Optional. Will be called once for each page.
*
* NOTE: With respect to the order of drawing operations as seen
* by the target, this call will occur before any drawing
* operations for the relevant page. However, with respect to the
* function calls as made by the user, this call will be *after*
* any drawing operations for the page, (that is, it will occur
* during the user's call to cairo_show_page or cairo_copy_page).
*/
cairo_int_status_t
(*start_page) (void *surface);
typedef struct _cairo_paginated_surface {
cairo_surface_t base;
/* Required. Will be called twice for each page, once with an
* argument of CAIRO_PAGINATED_MODE_ANALYZE and once with
* CAIRO_PAGINATED_MODE_RENDER. See more details in the
* documentation for _cairo_paginated_surface_create below.
*/
void
(*set_paginated_mode) (void *surface,
cairo_paginated_mode_t mode);
} cairo_paginated_surface_backend_t;
/* The target surface to hold the final result. */
cairo_surface_t *target;
/* A cairo_paginated_surface provides a very convenient wrapper that
* is well-suited for doing the analysis common to most surfaces that
* have paginated output, (that is, things directed at printers, or
* for saving content in files such as PostScript or PDF files).
*
* To use the paginated surface, you'll first need to create your
* 'real' surface using _cairo_surface_init and the standard
* cairo_surface_backend_t. Then you also call
* _cairo_paginated_surface_create which takes its own, much simpler,
* cairo_paginated_surface_backend. You are free to return the result
* of _cairo_paginated_surface_create from your public
* cairo_<foo>_surface_create. The paginated backend will be careful
* to not let the user see that they really got a "wrapped"
* surface. See test-paginated-surface.c for a fairly minimal example
* of a paginated-using surface. That should be a reasonable example
* to follow.
*
* What the paginated surface does is first save all drawing
* operations for a page into a meta-surface. Then when the user calls
* cairo_show_page, the paginated surface performs the following
* sequence of operations (using the backend functions passed to
* cairo_paginated_surface_create):
*
* 1. Calls start_page (if non NULL). At this point, it is appropriate
* for the target to emit any page-specific header information into
* its output.
*
* 2. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_ANALYZE
*
* 3. Replays the meta-surface to the target surface, (with an
* analysis surface inserted between which watches the return value
* from each operation). This analysis stage is used to decide which
* operations will require fallbacks.
*
* 4. Calls set_paginated_mode with an argument of CAIRO_PAGINATED_MODE_RENDER
*
* 5. Replays a subset of the meta-surface operations to the target surface
*
* 6. Replays the remaining operations to an image surface, sets an
* appropriate clip on the target, then paints the resulting image
* surface to the target.
*
* So, the target will see drawing operations during two separate
* stages, (ANALYZE and RENDER). During the ANALYZE phase the target
* should not actually perform any rendering, (for example, if
* performing output to a file, no output should be generated during
* this stage). Instead the drawing functions simply need to return
* CAIRO_STATUS_SUCCESS or CAIRO_INT_STATUS_UNSUPPORTED to indicate
* whether rendering would be supported. And it should do this as
* quickly as possible.
*
* NOTE: The paginated surface layer assumes that the target surface
* is "blank" by default at the beginning of each page, without any
* need for an explicit erasea operation, (as opposed to an image
* surface, for example, which might have uninitialized content
* originally). As such, it optimizes away CLEAR operations that
* happen at the beginning of each page---the target surface will not
* even see these operations.
*/
cairo_private cairo_surface_t *
_cairo_paginated_surface_create (cairo_surface_t *target,
cairo_content_t content,
int width,
int height,
const cairo_paginated_surface_backend_t *backend);
cairo_content_t content;
cairo_private cairo_surface_t *
_cairo_paginated_surface_get_target (cairo_surface_t *surface);
/* XXX: These shouldn't actually exist. We inherit this ugliness
* from _cairo_meta_surface_create. The width/height parameters
* from that function also should not exist. The fix that will
* allow us to remove all of these is to fix acquire_source_image
* to pass an interest rectangle. */
int width;
int height;
cairo_private cairo_bool_t
_cairo_surface_is_paginated (cairo_surface_t *surface);
/* Paginated-surface specific functions for the target */
const cairo_paginated_surface_backend_t *backend;
/* A cairo_meta_surface to record all operations. To be replayed
* against target, and also against image surface as necessary for
* fallbacks. */
cairo_surface_t *meta;
int page_num;
cairo_bool_t page_is_blank;
} cairo_paginated_surface_t;
#endif /* CAIRO_PAGINATED_SURFACE_H */

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

@ -36,45 +36,17 @@
/* The paginated surface layer exists to provide as much code sharing
* as possible for the various paginated surface backends in cairo
* (PostScript, PDF, etc.). See cairo-paginated-surface-private.h for
* (PostScript, PDF, etc.). See cairo-paginated-private.h for
* more details on how it works and how to use it.
*/
#include "cairoint.h"
#include "cairo-paginated-private.h"
#include "cairo-paginated-surface-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-analysis-surface-private.h"
typedef struct _cairo_paginated_surface {
cairo_surface_t base;
/* The target surface to hold the final result. */
cairo_surface_t *target;
cairo_content_t content;
/* XXX: These shouldn't actually exist. We inherit this ugliness
* from _cairo_meta_surface_create. The width/height parameters
* from that function also should not exist. The fix that will
* allow us to remove all of these is to fix acquire_source_image
* to pass an interest rectangle. */
int width;
int height;
/* Paginated-surface specific functions for the target */
const cairo_paginated_surface_backend_t *backend;
/* A cairo_meta_surface to record all operations. To be replayed
* against target, and also against image surface as necessary for
* fallbacks. */
cairo_surface_t *meta;
int page_num;
cairo_bool_t page_is_blank;
} cairo_paginated_surface_t;
const cairo_private cairo_surface_backend_t cairo_paginated_surface_backend;
static cairo_int_status_t
@ -162,11 +134,15 @@ _cairo_paginated_surface_finish (void *abstract_surface)
if (surface->page_is_blank == FALSE || surface->page_num == 1)
status = _cairo_paginated_surface_show_page (abstract_surface);
if (status == CAIRO_STATUS_SUCCESS)
if (status == CAIRO_STATUS_SUCCESS) {
cairo_surface_finish (surface->target);
status = cairo_surface_status (surface->target);
}
if (status == CAIRO_STATUS_SUCCESS)
if (status == CAIRO_STATUS_SUCCESS) {
cairo_surface_finish (surface->meta);
status = cairo_surface_status (surface->meta);
}
cairo_surface_destroy (surface->target);
@ -201,15 +177,22 @@ _cairo_paginated_surface_acquire_source_image (void *abstract_surface,
{
cairo_paginated_surface_t *surface = abstract_surface;
cairo_surface_t *image;
cairo_rectangle_int16_t extents;
cairo_status_t status;
cairo_rectangle_int_t extents;
_cairo_surface_get_extents (surface->target, &extents);
status = _cairo_surface_get_extents (surface->target, &extents);
if (status)
return status;
image = _cairo_paginated_surface_create_image_surface (surface,
extents.width,
extents.height);
_cairo_meta_surface_replay (surface->meta, image);
status = _cairo_meta_surface_replay (surface->meta, image);
if (status) {
cairo_surface_destroy (image);
return status;
}
*image_out = (cairo_image_surface_t*) image;
*image_extra = NULL;
@ -235,13 +218,16 @@ _paint_page (cairo_paginated_surface_t *surface)
analysis = _cairo_analysis_surface_create (surface->target,
surface->width, surface->height);
if (analysis == NULL)
return CAIRO_STATUS_NO_MEMORY;
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE);
_cairo_meta_surface_replay (surface->meta, analysis);
status = _cairo_meta_surface_replay (surface->meta, analysis);
surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_RENDER);
if (analysis->status) {
status = analysis->status;
if (status || analysis->status) {
if (status == CAIRO_STATUS_SUCCESS)
status = analysis->status;
cairo_surface_destroy (analysis);
return status;
}
@ -257,26 +243,29 @@ _paint_page (cairo_paginated_surface_t *surface)
surface->height * y_scale);
_cairo_surface_set_device_scale (image, x_scale, y_scale);
_cairo_meta_surface_replay (surface->meta, image);
status = _cairo_meta_surface_replay (surface->meta, image);
if (status)
goto CLEANUP_IMAGE;
pattern = cairo_pattern_create_for_surface (image);
cairo_matrix_init_scale (&matrix, x_scale, y_scale);
cairo_pattern_set_matrix (pattern, &matrix);
_cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
status = _cairo_surface_paint (surface->target, CAIRO_OPERATOR_SOURCE, pattern);
cairo_pattern_destroy (pattern);
CLEANUP_IMAGE:
cairo_surface_destroy (image);
}
else
{
_cairo_meta_surface_replay (surface->meta, surface->target);
status = _cairo_meta_surface_replay (surface->meta, surface->target);
}
cairo_surface_destroy (analysis);
return CAIRO_STATUS_SUCCESS;
return status;
}
static cairo_status_t
@ -298,7 +287,9 @@ _cairo_paginated_surface_copy_page (void *abstract_surface)
if (status)
return status;
_paint_page (surface);
status = _paint_page (surface);
if (status)
return status;
surface->page_num++;
@ -323,9 +314,16 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
if (status)
return status;
_paint_page (surface);
status = _paint_page (surface);
if (status)
return status;
_cairo_surface_show_page (surface->target);
status = _cairo_surface_show_page (surface->target);
if (status)
return status;
if (cairo_surface_status (surface->meta))
return cairo_surface_status (surface->meta);
cairo_surface_destroy (surface->meta);
@ -356,7 +354,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_paginated_surface_t *surface = abstract_surface;
@ -485,6 +483,7 @@ _cairo_paginated_surface_show_glyphs (void *abstract_surface,
static cairo_surface_t *
_cairo_paginated_surface_snapshot (void *abstract_other)
{
cairo_status_t status;
cairo_paginated_surface_t *other = abstract_other;
/* XXX: Just making a snapshot of other->meta is what we really
@ -502,16 +501,22 @@ _cairo_paginated_surface_snapshot (void *abstract_other)
#if 0
return _cairo_surface_snapshot (other->meta);
#else
cairo_rectangle_int16_t extents;
cairo_rectangle_int_t extents;
cairo_surface_t *surface;
_cairo_surface_get_extents (other->target, &extents);
status = _cairo_surface_get_extents (other->target, &extents);
if (status)
return (cairo_surface_t*) &_cairo_surface_nil;
surface = _cairo_paginated_surface_create_image_surface (other,
extents.width,
extents.height);
_cairo_meta_surface_replay (other->meta, surface);
status = _cairo_meta_surface_replay (other->meta, surface);
if (status) {
cairo_surface_destroy (surface);
surface = (cairo_surface_t*) &_cairo_surface_nil;
}
return surface;
#endif

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

@ -51,7 +51,7 @@ _cairo_path_bounder_init (cairo_path_bounder_t *bounder);
static void
_cairo_path_bounder_fini (cairo_path_bounder_t *bounder);
static cairo_status_t
static void
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *point);
static cairo_status_t
@ -81,7 +81,7 @@ _cairo_path_bounder_fini (cairo_path_bounder_t *bounder)
bounder->has_point = 0;
}
static cairo_status_t
static void
_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *point)
{
if (bounder->has_point) {
@ -104,8 +104,6 @@ _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *poi
bounder->has_point = 1;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t

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

@ -88,37 +88,28 @@ _cairo_filler_fini (cairo_filler_t *filler)
static cairo_status_t
_cairo_filler_move_to (void *closure, cairo_point_t *point)
{
cairo_status_t status;
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
status = _cairo_polygon_close (polygon);
if (status)
return status;
status = _cairo_polygon_move_to (polygon, point);
if (status)
return status;
_cairo_polygon_close (polygon);
_cairo_polygon_move_to (polygon, point);
filler->current_point = *point;
return CAIRO_STATUS_SUCCESS;
return _cairo_polygon_status (&filler->polygon);
}
static cairo_status_t
_cairo_filler_line_to (void *closure, cairo_point_t *point)
{
cairo_status_t status;
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
status = _cairo_polygon_line_to (polygon, point);
if (status)
return status;
_cairo_polygon_line_to (polygon, point);
filler->current_point = *point;
return CAIRO_STATUS_SUCCESS;
return _cairo_polygon_status (&filler->polygon);
}
static cairo_status_t
@ -138,15 +129,12 @@ _cairo_filler_curve_to (void *closure,
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
_cairo_spline_decompose (&spline, filler->tolerance);
status = _cairo_spline_decompose (&spline, filler->tolerance);
if (status)
goto CLEANUP_SPLINE;
for (i = 1; i < spline.num_points; i++) {
status = _cairo_polygon_line_to (polygon, &spline.points[i]);
if (status)
break;
}
for (i = 1; i < spline.num_points; i++)
_cairo_polygon_line_to (polygon, &spline.points[i]);
CLEANUP_SPLINE:
_cairo_spline_fini (&spline);
@ -159,15 +147,12 @@ _cairo_filler_curve_to (void *closure,
static cairo_status_t
_cairo_filler_close_path (void *closure)
{
cairo_status_t status;
cairo_filler_t *filler = closure;
cairo_polygon_t *polygon = &filler->polygon;
status = _cairo_polygon_close (polygon);
if (status)
return status;
_cairo_polygon_close (polygon);
return CAIRO_STATUS_SUCCESS;
return _cairo_polygon_status (polygon);
}
static cairo_int_status_t
@ -201,7 +186,8 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
if (status)
goto BAIL;
status = _cairo_polygon_close (&filler.polygon);
_cairo_polygon_close (&filler.polygon);
status = _cairo_polygon_status (&filler.polygon);
if (status)
goto BAIL;

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

@ -1,3 +1,4 @@
/* -*- 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
@ -35,7 +36,6 @@
* 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 (path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE ||
path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
if ((unsigned int) path->buf_tail->num_ops + 1 > CAIRO_PATH_BUF_SIZE ||
(unsigned int) path->buf_tail->num_points + num_points > CAIRO_PATH_BUF_SIZE)
{
cairo_path_buf_t *buf;
@ -510,25 +510,19 @@ _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 {
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));
buf->points[i].x = _cairo_fixed_mul (buf->points[i].x + offx, scalex);
}
if (scaley == CAIRO_FIXED_ONE) {
buf->points[i].y += offy;
} else {
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));
buf->points[i].y = _cairo_fixed_mul (buf->points[i].y + offy, scaley);
}
}

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

@ -67,7 +67,7 @@ typedef struct cairo_stroker {
} cairo_stroker_t;
/* private functions */
static void
static cairo_status_t
_cairo_stroker_init (cairo_stroker_t *stroker,
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *ctm,
@ -148,7 +148,7 @@ _cairo_stroker_step_dash (cairo_stroker_t *stroker, double step)
}
}
static void
static cairo_status_t
_cairo_stroker_init (cairo_stroker_t *stroker,
cairo_stroke_style_t *stroke_style,
cairo_matrix_t *ctm,
@ -156,15 +156,18 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
double tolerance,
cairo_traps_t *traps)
{
cairo_status_t status;
stroker->style = stroke_style;
stroker->ctm = ctm;
stroker->ctm_inverse = ctm_inverse;
stroker->tolerance = tolerance;
stroker->traps = traps;
_cairo_pen_init (&stroker->pen,
stroke_style->line_width / 2.0,
tolerance, ctm);
status = _cairo_pen_init (&stroker->pen,
stroke_style->line_width / 2.0,
tolerance, ctm);
if (status)
return status;
stroker->has_current_face = FALSE;
stroker->has_first_face = FALSE;
@ -174,6 +177,8 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
_cairo_stroker_start_dash (stroker);
else
stroker->dashed = FALSE;
return CAIRO_STATUS_SUCCESS;
}
static void
@ -205,6 +210,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
{
int clockwise = _cairo_stroker_face_clockwise (out, in);
cairo_point_t *inpt, *outpt;
cairo_status_t status;
if (in->cw.x == out->cw.x
&& in->cw.y == out->cw.y
@ -231,13 +237,21 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
tri[0] = in->point;
if (clockwise) {
_cairo_pen_find_active_ccw_vertex_index (pen, &in->dev_vector, &start);
status = _cairo_pen_find_active_ccw_vertex_index (pen, &in->dev_vector, &start);
if (status)
return status;
step = -1;
_cairo_pen_find_active_ccw_vertex_index (pen, &out->dev_vector, &stop);
status = _cairo_pen_find_active_ccw_vertex_index (pen, &out->dev_vector, &stop);
if (status)
return status;
} else {
_cairo_pen_find_active_cw_vertex_index (pen, &in->dev_vector, &start);
status = _cairo_pen_find_active_cw_vertex_index (pen, &in->dev_vector, &start);
if (status)
return status;
step = +1;
_cairo_pen_find_active_cw_vertex_index (pen, &out->dev_vector, &stop);
status = _cairo_pen_find_active_cw_vertex_index (pen, &out->dev_vector, &stop);
if (status)
return status;
}
i = start;
@ -245,7 +259,9 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st
while (i != stop) {
tri[2] = in->point;
_translate_point (&tri[2], &pen->vertices[i].point);
_cairo_traps_tessellate_triangle (stroker->traps, tri);
status = _cairo_traps_tessellate_triangle (stroker->traps, tri);
if (status)
return status;
tri[1] = tri[2];
i += step;
if (i < 0)
@ -378,17 +394,23 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
cairo_pen_t *pen = &stroker->pen;
slope = f->dev_vector;
_cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
status = _cairo_pen_find_active_cw_vertex_index (pen, &slope, &start);
if (status)
return status;
slope.dx = -slope.dx;
slope.dy = -slope.dy;
_cairo_pen_find_active_cw_vertex_index (pen, &slope, &stop);
status = _cairo_pen_find_active_cw_vertex_index (pen, &slope, &stop);
if (status)
return status;
tri[0] = f->point;
tri[1] = f->cw;
for (i=start; i != stop; i = (i+1) % pen->num_vertices) {
tri[2] = f->point;
_translate_point (&tri[2], &pen->vertices[i].point);
_cairo_traps_tessellate_triangle (stroker->traps, tri);
status = _cairo_traps_tessellate_triangle (stroker->traps, tri);
if (status)
return status;
tri[1] = tri[2];
}
tri[2] = f->ccw;
@ -419,8 +441,14 @@ _cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f)
_cairo_polygon_line_to (&polygon, &occw);
_cairo_polygon_line_to (&polygon, &f->ccw);
_cairo_polygon_close (&polygon);
status = _cairo_polygon_status (&polygon);
if (status == CAIRO_STATUS_SUCCESS) {
status = _cairo_bentley_ottmann_tessellate_polygon (stroker->traps,
&polygon,
CAIRO_FILL_RULE_WINDING);
}
status = _cairo_bentley_ottmann_tessellate_polygon (stroker->traps, &polygon, CAIRO_FILL_RULE_WINDING);
_cairo_polygon_fini (&polygon);
return status;
@ -967,9 +995,11 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
_cairo_stroker_init (&stroker, stroke_style,
ctm, ctm_inverse, tolerance,
traps);
status = _cairo_stroker_init (&stroker, stroke_style,
ctm, ctm_inverse, tolerance,
traps);
if (status)
return status;
if (stroker.style->dash)
status = _cairo_path_fixed_interpret (path,

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

@ -34,9 +34,10 @@
* Carl D. Worth <cworth@redhat.com>
*/
#include "cairoint.h"
#include "cairo-path-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-gstate-private.h"
const cairo_path_t _cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
@ -135,6 +136,7 @@ _cairo_path_count (cairo_path_t *path,
double tolerance,
cairo_bool_t flatten)
{
cairo_status_t status;
cpc_t cpc;
cpc.count = 0;
@ -142,15 +144,17 @@ _cairo_path_count (cairo_path_t *path,
cpc.current_point.x = 0;
cpc.current_point.y = 0;
_cairo_path_fixed_interpret (path_fixed,
CAIRO_DIRECTION_FORWARD,
_cpc_move_to,
_cpc_line_to,
flatten ?
_cpc_curve_to_flatten :
_cpc_curve_to,
_cpc_close_path,
&cpc);
status = _cairo_path_fixed_interpret (path_fixed,
CAIRO_DIRECTION_FORWARD,
_cpc_move_to,
_cpc_line_to,
flatten ?
_cpc_curve_to_flatten :
_cpc_curve_to,
_cpc_close_path,
&cpc);
if (status)
return -1;
return cpc.count;
}
@ -275,7 +279,8 @@ _cpp_curve_to_flatten (void *closure,
if (status == CAIRO_INT_STATUS_DEGENERATE)
return CAIRO_STATUS_SUCCESS;
status = _cairo_spline_decompose (&spline, cpp->gstate->tolerance);
status = _cairo_spline_decompose (&spline,
_cairo_gstate_get_tolerance (cpp->gstate));
if (status)
goto out;
@ -305,12 +310,13 @@ _cpp_close_path (void *closure)
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
_cairo_path_populate (cairo_path_t *path,
cairo_path_fixed_t *path_fixed,
cairo_gstate_t *gstate,
cairo_bool_t flatten)
{
cairo_status_t status;
cpp_t cpp;
cpp.data = path->data;
@ -318,18 +324,22 @@ _cairo_path_populate (cairo_path_t *path,
cpp.current_point.x = 0;
cpp.current_point.y = 0;
_cairo_path_fixed_interpret (path_fixed,
CAIRO_DIRECTION_FORWARD,
_cpp_move_to,
_cpp_line_to,
flatten ?
_cpp_curve_to_flatten :
_cpp_curve_to,
_cpp_close_path,
&cpp);
status = _cairo_path_fixed_interpret (path_fixed,
CAIRO_DIRECTION_FORWARD,
_cpp_move_to,
_cpp_line_to,
flatten ?
_cpp_curve_to_flatten :
_cpp_curve_to,
_cpp_close_path,
&cpp);
if (status)
return status;
/* Sanity check the count */
assert (cpp.data - path->data == path->num_data);
return status;
}
cairo_path_t *
@ -337,6 +347,10 @@ _cairo_path_create_in_error (cairo_status_t status)
{
cairo_path_t *path;
/* special case NO_MEMORY so as to avoid allocations */
if (status == CAIRO_STATUS_NO_MEMORY)
return (cairo_path_t*) &_cairo_path_nil;
path = malloc (sizeof (cairo_path_t));
if (path == NULL)
return (cairo_path_t*) &_cairo_path_nil;
@ -360,18 +374,21 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed,
return (cairo_path_t*) &_cairo_path_nil;
path->num_data = _cairo_path_count (path, path_fixed,
gstate->tolerance, flatten);
_cairo_gstate_get_tolerance (gstate),
flatten);
if (path->num_data <= 0) {
free (path);
return (cairo_path_t*) &_cairo_path_nil;
}
path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
path->data = _cairo_malloc_ab (path->num_data, sizeof (cairo_path_data_t));
if (path->data == NULL) {
free (path);
return (cairo_path_t*) &_cairo_path_nil;
}
path->status = CAIRO_STATUS_SUCCESS;
_cairo_path_populate (path, path_fixed,
gstate, flatten);
path->status = _cairo_path_populate (path, path_fixed,
gstate, flatten);
return path;
}
@ -460,6 +477,7 @@ _cairo_path_append_to_context (const cairo_path_t *path,
{
int i;
cairo_path_data_t *p;
cairo_status_t status;
for (i=0; i < path->num_data; i += path->data[i].header.length) {
p = &path->data[i];
@ -492,6 +510,10 @@ _cairo_path_append_to_context (const cairo_path_t *path,
default:
return CAIRO_STATUS_INVALID_PATH_DATA;
}
status = cairo_status (cr);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;

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

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

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

@ -1,54 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_PDF_TEST_H
#define CAIRO_PDF_TEST_H
#include <cairo.h>
#if CAIRO_HAS_PDF_SURFACE
#include <cairo-pdf.h>
CAIRO_BEGIN_DECLS
cairo_public void
_cairo_pdf_test_force_fallbacks (void);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_PDF_SURFACE */
#endif /* CAIRO_PDF_TEST_H */

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

@ -45,15 +45,13 @@ _cairo_pen_compute_slopes (cairo_pen_t *pen);
static cairo_status_t
_cairo_pen_stroke_spline_half (cairo_pen_t *pen, cairo_spline_t *spline, cairo_direction_t dir, cairo_polygon_t *polygon);
cairo_status_t
void
_cairo_pen_init_empty (cairo_pen_t *pen)
{
pen->radius = 0;
pen->tolerance = 0;
pen->vertices = NULL;
pen->num_vertices = 0;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -80,7 +78,7 @@ _cairo_pen_init (cairo_pen_t *pen,
radius,
ctm);
pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
pen->vertices = _cairo_malloc_ab (pen->num_vertices, sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL) {
return CAIRO_STATUS_NO_MEMORY;
}
@ -121,7 +119,7 @@ _cairo_pen_init_copy (cairo_pen_t *pen, cairo_pen_t *other)
*pen = *other;
if (pen->num_vertices) {
pen->vertices = malloc (pen->num_vertices * sizeof (cairo_pen_vertex_t));
pen->vertices = _cairo_malloc_ab (pen->num_vertices, sizeof (cairo_pen_vertex_t));
if (pen->vertices == NULL) {
return CAIRO_STATUS_NO_MEMORY;
}
@ -135,6 +133,7 @@ cairo_status_t
_cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points)
{
cairo_pen_vertex_t *vertices;
cairo_status_t status;
int num_vertices;
int i;
@ -150,7 +149,9 @@ _cairo_pen_add_points (cairo_pen_t *pen, cairo_point_t *point, int num_points)
for (i=0; i < num_points; i++)
pen->vertices[pen->num_vertices-num_points+i].point = point[i];
_cairo_hull_compute (pen->vertices, &pen->num_vertices);
status = _cairo_hull_compute (pen->vertices, &pen->num_vertices);
if (status)
return status;
_cairo_pen_compute_slopes (pen);
@ -388,15 +389,18 @@ _cairo_pen_stroke_spline_half (cairo_pen_t *pen,
final_slope.dy = -final_slope.dy;
}
_cairo_pen_find_active_cw_vertex_index (pen, &initial_slope, &active);
status = _cairo_pen_find_active_cw_vertex_index (pen,
&initial_slope,
&active);
if (status)
return status;
i = start;
while (i != stop) {
hull_point.x = point[i].x + pen->vertices[active].point.x;
hull_point.y = point[i].y + pen->vertices[active].point.y;
status = _cairo_polygon_line_to (polygon, &hull_point);
if (status)
return status;
_cairo_polygon_line_to (polygon, &hull_point);
if (i + step == stop)
slope = final_slope;
@ -437,19 +441,24 @@ _cairo_pen_stroke_spline (cairo_pen_t *pen,
status = _cairo_spline_decompose (spline, tolerance);
if (status)
return status;
goto BAIL;
status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_FORWARD, &polygon);
if (status)
return status;
goto BAIL;
status = _cairo_pen_stroke_spline_half (pen, spline, CAIRO_DIRECTION_REVERSE, &polygon);
if (status)
return status;
goto BAIL;
_cairo_polygon_close (&polygon);
_cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
status = _cairo_polygon_status (&polygon);
if (status)
goto BAIL;
status = _cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, CAIRO_FILL_RULE_WINDING);
BAIL:
_cairo_polygon_fini (&polygon);
return CAIRO_STATUS_SUCCESS;
return status;
}

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

@ -35,8 +35,9 @@
* Kristian Høgsberg <krh@redhat.com>
*/
#include <errno.h>
#include "cairoint.h"
#include <errno.h>
#include <png.h>
/* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
@ -82,6 +83,25 @@ convert_data_to_bytes (png_structp png, png_row_infop row_info, png_bytep data)
}
}
/* Use a couple of simple error callbacks that do not print anything to
* stderr and rely on the user to check for errors via the cairo_status_t
* return.
*/
static void
png_simple_error_callback (png_structp png_save_ptr,
png_const_charp error_msg)
{
_cairo_error (CAIRO_STATUS_NO_MEMORY);
longjmp (png_save_ptr->jmpbuf, CAIRO_STATUS_NO_MEMORY);
}
static void
png_simple_warning_callback (png_structp png_save_ptr,
png_const_charp error_msg)
{
}
static cairo_status_t
write_png (cairo_surface_t *surface,
png_rw_ptr write_func,
@ -108,7 +128,7 @@ write_png (cairo_surface_t *surface,
else if (status != CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
rows = malloc (image->height * sizeof(png_byte*));
rows = _cairo_malloc_ab (image->height, sizeof(png_byte*));
if (rows == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL1;
@ -117,7 +137,9 @@ write_png (cairo_surface_t *surface,
for (i = 0; i < image->height; i++)
rows[i] = (png_byte *) image->data + i * image->stride;
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL,
png_simple_error_callback,
png_simple_warning_callback);
if (png == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto BAIL2;
@ -129,10 +151,9 @@ write_png (cairo_surface_t *surface,
goto BAIL3;
}
if (setjmp (png_jmpbuf (png))) {
status = CAIRO_STATUS_NO_MEMORY;
status = setjmp (png_jmpbuf (png));
if (status)
goto BAIL3;
}
png_set_write_fn (png, closure, write_func, NULL);
@ -154,7 +175,7 @@ write_png (cairo_surface_t *surface,
png_color_type = PNG_COLOR_TYPE_GRAY;
break;
default:
status = CAIRO_STATUS_NULL_POINTER;
status = CAIRO_STATUS_INVALID_FORMAT;
goto BAIL3;
}
@ -206,8 +227,13 @@ stdio_write_func (png_structp png, png_bytep data, png_size_t size)
FILE *fp;
fp = png_get_io_ptr (png);
if (fwrite (data, 1, size, fp) != size)
png_error(png, "Write Error");
while (size) {
size_t ret = fwrite (data, 1, size, fp);
size -= ret;
data += ret;
if (size && ferror (fp))
png_error(png, "Write Error");
}
}
/**
@ -332,20 +358,20 @@ read_png (png_rw_ptr read_func,
void *closure)
{
cairo_surface_t *surface = (cairo_surface_t*) &_cairo_surface_nil;
png_byte *data = NULL;
unsigned int i;
png_struct *png = NULL;
png_info *info;
png_byte *data = NULL;
png_byte **row_pointers = NULL;
png_uint_32 png_width, png_height, stride;
int depth, color_type, interlace;
unsigned int i;
unsigned int pixel_size;
png_byte **row_pointers = NULL;
/* XXX: Perhaps we'll want some other error handlers? */
png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL);
png_simple_error_callback,
png_simple_warning_callback);
if (png == NULL)
goto BAIL;
@ -373,7 +399,11 @@ read_png (png_rw_ptr read_func,
/* expand gray bit depth if needed */
if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8)
#if PNG_LIBPNG_VER >= 10209
png_set_expand_gray_1_2_4_to_8 (png);
#else
png_set_gray_1_2_4_to_8 (png);
#endif
/* transform transparency to alpha */
if (png_get_valid(png, info, PNG_INFO_tRNS))
png_set_tRNS_to_alpha (png);
@ -399,11 +429,11 @@ read_png (png_rw_ptr read_func,
png_read_update_info (png, info);
pixel_size = 4;
data = malloc (png_width * png_height * pixel_size);
data = _cairo_malloc_abc (png_height, png_width, pixel_size);
if (data == NULL)
goto BAIL;
row_pointers = malloc (png_height * sizeof(char *));
row_pointers = _cairo_malloc_ab (png_height, sizeof(char *));
if (row_pointers == NULL)
goto BAIL;
@ -442,8 +472,13 @@ stdio_read_func (png_structp png, png_bytep data, png_size_t size)
FILE *fp;
fp = png_get_io_ptr (png);
if (fread (data, 1, size, fp) != size)
png_error(png, "Read Error");
while (size) {
size_t ret = fread (data, 1, size, fp);
size -= ret;
data += ret;
if (size && ferror (fp))
png_error(png, "Read Error");
}
}
/**

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

@ -34,7 +34,6 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include <stdlib.h>
#include "cairoint.h"
/* private functions */
@ -45,6 +44,8 @@ _cairo_polygon_grow (cairo_polygon_t *polygon);
void
_cairo_polygon_init (cairo_polygon_t *polygon)
{
polygon->status = CAIRO_STATUS_SUCCESS;
polygon->num_edges = 0;
polygon->edges_size = 0;
@ -66,13 +67,19 @@ _cairo_polygon_fini (cairo_polygon_t *polygon)
polygon->has_current_point = FALSE;
}
cairo_status_t
_cairo_polygon_status (cairo_polygon_t *polygon)
{
return polygon->status;
}
/* make room for at least one more edge */
static cairo_status_t
_cairo_polygon_grow (cairo_polygon_t *polygon)
{
cairo_edge_t *new_edges;
int old_size = polygon->edges_size;
int embedded_size = sizeof (polygon->edges_embedded) / sizeof (polygon->edges_embedded[0]);
int embedded_size = ARRAY_LENGTH (polygon->edges_embedded);
int new_size = 2 * MAX (old_size, 16);
/* we have a local buffer at polygon->edges_embedded. try to fulfill the request
@ -86,7 +93,7 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
assert (polygon->num_edges <= polygon->edges_size);
if (polygon->edges == polygon->edges_embedded) {
new_edges = malloc (new_size * sizeof (cairo_edge_t));
new_edges = _cairo_malloc_ab (new_size, sizeof (cairo_edge_t));
if (new_edges)
memcpy (new_edges, polygon->edges, old_size * sizeof (cairo_edge_t));
} else {
@ -103,22 +110,22 @@ _cairo_polygon_grow (cairo_polygon_t *polygon)
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
void
_cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_point_t *p2)
{
cairo_status_t status;
cairo_edge_t *edge;
if (polygon->status)
return;
/* drop horizontal edges */
if (p1->y == p2->y) {
if (p1->y == p2->y)
goto DONE;
}
if (polygon->num_edges >= polygon->edges_size) {
status = _cairo_polygon_grow (polygon);
if (status) {
return status;
}
polygon->status = _cairo_polygon_grow (polygon);
if (polygon->status)
return;
}
edge = &polygon->edges[polygon->num_edges];
@ -136,49 +143,45 @@ _cairo_polygon_add_edge (cairo_polygon_t *polygon, cairo_point_t *p1, cairo_poin
DONE:
_cairo_polygon_move_to (polygon, p2);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
void
_cairo_polygon_move_to (cairo_polygon_t *polygon, cairo_point_t *point)
{
if (polygon->status)
return;
if (! polygon->has_current_point)
polygon->first_point = *point;
polygon->current_point = *point;
polygon->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
void
_cairo_polygon_line_to (cairo_polygon_t *polygon, cairo_point_t *point)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
if (polygon->status)
return;
if (polygon->has_current_point) {
status = _cairo_polygon_add_edge (polygon, &polygon->current_point, point);
_cairo_polygon_add_edge (polygon, &polygon->current_point, point);
} else {
_cairo_polygon_move_to (polygon, point);
}
return status;
}
cairo_status_t
void
_cairo_polygon_close (cairo_polygon_t *polygon)
{
cairo_status_t status;
if (polygon->status)
return;
if (polygon->has_current_point) {
status = _cairo_polygon_add_edge (polygon,
&polygon->current_point,
&polygon->first_point);
if (status)
return status;
_cairo_polygon_add_edge (polygon,
&polygon->current_point,
&polygon->first_point);
polygon->has_current_point = FALSE;
}
return CAIRO_STATUS_SUCCESS;
}

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

@ -39,9 +39,9 @@
#include "cairoint.h"
#include "cairo-ps.h"
#include "cairo-ps-test.h"
#include "cairo-ps-surface-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-paginated-surface-private.h"
#include "cairo-paginated-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-output-stream-private.h"
@ -52,40 +52,6 @@
static const cairo_surface_backend_t cairo_ps_surface_backend;
static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend;
typedef struct cairo_ps_surface {
cairo_surface_t base;
/* Here final_stream corresponds to the stream/file passed to
* cairo_ps_surface_create surface is built. Meanwhile stream is a
* temporary stream in which the file output is built, (so that
* the header can be built and inserted into the target stream
* before the contents of the temporary stream are copied). */
cairo_output_stream_t *final_stream;
FILE *tmpfile;
cairo_output_stream_t *stream;
double width;
double height;
double max_width;
double max_height;
int num_pages;
cairo_paginated_mode_t paginated_mode;
cairo_scaled_font_subsets_t *font_subsets;
cairo_array_t dsc_header_comments;
cairo_array_t dsc_setup_comments;
cairo_array_t dsc_page_setup_comments;
cairo_array_t *dsc_comment_target;
} cairo_ps_surface_t;
#define PS_SURFACE_MAX_GLYPHS_PER_FONT 256
/* A word wrap stream can be used as a filter to do word wrapping on
* top of an existing output stream. The word wrapping is quite
* simple, using isspace to determine characters that separate
@ -182,7 +148,7 @@ _word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
stream = malloc (sizeof (word_wrap_stream_t));
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
_cairo_output_stream_init (&stream->base,
_word_wrap_stream_write,
@ -297,7 +263,7 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface,
cairo_line_cap_t line_cap)
{
cairo_output_stream_t *word_wrap;
cairo_status_t status;
cairo_status_t status, status2;
ps_path_info_t path_info;
word_wrap = _word_wrap_stream_create (stream, 79);
@ -315,7 +281,9 @@ _cairo_ps_surface_emit_path (cairo_ps_surface_t *surface,
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_output_stream_get_status (word_wrap);
_cairo_output_stream_destroy (word_wrap);
status2 = _cairo_output_stream_destroy (word_wrap);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
return status;
}
@ -484,18 +452,18 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
/* FIXME: Figure out how subset->x_max etc maps to the /FontBBox */
for (i = 0; i < font_subset->num_glyphs; i++)
for (i = 1; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->final_stream,
"Encoding %d /g%d put\n", i, i);
_cairo_output_stream_printf (surface->final_stream,
"/CharStrings %d dict dup begin\n"
"/.notdef 0 def\n",
font_subset->num_glyphs + 1);
font_subset->num_glyphs);
for (i = 0; i < font_subset->num_glyphs; i++)
for (i = 1; i < font_subset->num_glyphs; i++)
_cairo_output_stream_printf (surface->final_stream,
"/g%d %d def\n", i, i + 1);
"/g%d %d def\n", i, i);
_cairo_output_stream_printf (surface->final_stream,
"end readonly def\n");
@ -579,6 +547,8 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
CAIRO_SCALED_GLYPH_INFO_METRICS|
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (status)
return status;
image = scaled_glyph->surface;
if (image->format != CAIRO_FORMAT_A1) {
@ -634,7 +604,7 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
_cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
@ -658,6 +628,8 @@ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
if (status)
_cairo_surface_set_error (&surface->base, status);
return status;
}
static cairo_status_t
@ -666,6 +638,7 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
{
cairo_status_t status;
cairo_matrix_t matrix;
unsigned int i;
@ -678,7 +651,9 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
font_subset->subset_id);
matrix = font_subset->scaled_font->scale;
cairo_matrix_invert (&matrix);
status = cairo_matrix_invert (&matrix);
/* _cairo_scaled_font_init ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
_cairo_output_stream_printf (surface->final_stream,
"\t/FontType\t3\n"
"\t/FontMatrix\t[%f %f %f %f 0 0]\n"
@ -691,9 +666,11 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
-matrix.yy);
for (i = 0; i < font_subset->num_glyphs; i++) {
_cairo_ps_surface_emit_glyph (surface,
font_subset->scaled_font,
font_subset->glyphs[i], i);
status = _cairo_ps_surface_emit_glyph (surface,
font_subset->scaled_font,
font_subset->glyphs[i], i);
if (status)
return status;
}
_cairo_output_stream_printf (surface->final_stream,
@ -809,8 +786,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
if (status)
goto CLEANUP_TMPFILE;
surface->font_subsets = _cairo_scaled_font_subsets_create (PS_SURFACE_MAX_GLYPHS_PER_FONT,
PS_SURFACE_MAX_GLYPHS_PER_FONT);
surface->font_subsets = _cairo_scaled_font_subsets_create_simple ();
if (! surface->font_subsets)
goto CLEANUP_OUTPUT_STREAM;
@ -819,6 +795,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
surface->max_width = width;
surface->max_height = height;
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
surface->force_fallbacks = FALSE;
surface->num_pages = 0;
@ -834,7 +811,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
&cairo_ps_surface_paginated_backend);
CLEANUP_OUTPUT_STREAM:
_cairo_output_stream_destroy (surface->stream);
status = _cairo_output_stream_destroy (surface->stream);
/* Ignore status---we're already on a failure path. */
CLEANUP_TMPFILE:
fclose (surface->tmpfile);
CLEANUP_SURFACE:
@ -1201,7 +1179,7 @@ cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface)
static cairo_status_t
_cairo_ps_surface_finish (void *abstract_surface)
{
cairo_status_t status;
cairo_status_t status, status2;
cairo_ps_surface_t *surface = abstract_surface;
int i, num_comments;
char **comments;
@ -1214,16 +1192,13 @@ _cairo_ps_surface_finish (void *abstract_surface)
_cairo_ps_surface_emit_footer (surface);
_cairo_output_stream_close (surface->stream);
status = _cairo_output_stream_get_status (surface->stream);
_cairo_output_stream_destroy (surface->stream);
status = _cairo_output_stream_destroy (surface->stream);
fclose (surface->tmpfile);
_cairo_output_stream_close (surface->final_stream);
status2 = _cairo_output_stream_destroy (surface->final_stream);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_output_stream_get_status (surface->final_stream);
_cairo_output_stream_destroy (surface->final_stream);
status = status2;
num_comments = _cairo_array_num_elements (&surface->dsc_header_comments);
comments = _cairo_array_index (&surface->dsc_header_comments, 0);
@ -1383,32 +1358,12 @@ pattern_supported (const cairo_pattern_t *pattern)
return FALSE;
}
static cairo_bool_t cairo_ps_force_fallbacks = FALSE;
/**
* _cairo_ps_test_force_fallbacks
*
* Force the PS surface backend to use image fallbacks for every
* operation.
*
* <note>
* This function is <emphasis>only</emphasis> intended for internal
* testing use within the cairo distribution. It is not installed in
* any public header file.
* </note>
**/
void
_cairo_ps_test_force_fallbacks (void)
{
cairo_ps_force_fallbacks = TRUE;
}
static cairo_int_status_t
_cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *pattern)
{
if (cairo_ps_force_fallbacks)
if (surface->force_fallbacks)
return FALSE;
if (! pattern_supported (pattern))
@ -1542,7 +1497,7 @@ _string_array_stream_create (cairo_output_stream_t *output)
stream = malloc (sizeof (string_array_stream_t));
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
_cairo_output_stream_init (&stream->base,
_string_array_stream_write,
@ -1562,7 +1517,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
cairo_image_surface_t *image,
const char *name)
{
cairo_status_t status;
cairo_status_t status, status2;
unsigned char *rgb, *compressed;
unsigned long rgb_size, compressed_size;
cairo_surface_t *opaque;
@ -1588,20 +1543,29 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
_cairo_surface_fill_rectangle (opaque,
CAIRO_OPERATOR_SOURCE,
CAIRO_COLOR_WHITE,
0, 0, image->width, image->height);
status = _cairo_surface_fill_rectangle (opaque,
CAIRO_OPERATOR_SOURCE,
CAIRO_COLOR_WHITE,
0, 0,
image->width, image->height);
if (status) {
_cairo_pattern_fini (&pattern.base);
goto bail0;
}
_cairo_surface_composite (CAIRO_OPERATOR_OVER,
&pattern.base,
NULL,
opaque,
0, 0,
0, 0,
0, 0,
image->width,
image->height);
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
&pattern.base,
NULL,
opaque,
0, 0,
0, 0,
0, 0,
image->width,
image->height);
if (status) {
_cairo_pattern_fini (&pattern.base);
goto bail0;
}
_cairo_pattern_fini (&pattern.base);
opaque_image = (cairo_image_surface_t *) opaque;
@ -1619,7 +1583,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
i = 0;
for (y = 0; y < opaque_image->height; y++) {
pixman_bits_t *pixel = (pixman_bits_t *) (opaque_image->data + y * opaque_image->stride);
uint32_t *pixel = (uint32_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;
@ -1646,8 +1610,12 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
_cairo_output_stream_write (base85_stream, compressed, compressed_size);
_cairo_output_stream_destroy (base85_stream);
_cairo_output_stream_destroy (string_array_stream);
status = _cairo_output_stream_destroy (base85_stream);
status2 = _cairo_output_stream_destroy (string_array_stream);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
if (status)
goto bail3;
_cairo_output_stream_printf (surface->stream,
"] def\n");
@ -1679,6 +1647,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
status = CAIRO_STATUS_SUCCESS;
bail3:
free (compressed);
bail2:
free (rgb);
@ -1705,19 +1674,26 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface,
pattern->color.blue);
}
static void
static cairo_status_t
_cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
cairo_surface_pattern_t *pattern)
{
cairo_status_t status;
double bbox_width, bbox_height;
double xstep, ystep;
cairo_matrix_t inverse = pattern->base.matrix;
cairo_matrix_invert (&inverse);
status = cairo_matrix_invert (&inverse);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
if (_cairo_surface_is_meta (pattern->surface)) {
_cairo_output_stream_printf (surface->stream, "/MyPattern {\n");
_cairo_meta_surface_replay (pattern->surface, &surface->base);
status = _cairo_meta_surface_replay (pattern->surface, &surface->base);
if (status)
return status;
bbox_width = surface->width;
bbox_height = surface->height;
xstep = surface->width;
@ -1805,6 +1781,8 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
inverse.x0, inverse.y0);
_cairo_output_stream_printf (surface->stream,
"makepattern setpattern\n");
return CAIRO_STATUS_SUCCESS;
}
static void
@ -1821,12 +1799,13 @@ _cairo_ps_surface_emit_radial_pattern (cairo_ps_surface_t *surface,
/* XXX: NYI */
}
static void
static cairo_status_t
_cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pattern)
{
/* FIXME: We should keep track of what pattern is currently set in
* the postscript file and only emit code if we're setting a
* different pattern. */
cairo_status_t status;
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
@ -1834,7 +1813,10 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pa
break;
case CAIRO_PATTERN_TYPE_SURFACE:
_cairo_ps_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern);
status = _cairo_ps_surface_emit_surface_pattern (surface,
(cairo_surface_pattern_t *) pattern);
if (status)
return status;
break;
case CAIRO_PATTERN_TYPE_LINEAR:
@ -1845,6 +1827,8 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, cairo_pattern_t *pa
_cairo_ps_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern);
break;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@ -1894,7 +1878,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_ps_surface_t *surface = abstract_surface;
@ -1929,7 +1913,8 @@ _cairo_ps_surface_paint (void *abstract_surface,
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_rectangle_int16_t extents, pattern_extents;
cairo_rectangle_int_t extents, pattern_extents;
cairo_status_t status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_ps_surface_analyze_operation (surface, op, source);
@ -1941,17 +1926,25 @@ _cairo_ps_surface_paint (void *abstract_surface,
* possible only because there is nothing between the fallback
* images and the paper, nor is anything painted above. */
/*
assert (__cairo_ps_surface_operation_supported (op, source));
assert (_cairo_ps_surface_operation_supported (op, source));
*/
_cairo_output_stream_printf (stream,
"%% _cairo_ps_surface_paint\n");
_cairo_surface_get_extents (&surface->base, &extents);
_cairo_pattern_get_extents (source, &pattern_extents);
status = _cairo_surface_get_extents (&surface->base, &extents);
if (status)
return status;
status = _cairo_pattern_get_extents (source, &pattern_extents);
if (status)
return status;
_cairo_rectangle_intersect (&extents, &pattern_extents);
_cairo_ps_surface_emit_pattern (surface, source);
status = _cairo_ps_surface_emit_pattern (surface, source);
if (status)
return status;
_cairo_output_stream_printf (stream, "%d %d M\n",
extents.x, extents.y);
@ -1965,6 +1958,7 @@ _cairo_ps_surface_paint (void *abstract_surface,
extents.x,
extents.y + extents.height);
_cairo_output_stream_printf (stream, "P F\n");
return CAIRO_STATUS_SUCCESS;
}
@ -2043,7 +2037,7 @@ _cairo_ps_surface_stroke (void *abstract_surface,
* can modify some of the values.
*/
if (num_dashes % 2) {
dash = malloc (2 * num_dashes * sizeof (double));
dash = _cairo_malloc_abc (num_dashes, 2, sizeof (double));
if (dash == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -2200,7 +2194,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
unsigned int current_subset_id = -1;
unsigned int font_id;
cairo_scaled_font_subsets_glyph_t subset_glyph;
cairo_ps_glyph_id_t *glyph_ids;
cairo_status_t status;
unsigned int num_glyphs_unsigned, i, j, last, end;
@ -2221,18 +2215,18 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
num_glyphs_unsigned = num_glyphs;
_cairo_ps_surface_emit_pattern (surface, source);
glyph_ids = malloc (num_glyphs_unsigned*sizeof (cairo_ps_glyph_id_t));
glyph_ids = _cairo_malloc_ab (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,
&font_id,
&(glyph_ids[i].subset_id),
&(glyph_ids[i].glyph_id));
&subset_glyph);
if (status)
goto fail;
glyph_ids[i].subset_id = subset_glyph.subset_id;
glyph_ids[i].glyph_id = subset_glyph.subset_glyph_index;
}
i = 0;
@ -2242,7 +2236,7 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
"/CairoFont-%d-%d findfont\n"
"[ %f %f %f %f 0 0 ] makefont\n"
"setfont\n",
font_id,
subset_glyph.font_id,
glyph_ids[i].subset_id,
scaled_font->scale.xx,
scaled_font->scale.yx,

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

@ -1,54 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_PS_TEST_H
#define CAIRO_PS_TEST_H
#include <cairo.h>
#if CAIRO_HAS_PS_SURFACE
#include <cairo-ps.h>
CAIRO_BEGIN_DECLS
cairo_public void
_cairo_ps_test_force_fallbacks (void);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_PS_SURFACE */
#endif /* CAIRO_PS_TEST_H */

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

@ -51,13 +51,16 @@ typedef struct cairo_quartz_surface {
CGContextRef cgContext;
CGAffineTransform cgContextBaseCTM;
cairo_rectangle_int16_t extents;
cairo_rectangle_int_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,47 +101,24 @@ static void quartz_image_to_png (CGImageRef, char *dest);
* Cairo path -> Quartz path conversion helpers
*/
/* cairo path -> mutable path */
static cairo_status_t
_cairo_path_to_quartz_path_move_to (void *closure, cairo_point_t *point)
{
CGPathMoveToPoint ((CGMutablePathRef) closure, NULL,
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_path_to_quartz_path_line_to (void *closure, cairo_point_t *point)
{
CGPathAddLineToPoint ((CGMutablePathRef) closure, NULL,
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_path_to_quartz_path_curve_to (void *closure, cairo_point_t *p0, cairo_point_t *p1, cairo_point_t *p2)
{
CGPathAddCurveToPoint ((CGMutablePathRef) closure, NULL,
_cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
_cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
_cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_path_to_quartz_path_close_path (void *closure)
{
CGPathCloseSubpath ((CGMutablePathRef) closure);
return CAIRO_STATUS_SUCCESS;
}
typedef struct _quartz_stroke {
CGContextRef cgContext;
cairo_matrix_t *ctm_inverse;
} quartz_stroke_t;
/* cairo path -> execute in context */
static cairo_status_t
_cairo_path_to_quartz_context_move_to (void *closure, cairo_point_t *point)
{
//ND((stderr, "moveto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
CGContextMoveToPoint ((CGContextRef) closure,
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
if (stroke->ctm_inverse)
cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
CGContextMoveToPoint (stroke->cgContext, x, y);
return CAIRO_STATUS_SUCCESS;
}
@ -149,12 +126,17 @@ static cairo_status_t
_cairo_path_to_quartz_context_line_to (void *closure, cairo_point_t *point)
{
//ND((stderr, "lineto: %f %f\n", _cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y)));
if (CGContextIsPathEmpty ((CGContextRef) closure))
CGContextMoveToPoint ((CGContextRef) closure,
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
if (stroke->ctm_inverse)
cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
if (CGContextIsPathEmpty (stroke->cgContext))
CGContextMoveToPoint (stroke->cgContext, x, y);
else
CGContextAddLineToPoint ((CGContextRef) closure,
_cairo_fixed_to_double(point->x), _cairo_fixed_to_double(point->y));
CGContextAddLineToPoint (stroke->cgContext, x, y);
return CAIRO_STATUS_SUCCESS;
}
@ -165,11 +147,22 @@ _cairo_path_to_quartz_context_curve_to (void *closure, cairo_point_t *p0, cairo_
// _cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
// _cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
// _cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y)));
quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
double x0 = _cairo_fixed_to_double (p0->x);
double y0 = _cairo_fixed_to_double (p0->y);
double x1 = _cairo_fixed_to_double (p1->x);
double y1 = _cairo_fixed_to_double (p1->y);
double x2 = _cairo_fixed_to_double (p2->x);
double y2 = _cairo_fixed_to_double (p2->y);
CGContextAddCurveToPoint ((CGContextRef) closure,
_cairo_fixed_to_double(p0->x), _cairo_fixed_to_double(p0->y),
_cairo_fixed_to_double(p1->x), _cairo_fixed_to_double(p1->y),
_cairo_fixed_to_double(p2->x), _cairo_fixed_to_double(p2->y));
if (stroke->ctm_inverse) {
cairo_matrix_transform_point (stroke->ctm_inverse, &x0, &y0);
cairo_matrix_transform_point (stroke->ctm_inverse, &x1, &y1);
cairo_matrix_transform_point (stroke->ctm_inverse, &x2, &y2);
}
CGContextAddCurveToPoint (stroke->cgContext,
x0, y0, x1, y1, x2, y2);
return CAIRO_STATUS_SUCCESS;
}
@ -177,26 +170,14 @@ static cairo_status_t
_cairo_path_to_quartz_context_close_path (void *closure)
{
//ND((stderr, "closepath\n"));
CGContextClosePath ((CGContextRef) closure);
quartz_stroke_t *stroke = (quartz_stroke_t *)closure;
CGContextClosePath (stroke->cgContext);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_quartz_cairo_path_to_quartz_path (cairo_path_fixed_t *path,
CGMutablePathRef cgPath)
{
return _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_path_to_quartz_path_move_to,
_cairo_path_to_quartz_path_line_to,
_cairo_path_to_quartz_path_curve_to,
_cairo_path_to_quartz_path_close_path,
cgPath);
}
static cairo_status_t
_cairo_quartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path,
CGContextRef cgc)
quartz_stroke_t *stroke)
{
return _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
@ -204,7 +185,7 @@ _cairo_quartz_cairo_path_to_quartz_context (cairo_path_fixed_t *path,
_cairo_path_to_quartz_context_line_to,
_cairo_path_to_quartz_context_curve_to,
_cairo_path_to_quartz_context_close_path,
cgc);
stroke);
}
/*
@ -286,8 +267,8 @@ _cairo_quartz_cairo_matrix_to_quartz (const cairo_matrix_t *src,
CGAffineTransform *dst)
{
dst->a = src->xx;
dst->b = src->xy;
dst->c = src->yx;
dst->b = src->yx;
dst->c = src->xy;
dst->d = src->yy;
dst->tx = src->x0;
dst->ty = src->y0;
@ -301,7 +282,7 @@ static void
ComputeGradientValue (void *info, const float *in, float *out)
{
float fdist = *in; /* 0.0 .. 1.0 */
cairo_fixed_16_16_t fdist_fix = _cairo_fixed_from_double(*in);
cairo_fixed_t fdist_fix = _cairo_fixed_from_double(*in);
cairo_gradient_pattern_t *grad = (cairo_gradient_pattern_t*) info;
unsigned int i;
@ -365,6 +346,13 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
abspat->type != CAIRO_PATTERN_TYPE_RADIAL)
return NULL;
/* bandaid for mozilla bug 379321, also visible in the
* linear-gradient-reflect test.
*/
if (abspat->extend == CAIRO_EXTEND_REFLECT ||
abspat->extend == CAIRO_EXTEND_REPEAT)
return NULL;
/* We can only do this if we have an identity pattern matrix;
* otherwise fall back through to the generic pattern case.
* XXXperf we could optimize this by creating a pattern with the shading;
@ -386,10 +374,10 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
CGFunctionRef gradFunc;
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
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);
start = CGPointMake (_cairo_fixed_to_double (lpat->p1.x) - x0,
_cairo_fixed_to_double (lpat->p1.y) - y0);
end = CGPointMake (_cairo_fixed_to_double (lpat->p2.x) - x0,
_cairo_fixed_to_double (lpat->p2.y) - y0);
cairo_pattern_reference (abspat);
gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) lpat);
@ -410,18 +398,18 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
CGFunctionRef gradFunc;
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
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);
start = CGPointMake (_cairo_fixed_to_double (rpat->c1.x) - x0,
_cairo_fixed_to_double (rpat->c1.y) - y0);
end = CGPointMake (_cairo_fixed_to_double (rpat->c2.x) - x0,
_cairo_fixed_to_double (rpat->c2.y) - y0);
cairo_pattern_reference (abspat);
gradFunc = CreateGradientFunction ((cairo_gradient_pattern_t*) rpat);
shading = CGShadingCreateRadial (rgb,
start,
_cairo_fixed_to_double (rpat->gradient.c1.radius),
_cairo_fixed_to_double (rpat->r1),
end,
_cairo_fixed_to_double (rpat->gradient.c2.radius),
_cairo_fixed_to_double (rpat->r2),
gradFunc,
true, true);
CGColorSpaceRelease(rgb);
@ -435,38 +423,30 @@ _cairo_quartz_cairo_gradient_pattern_to_quartz (cairo_pattern_t *abspat)
return NULL;
}
/* Generic cairo_pattern -> CGPattern function */
static void
SurfacePatternDrawFunc (void *info, CGContextRef context)
/* generic cairo surface -> cairo_quartz_surface_t function */
static cairo_quartz_surface_t *
_cairo_quartz_surface_to_quartz (cairo_surface_t *target, cairo_surface_t *pat_surf)
{
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
cairo_surface_t *pat_surf = spat->surface;
cairo_quartz_surface_t *quartz_surf = NULL;
cairo_bool_t flip = FALSE;
CGImageRef img;
if (cairo_surface_get_type(pat_surf) != CAIRO_SURFACE_TYPE_QUARTZ) {
/* This sucks; we should really store a dummy quartz surface
* for passing in here
* XXXtodo store a dummy quartz surface somewhere for handing off to clone_similar
* XXXtodo/perf don't use clone if the source surface is an image surface! Instead,
/* XXXtodo/perf don't use clone if the source surface is an image surface! Instead,
* just create the CGImage directly!
*/
cairo_surface_t *dummy = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
cairo_surface_t *ref_type = target;
cairo_surface_t *new_surf = NULL;
cairo_rectangle_int16_t rect;
cairo_rectangle_int_t rect;
if (ref_type == NULL)
ref_type = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
_cairo_surface_get_extents (pat_surf, &rect);
_cairo_surface_clone_similar (dummy, pat_surf, rect.x, rect.y,
_cairo_surface_clone_similar (ref_type, pat_surf, rect.x, rect.y,
rect.width, rect.height, &new_surf);
cairo_surface_destroy(dummy);
if (target == NULL)
cairo_surface_destroy(ref_type);
quartz_surf = (cairo_quartz_surface_t *) new_surf;
} else {
@ -476,15 +456,21 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
cairo_surface_reference (pat_surf);
quartz_surf = (cairo_quartz_surface_t*) pat_surf;
/* XXXtodo WHY does this need to be flipped? Writing this stuff
* to disk shows that in both this path and the path above the source image
* has an identical orientation, and the destination context at all times has a Y
* flip. So why do we need to flip in this case?
*/
flip = TRUE;
}
img = CGBitmapContextCreateImage (quartz_surf->cgContext);
return quartz_surf;
}
/* Generic cairo_pattern -> CGPattern function */
static void
SurfacePatternDrawFunc (void *info, CGContextRef context)
{
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) info;
cairo_surface_t *pat_surf = spat->surface;
cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz (NULL, pat_surf);
CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
CGRect imageBounds;
if (!img) {
// ... give up.
@ -493,17 +479,33 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
return;
}
if (flip) {
/* XXXtodo WHY does this need to be flipped? Writing this stuff
* to disk shows that in both this path and the path above the source image
* has an identical orientation, and the destination context at all times has a Y
* flip. So why do we need to flip in this case?
*/
if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
CGContextTranslateCTM (context, 0, CGImageGetHeight(img));
CGContextScaleCTM (context, 1, -1);
}
CGRect imageBounds;
imageBounds.size = CGSizeMake (CGImageGetWidth(img), CGImageGetHeight(img));
imageBounds.origin.x = 0;
imageBounds.origin.y = 0;
CGContextDrawImage (context, imageBounds, img);
if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
/* draw 3 more copies of the image, flipped. */
CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
CGContextScaleCTM (context, 1, -1);
CGContextDrawImage (context, imageBounds, img);
CGContextTranslateCTM (context, 2 * imageBounds.size.width, 0);
CGContextScaleCTM (context, -1, 1);
CGContextDrawImage (context, imageBounds, img);
CGContextTranslateCTM (context, 0, 2 * imageBounds.size.height);
CGContextScaleCTM (context, 1, -1);
CGContextDrawImage (context, imageBounds, img);
}
CGImageRelease (img);
@ -515,7 +517,11 @@ static cairo_status_t
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
_cairo_pattern_init_copy (pattern, other);
cairo_status_t status;
status = _cairo_pattern_init_copy (pattern, other);
if (status)
return status;
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern =
@ -539,7 +545,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_int16_t extents;
cairo_rectangle_int_t extents;
CGRect pbounds;
CGAffineTransform ptransform, stransform;
@ -563,8 +569,24 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
_cairo_surface_get_extents (pat_surf, &extents);
pbounds.origin.x = 0;
pbounds.origin.y = 0;
pbounds.size.width = extents.width;
pbounds.size.height = extents.height;
// kjs seems to indicate this should work (setting to 0,0 to avoid
// tiling); however, the pattern CTM scaling ends up being NaN in
// the pattern draw function if either rw or rh are 0.
// XXXtodo get pattern drawing working with extend options
// XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
/* XXX broken; need to emulate by reflecting the image into 4 quadrants
* and then tiling that
*/
pbounds.size.width = 2 * extents.width;
pbounds.size.height = 2 * extents.height;
} else {
pbounds.size.width = extents.width;
pbounds.size.height = extents.height;
}
rw = pbounds.size.width;
rh = pbounds.size.height;
m = spat->base.matrix;
cairo_matrix_invert(&m);
@ -584,38 +606,6 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
ND((stderr, " context xform: t: %f %f xx: %f xy: %f yx: %f yy: %f\n", xform.tx, xform.ty, xform.a, xform.b, xform.c, xform.d));
#endif
// kjs seems to indicate this should work (setting to 0,0 to avoid
// tiling); however, the pattern CTM scaling ends up being NaN in
// the pattern draw function if either rw or rh are 0.
// XXXtodo get pattern drawing working with extend options
// XXXtodo/perf optimize CAIRO_EXTEND_NONE to a single DrawImage instead of a pattern
#if 0
if (spat->base.extend == CAIRO_EXTEND_NONE) {
/* XXX wasteful; this will keep drawing the pattern in the
* original location. We need to set up the clip region
* instead to do this right.
*/
rw = 0;
rh = 0;
} else if (spat->base.extend == CAIRO_EXTEND_REPEAT) {
rw = extents.width;
rh = extents.height;
} else if (spat->base.extend == CAIRO_EXTEND_REFLECT) {
/* XXX broken; need to emulate by reflecting the image into 4 quadrants
* and then tiling that
*/
rw = extents.width;
rh = extents.height;
} else {
/* CAIRO_EXTEND_PAD */
/* XXX broken. */
rw = 0;
rh = 0;
}
#else
rw = extents.width;
rh = extents.height;
#endif
/* XXX fixme: only do snapshots if the context is for printing, or get rid of the
other block if it doesn't fafect performance */
@ -642,12 +632,13 @@ typedef enum {
DO_SOLID,
DO_SHADING,
DO_PATTERN,
DO_IMAGE,
DO_UNSUPPORTED
} cairo_quartz_action_t;
static cairo_quartz_action_t
_cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
cairo_pattern_t *source)
cairo_pattern_t *source)
{
assert (!(surface->sourceImage || surface->sourceShading || surface->sourcePattern));
@ -676,19 +667,44 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
surface->sourceShading = shading;
return DO_SHADING;
} else if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
source->extend == CAIRO_EXTEND_NONE)
{
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t *) source;
cairo_surface_t *pat_surf = spat->surface;
cairo_quartz_surface_t *quartz_surf = _cairo_quartz_surface_to_quartz ((cairo_surface_t *) surface, pat_surf);
CGImageRef img = CGBitmapContextCreateImage (quartz_surf->cgContext);
cairo_matrix_t m = spat->base.matrix;
cairo_rectangle_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);
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetFillColorSpace (surface->cgContext, patternSpace);
CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
CGContextSetStrokeColorSpace (surface->cgContext, patternSpace);
@ -716,7 +732,11 @@ _cairo_quartz_teardown_source (cairo_quartz_surface_t *surface,
cairo_pattern_t *source)
{
if (surface->sourceImage) {
// nothing to do; we don't use sourceImage yet
CGImageRelease(surface->sourceImage);
surface->sourceImage = NULL;
cairo_surface_destroy(surface->sourceImageSurface);
surface->sourceImageSurface = NULL;
}
if (surface->sourceShading) {
@ -865,12 +885,21 @@ _cairo_quartz_surface_acquire_source_image (void *abstract_surface,
return _cairo_quartz_get_image (surface, image_out, NULL);
}
static void
_cairo_quartz_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra)
{
cairo_surface_destroy ((cairo_surface_t *) image);
}
static cairo_status_t
_cairo_quartz_surface_acquire_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect,
void **image_extra)
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *image_rect,
void **image_extra)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t status;
@ -891,10 +920,10 @@ _cairo_quartz_surface_acquire_dest_image (void *abstract_surface,
static void
_cairo_quartz_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
void *image_extra)
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
unsigned char *imageData = (unsigned char *) image_extra;
@ -965,7 +994,6 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
int height,
cairo_surface_t **clone_out)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_quartz_surface_t *new_surface = NULL;
cairo_format_t new_format;
@ -1052,7 +1080,7 @@ _cairo_quartz_surface_clone_similar (void *abstract_surface,
static cairo_int_status_t
_cairo_quartz_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *extents)
cairo_rectangle_int_t *extents)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
@ -1086,6 +1114,19 @@ _cairo_quartz_surface_paint (void *abstract_surface,
surface->extents.height));
} else if (action == DO_SHADING) {
CGContextDrawShading (surface->cgContext, surface->sourceShading);
} else if (action == DO_IMAGE) {
cairo_surface_pattern_t *surface_pattern =
(cairo_surface_pattern_t *) source;
cairo_surface_t *pat_surf = surface_pattern->surface;
CGContextSaveGState (surface->cgContext);
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
CGContextScaleCTM (surface->cgContext, 1, -1);
}
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
CGContextRestoreGState (surface->cgContext);
} else {
rv = CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -1108,6 +1149,7 @@ _cairo_quartz_surface_fill (void *abstract_surface,
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
cairo_quartz_action_t action;
quartz_stroke_t stroke;
ND((stderr, "%p _cairo_quartz_surface_fill op %d source->type %d\n", surface, op, source->type));
@ -1126,7 +1168,10 @@ _cairo_quartz_surface_fill (void *abstract_surface,
}
CGContextBeginPath (surface->cgContext);
_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
stroke.cgContext = surface->cgContext;
stroke.ctm_inverse = NULL;
_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
if (action == DO_SOLID || action == DO_PATTERN) {
if (fill_rule == CAIRO_FILL_RULE_WINDING)
@ -1143,6 +1188,21 @@ _cairo_quartz_surface_fill (void *abstract_surface,
CGContextEOClip (surface->cgContext);
CGContextDrawShading (surface->cgContext, surface->sourceShading);
} else if (action == DO_IMAGE) {
cairo_surface_pattern_t *surface_pattern =
(cairo_surface_pattern_t *) source;
cairo_surface_t *pat_surf = surface_pattern->surface;
if (fill_rule == CAIRO_FILL_RULE_WINDING)
CGContextClip (surface->cgContext);
else
CGContextEOClip (surface->cgContext);
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
if (cairo_surface_get_type(pat_surf) == CAIRO_SURFACE_TYPE_QUARTZ) {
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
CGContextScaleCTM (surface->cgContext, 1, -1);
}
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
} else {
rv = CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -1169,6 +1229,8 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
cairo_quartz_action_t action;
quartz_stroke_t stroke;
CGAffineTransform strokeTransform;
ND((stderr, "%p _cairo_quartz_surface_stroke op %d source->type %d\n", surface, op, source->type));
@ -1184,6 +1246,8 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
CGContextSetLineCap (surface->cgContext, _cairo_quartz_cairo_line_cap_to_quartz (style->line_cap));
CGContextSetLineJoin (surface->cgContext, _cairo_quartz_cairo_line_join_to_quartz (style->line_join));
CGContextSetMiterLimit (surface->cgContext, style->miter_limit);
_cairo_quartz_cairo_matrix_to_quartz (ctm, &strokeTransform);
CGContextConcatCTM (surface->cgContext, strokeTransform);
if (style->dash && style->num_dashes) {
#define STATIC_DASH 32
@ -1191,7 +1255,7 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
float *fdash = sdash;
unsigned int k;
if (style->num_dashes > STATIC_DASH)
fdash = malloc (sizeof(float)*style->num_dashes);
fdash = _cairo_malloc_ab (style->num_dashes, sizeof (float));
for (k = 0; k < style->num_dashes; k++)
fdash[k] = (float) style->dash[k];
@ -1211,13 +1275,25 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
}
CGContextBeginPath (surface->cgContext);
_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
stroke.cgContext = surface->cgContext;
stroke.ctm_inverse = ctm_inverse;
_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
if (action == DO_SOLID || action == DO_PATTERN) {
CGContextStrokePath (surface->cgContext);
} else if (action == DO_IMAGE) {
CGContextReplacePathWithStrokedPath (surface->cgContext);
CGContextClip (surface->cgContext);
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
CGContextScaleCTM (surface->cgContext, 1, -1);
}
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
} else if (action == DO_SHADING) {
// we have to clip and then paint the shading; first we have to convert
// the stroke to a path that we can fill
CGContextReplacePathWithStrokedPath (surface->cgContext);
CGContextClip (surface->cgContext);
@ -1243,9 +1319,21 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
int num_glyphs,
cairo_scaled_font_t *scaled_font)
{
ATSUFontID fid;
ATSFontRef atsfref;
CGFontRef cgfref;
CGAffineTransform cairoTextTransform, textTransform, ctm;
// XXXtodo/perf: stack storage for glyphs/sizes
#define STATIC_BUF_SIZE 64
CGGlyph glyphs_static[STATIC_BUF_SIZE];
CGSize cg_advances_static[STATIC_BUF_SIZE];
CGGlyph *cg_glyphs = &glyphs_static[0];
CGSize *cg_advances = &cg_advances_static[0];
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
cairo_quartz_action_t action;
float xprev, yprev;
int i;
if (num_glyphs <= 0)
@ -1262,7 +1350,7 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
action = _cairo_quartz_setup_source (surface, source);
if (action == DO_SOLID || action == DO_PATTERN) {
CGContextSetTextDrawingMode (surface->cgContext, kCGTextFill);
} else if (action == DO_SHADING) {
} else if (action == DO_IMAGE || action == DO_SHADING) {
CGContextSetTextDrawingMode (surface->cgContext, kCGTextClip);
} else {
/* Unsupported */
@ -1272,9 +1360,9 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op));
ATSUFontID fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font);
ATSFontRef atsfref = FMGetATSFontRefFromFont (fid);
CGFontRef cgfref = CGFontCreateWithPlatformFont (&atsfref);
fid = _cairo_atsui_scaled_font_get_atsu_font_id (scaled_font);
atsfref = FMGetATSFontRefFromFont (fid);
cgfref = CGFontCreateWithPlatformFont (&atsfref);
CGContextSetFont (surface->cgContext, cgfref);
CGFontRelease (cgfref);
@ -1285,8 +1373,11 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
* text matrix?
*/
//ND((stderr, "show_glyphs: glyph 0 at: %f, %f\n", glyphs[0].x, glyphs[0].y));
CGAffineTransform cairoTextTransform, textTransform, ctm;
_cairo_quartz_cairo_matrix_to_quartz (&scaled_font->font_matrix, &cairoTextTransform);
cairoTextTransform = CGAffineTransformMake (scaled_font->font_matrix.xx,
scaled_font->font_matrix.yx,
scaled_font->font_matrix.xy,
scaled_font->font_matrix.yy,
0., 0.);
textTransform = CGAffineTransformMakeTranslation (glyphs[0].x, glyphs[0].y);
textTransform = CGAffineTransformScale (textTransform, 1.0, -1.0);
@ -1302,51 +1393,27 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
CGContextSetTextMatrix (surface->cgContext, textTransform);
CGContextSetFontSize (surface->cgContext, 1.0);
// XXXtodo/perf: stack storage for glyphs/sizes
#define STATIC_BUF_SIZE 64
CGGlyph glyphs_static[STATIC_BUF_SIZE];
CGSize cg_advances_static[STATIC_BUF_SIZE];
CGGlyph *cg_glyphs = &glyphs_static[0];
CGSize *cg_advances = &cg_advances_static[0];
if (num_glyphs > STATIC_BUF_SIZE) {
cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs);
cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs);
cg_glyphs = (CGGlyph*) _cairo_malloc_ab (num_glyphs, sizeof(CGGlyph));
cg_advances = (CGSize*) _cairo_malloc_ab (num_glyphs, sizeof(CGSize));
}
#ifndef MOZILLA_CAIRO_NOT_DEFINED
float xprev = glyphs[0].x;
float yprev = glyphs[0].y;
xprev = glyphs[0].x;
yprev = glyphs[0].y;
cg_glyphs[0] = glyphs[0].index;
cg_advances[0].width = 0;
cg_advances[0].height = 0;
for (i = 1; i < num_glyphs; i++) {
float xf = glyphs[i].x;
float yf = glyphs[i].y;
cg_glyphs[i] = glyphs[i].index;
float xf = glyphs[i].x;
float yf = glyphs[i].y;
cg_advances[i-1].width = xf - xprev;
cg_advances[i-1].height = yf - yprev;
xprev = xf;
yprev = yf;
}
#else
double xprev = glyphs[0].x;
double yprev = glyphs[0].y;
cg_glyphs[0] = glyphs[0].index;
cg_advances[0].width = 0;
cg_advances[0].height = 0;
for (i = 1; i < num_glyphs; i++) {
cg_glyphs[i] = glyphs[i].index;
cg_advances[i-1].width = glyphs[i].x - xprev;
cg_advances[i-1].height = glyphs[i].y - yprev;
xprev = glyphs[i].x;
yprev = glyphs[i].y;
}
#endif /* MOZCAIRO */
#if 0
for (i = 0; i < num_glyphs; i++) {
@ -1364,8 +1431,17 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
free (cg_advances);
}
if (action == DO_SHADING)
if (action == DO_IMAGE) {
CGContextConcatCTM (surface->cgContext, surface->sourceImageTransform);
if (cairo_surface_get_type(((cairo_surface_pattern_t*)source)->surface) == CAIRO_SURFACE_TYPE_QUARTZ) {
CGContextTranslateCTM (surface->cgContext, 0, CGImageGetHeight(surface->sourceImage));
CGContextScaleCTM (surface->cgContext, 1, -1);
}
CGContextDrawImage (surface->cgContext, surface->sourceImageRect, surface->sourceImage);
} else if (action == DO_SHADING) {
CGContextDrawShading (surface->cgContext, surface->sourceShading);
}
_cairo_quartz_teardown_source (surface, source);
@ -1421,6 +1497,7 @@ _cairo_quartz_surface_intersect_clip_path (void *abstract_surface,
cairo_antialias_t antialias)
{
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
quartz_stroke_t stroke;
ND((stderr, "%p _cairo_quartz_surface_intersect_clip_path path: %p\n", surface, path));
@ -1436,7 +1513,9 @@ _cairo_quartz_surface_intersect_clip_path (void *abstract_surface,
CGContextSaveGState (surface->cgContext);
} else {
CGContextBeginPath (surface->cgContext);
_cairo_quartz_cairo_path_to_quartz_context (path, surface->cgContext);
stroke.cgContext = surface->cgContext;
stroke.ctm_inverse = NULL;
_cairo_quartz_cairo_path_to_quartz_context (path, &stroke);
if (fill_rule == CAIRO_FILL_RULE_WINDING)
CGContextClip (surface->cgContext);
else
@ -1455,7 +1534,7 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
_cairo_quartz_surface_create_similar,
_cairo_quartz_surface_finish,
_cairo_quartz_surface_acquire_source_image,
NULL, /* release_source_image */
_cairo_quartz_surface_release_source_image,
_cairo_quartz_surface_acquire_dest_image,
_cairo_quartz_surface_release_dest_image,
_cairo_quartz_surface_clone_similar,
@ -1632,7 +1711,7 @@ cairo_quartz_surface_create (cairo_format_t format,
return (cairo_surface_t*) &_cairo_surface_nil;
}
imageData = malloc (height * stride);
imageData = _cairo_malloc_ab (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_int16_t is
* corners, expressed in fixed point numbers. A cairo_rectangle_int_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_int16_t by
* This function converts a cairo_box_t to a cairo_rectangle_int_t by
* increasing the area to the nearest integer coordinates. We should
* standardize on cairo_rectangle_int16_t and cairo_rectangle_int16_t, and
* standardize on cairo_rectangle_fixed_t and cairo_rectangle_int_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_int16_t *rectangle)
_cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_int_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_int16_t *rectan
}
void
_cairo_rectangle_intersect (cairo_rectangle_int16_t *dest, cairo_rectangle_int16_t *src)
_cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *src)
{
int x1, y1, x2, y2;

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

@ -1,3 +1,4 @@
/* -*- 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.
@ -31,52 +32,178 @@
*
* Contributor(s):
* Owen Taylor <otaylor@redhat.com>
* Vladimir Vukicevic <vladimir@pobox.com>
*/
#include <cairoint.h>
#include "cairoint.h"
/**
* _cairo_region_create_from_rectangle:
* @rect: a #cairo_rectangle_int16_t
*
* Creates a region with extents initialized from the given
* rectangle.
*
* Return value: a newly created #pixman_region16_t or %NULL if
* memory couldn't a allocated.
**/
pixman_region16_t *
_cairo_region_create_from_rectangle (cairo_rectangle_int16_t *rect)
void
_cairo_region_init (cairo_region_t *region)
{
/* 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;
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;
}
return region;
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);
}
/**
* _cairo_region_extents_rectangle:
* @region: a #pixman_region16_t
* _cairo_region_get_extents:
* @region: a #cairo_region_t
* @rect: rectangle into which to store the extents
*
* Gets the bounding box of a region as a cairo_rectangle_int16_t
* Gets the bounding box of a region as a cairo_rectangle_int_t
**/
void
_cairo_region_extents_rectangle (pixman_region16_t *region,
cairo_rectangle_int16_t *rect)
_cairo_region_get_extents (cairo_region_t *region, cairo_rectangle_int_t *extents)
{
pixman_box16_t *region_extents = pixman_region_extents (region);
pixman_box16_t *pextents = pixman_region_extents (&region->rgn);
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;
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);
}

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

@ -39,19 +39,17 @@
#include "cairoint.h"
typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
typedef struct _cairo_scaled_font_subsets_glyph {
unsigned int font_id;
unsigned int subset_id;
unsigned int subset_glyph_index;
cairo_bool_t is_scaled;
cairo_bool_t is_composite;
double x_advance;
} cairo_scaled_font_subsets_glyph_t;
/**
* _cairo_scaled_font_subsets_create:
*
* @max_glyphs_per_unscaled_subset: the maximum number of glyphs that
* should appear in any unscaled subset. A value of 0 indicates that
* no unscaled subset will be created. All glyphs will mapped to
* scaled subsets.
*
* @max_glyphs_per_scaled_subset: the maximum number of glyphs that
* should appear in any scaled subset. A value of 0 indicates that
* no scaled subset will be created.
* _cairo_scaled_font_subsets_create_scaled:
*
* Create a new #cairo_scaled_font_subsets_t object which can be used
* to create subsets of any number of cairo_scaled_font_t
@ -60,16 +58,57 @@ typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
* subsets with glyph indices packed into the range
* [0 .. max_glyphs_per_subset).
*
* @max_glyphs_per_unscaled_subset and @max_glyphs_per_scaled_subset
* cannot both be 0.
* Return value: a pointer to the newly creates font subsets. The
* caller owns this object and should call
* _cairo_scaled_font_subsets_destroy() when done with it.
**/
cairo_private cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create_scaled (void);
/**
* _cairo_scaled_font_subsets_create_simple:
*
* Create a new #cairo_scaled_font_subsets_t object which can be used
* to create font subsets suitable for embedding as Postscript or PDF
* simple fonts.
*
* Glyphs with an outline path available will be mapped to one font
* subset for each font face. Glyphs from bitmap fonts will mapped to
* separate font subsets for each cairo_scaled_font_t object.
*
* The maximum number of glyphs per subset is 256. Each subset
* reserves the first glyph for the .notdef glyph.
*
* Return value: a pointer to the newly creates font subsets. The
* caller owns this object and should call
* _cairo_scaled_font_subsets_destroy() when done with it.
**/
cairo_private cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create (int max_glyphs_unscaled_per_subset,
int max_glyphs_scaled_per_subset);
_cairo_scaled_font_subsets_create_simple (void);
/**
* _cairo_scaled_font_subsets_create_composite:
*
* Create a new #cairo_scaled_font_subsets_t object which can be used
* to create font subsets suitable for embedding as Postscript or PDF
* composite fonts.
*
* Glyphs with an outline path available will be mapped to one font
* subset for each font face. Each unscaled subset has a maximum of
* 65536 glyphs except for Type1 fonts which have a maximum of 256 glyphs.
*
* Glyphs from bitmap fonts will mapped to separate font subsets for
* each cairo_scaled_font_t object. Each unscaled subset has a maximum
* of 256 glyphs.
*
* Each subset reserves the first glyph for the .notdef glyph.
*
* Return value: a pointer to the newly creates font subsets. The
* caller owns this object and should call
* _cairo_scaled_font_subsets_destroy() when done with it.
**/
cairo_private cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create_composite (void);
/**
* _cairo_scaled_font_subsets_destroy:
@ -85,6 +124,8 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
* @font_subsets: a #cairo_scaled_font_subsets_t
* @scaled_font: the font of the glyph to be mapped
* @scaled_font_glyph_index: the index of the glyph to be mapped
* @subset_glyph_ret: return structure containing subset font and glyph id
*
* @font_id_ret: return value giving the font ID of the mapped glyph
* @subset_id_ret: return value giving the subset ID of the mapped glyph within the @font_id_ret
* @subset_glyph_index_ret: return value giving the index of the mapped glyph within the @subset_id_ret subset
@ -126,6 +167,17 @@ _cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *font_subsets);
* used by #cairo_scaled_font_subset_t as provided by
* _cairo_scaled_font_subsets_foreach.
*
* The returned values in the cairo_scaled_font_subsets_glyph_t struct are:
*
* @font_id: The font ID of the mapped glyph
* @subset_id : The subset ID of the mapped glyph within the @font_id
* @subset_glyph_index: The index of the mapped glyph within the @subset_id subset
* @is_scaled: If true, the mapped glyph is from a bitmap font, and separate font
* subset is created for each font scale used. If false, the outline of the mapped glyph
* is available. One font subset for each font face is created.
* @x_advance: When @is_scaled is true, @x_advance contains the x_advance for the mapped glyph in device space.
* When @is_scaled is false, @x_advance contains the x_advance for the the mapped glyph from an unhinted 1 point font.
*
* Return value: CAIRO_STATUS_SUCCESS if successful, or a non-zero
* value indicating an error. Possible errors include
* CAIRO_STATUS_NO_MEMORY.
@ -134,9 +186,7 @@ cairo_private cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
unsigned int *font_id_ret,
unsigned int *subset_id_ret,
unsigned int *subset_glyph_index_ret);
cairo_scaled_font_subsets_glyph_t *subset_glyph_ret);
typedef void
(*cairo_scaled_font_subset_callback_func_t) (cairo_scaled_font_subset_t *font_subset,
@ -253,6 +303,37 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
cairo_private void
_cairo_cff_subset_fini (cairo_cff_subset_t *cff_subset);
/**
* _cairo_cff_fallback_init:
* @cff_subset: a #cairo_cff_subset_t to initialize
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
*
* If possible (depending on the format of the underlying
* cairo_scaled_font_t and the font backend in use) generate a cff
* file corresponding to @font_subset and initialize @cff_subset
* with information about the subset and the cff data.
*
* Return value: CAIRO_STATUS_SUCCESS if successful,
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a
* cff file, or an non-zero value indicating an error. Possible
* errors include CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
const char *name,
cairo_scaled_font_subset_t *font_subset);
/**
* _cairo_cff_fallback_fini:
* @cff_subset: a #cairo_cff_subset_t
*
* Free all resources associated with @cff_subset. After this
* call, @cff_subset should not be used again without a
* subsequent call to _cairo_cff_subset_init() again first.
**/
cairo_private void
_cairo_cff_fallback_fini (cairo_cff_subset_t *cff_subset);
typedef struct _cairo_truetype_subset {
char *base_font;
double *widths;
@ -341,6 +422,15 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type_subset,
cairo_private void
_cairo_type1_subset_fini (cairo_type1_subset_t *subset);
/**
* _cairo_type1_scaled_font_is_type1:
* @scaled_font: a #cairo_scaled_font_t
*
* Return TRUE if @scaled_font is a Type 1 font, otherwise return FALSE.
**/
cairo_private cairo_bool_t
_cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font);
/**
* _cairo_type1_fallback_init_binary:
* @type1_subset: a #cairo_type1_subset_t to initialize
@ -394,6 +484,43 @@ _cairo_type1_fallback_init_hex (cairo_type1_subset_t *type_subset,
cairo_private void
_cairo_type1_fallback_fini (cairo_type1_subset_t *subset);
typedef struct _cairo_type2_charstrings {
int *widths;
long x_min, y_min, x_max, y_max;
long ascent, descent;
cairo_array_t charstrings;
} cairo_type2_charstrings_t;
/**
* _cairo_type2_charstrings_init:
* @type2_subset: a #cairo_type2_subset_t to initialize
* @font_subset: the #cairo_scaled_font_subset_t to initialize from
*
* If possible (depending on the format of the underlying
* cairo_scaled_font_t and the font backend in use) generate type2
* charstrings to @font_subset and initialize @type2_subset
* with information about the subset.
*
* Return value: CAIRO_STATUS_SUCCESS if successful,
* CAIRO_INT_STATUS_UNSUPPORTED if the font can't be subset as a type2
* charstrings, or an non-zero value indicating an error. Possible errors
* include CAIRO_STATUS_NO_MEMORY.
**/
cairo_private cairo_status_t
_cairo_type2_charstrings_init (cairo_type2_charstrings_t *charstrings,
cairo_scaled_font_subset_t *font_subset);
/**
* _cairo_type2_charstrings_fini:
* @subset: a #cairo_type2_charstrings_t
*
* Free all resources associated with @type2_charstring. After this call,
* @type2_charstring should not be used again without a subsequent call to
* _cairo_type2_charstring_init() again first.
**/
cairo_private void
_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *charstrings);
/**
* _cairo_truetype_create_glyph_to_unicode_map:
* @font_subset: the #cairo_scaled_font_subset_t to initialize from

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

@ -42,12 +42,21 @@
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
#define MAX_GLYPHS_PER_SIMPLE_FONT 256
#define MAX_GLYPHS_PER_COMPOSITE_FONT 65536
typedef enum {
CAIRO_SUBSETS_SCALED,
CAIRO_SUBSETS_SIMPLE,
CAIRO_SUBSETS_COMPOSITE
} cairo_subsets_type_t;
struct _cairo_scaled_font_subsets {
int max_glyphs_per_unscaled_subset_limit;
cairo_subsets_type_t type;
int max_glyphs_per_unscaled_subset_used;
cairo_hash_table_t *unscaled_sub_fonts;
int max_glyphs_per_scaled_subset_limit;
int max_glyphs_per_scaled_subset_used;
cairo_hash_table_t *scaled_sub_fonts;
@ -58,6 +67,7 @@ typedef struct _cairo_sub_font {
cairo_hash_entry_t base;
cairo_bool_t is_scaled;
cairo_bool_t is_composite;
cairo_scaled_font_subsets_t *parent;
cairo_scaled_font_t *scaled_font;
unsigned int font_id;
@ -74,6 +84,7 @@ typedef struct _cairo_sub_font_glyph {
unsigned int subset_id;
unsigned int subset_glyph_index;
double x_advance;
} cairo_sub_font_glyph_t;
typedef struct _cairo_sub_font_collection {
@ -107,7 +118,8 @@ _cairo_sub_font_glyphs_equal (const void *key_a, const void *key_b)
static cairo_sub_font_glyph_t *
_cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
unsigned int subset_id,
unsigned int subset_glyph_index)
unsigned int subset_glyph_index,
double x_advance)
{
cairo_sub_font_glyph_t *sub_font_glyph;
@ -118,6 +130,7 @@ _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index,
_cairo_sub_font_glyph_init_key (sub_font_glyph, scaled_font_glyph_index);
sub_font_glyph->subset_id = subset_id;
sub_font_glyph->subset_glyph_index = subset_glyph_index;
sub_font_glyph->x_advance = x_advance;
return sub_font_glyph;
}
@ -195,7 +208,8 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
cairo_scaled_font_t *scaled_font,
unsigned int font_id,
int max_glyphs_per_subset,
cairo_bool_t is_scaled)
cairo_bool_t is_scaled,
cairo_bool_t is_composite)
{
cairo_sub_font_t *sub_font;
@ -204,10 +218,11 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
return NULL;
sub_font->is_scaled = is_scaled;
sub_font->is_composite = is_composite;
_cairo_sub_font_init_key (sub_font, scaled_font);
sub_font->parent = parent;
sub_font->scaled_font = cairo_scaled_font_reference (scaled_font);
sub_font->scaled_font = scaled_font;
sub_font->font_id = font_id;
sub_font->current_subset = 0;
@ -220,6 +235,11 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent,
return NULL;
}
if (parent->type != CAIRO_SUBSETS_SCALED) {
/* Reserve first glyph in subset for the .notdef glyph */
sub_font->num_glyphs_in_current_subset++;
}
return sub_font;
}
@ -245,10 +265,9 @@ _cairo_sub_font_pluck (void *entry, void *closure)
}
static cairo_status_t
_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
unsigned int *subset_id,
unsigned int *subset_glyph_index)
_cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
@ -256,8 +275,12 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
if (_cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
(cairo_hash_entry_t **) &sub_font_glyph))
{
*subset_id = sub_font_glyph->subset_id;
*subset_glyph_index = sub_font_glyph->subset_glyph_index;
subset_glyph->font_id = sub_font->font_id;
subset_glyph->subset_id = sub_font_glyph->subset_id;
subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
subset_glyph->is_scaled = sub_font->is_scaled;
subset_glyph->is_composite = sub_font->is_composite;
subset_glyph->x_advance = sub_font_glyph->x_advance;
return CAIRO_STATUS_SUCCESS;
}
@ -268,11 +291,11 @@ _cairo_sub_font_lookup_glyph (cairo_sub_font_t *sub_font,
static cairo_status_t
_cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
unsigned long scaled_font_glyph_index,
unsigned int *subset_id,
unsigned int *subset_glyph_index)
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_glyph_t key, *sub_font_glyph;
cairo_status_t status;
cairo_scaled_glyph_t *scaled_glyph;
_cairo_sub_font_glyph_init_key (&key, scaled_font_glyph_index);
if (! _cairo_hash_table_lookup (sub_font->sub_font_glyphs, &key.base,
@ -282,11 +305,24 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
{
sub_font->current_subset++;
sub_font->num_glyphs_in_current_subset = 0;
if (sub_font->parent->type != CAIRO_SUBSETS_SCALED) {
/* Reserve first glyph in subset for the .notdef glyph */
sub_font->num_glyphs_in_current_subset++;
}
}
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph);
if (status)
return status;
sub_font_glyph = _cairo_sub_font_glyph_create (scaled_font_glyph_index,
sub_font->current_subset,
sub_font->num_glyphs_in_current_subset++);
sub_font->num_glyphs_in_current_subset++,
scaled_glyph->metrics.x_advance);
if (sub_font_glyph == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -302,12 +338,18 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font,
}
status = _cairo_hash_table_insert (sub_font->sub_font_glyphs, &sub_font_glyph->base);
if (status)
if (status) {
_cairo_sub_font_glyph_destroy (sub_font_glyph);
return status;
}
}
*subset_id = sub_font_glyph->subset_id;
*subset_glyph_index = sub_font_glyph->subset_glyph_index;
subset_glyph->font_id = sub_font->font_id;
subset_glyph->subset_id = sub_font_glyph->subset_id;
subset_glyph->subset_glyph_index = sub_font_glyph->subset_glyph_index;
subset_glyph->is_scaled = sub_font->is_scaled;
subset_glyph->is_composite = sub_font->is_composite;
subset_glyph->x_advance = sub_font_glyph->x_advance;
return CAIRO_STATUS_SUCCESS;
}
@ -324,23 +366,31 @@ _cairo_sub_font_collect (void *entry, void *closure)
for (i = 0; i <= sub_font->current_subset; i++) {
collection->subset_id = i;
collection->num_glyphs = 0;
collection->max_glyph = 0;
if (sub_font->parent->type == CAIRO_SUBSETS_SCALED) {
collection->num_glyphs = 0;
collection->max_glyph = 0;
} else {
/* Assign .notdef glyph to the first glyph in the subset */
collection->glyphs[0] = 0;
collection->num_glyphs = 1;
collection->max_glyph = 0;
}
_cairo_hash_table_foreach (sub_font->sub_font_glyphs,
_cairo_sub_font_glyph_collect, collection);
/* Ensure the resulting array has no uninitialized holes */
/* Ensure the resulting array has no uninitialized holes */
assert (collection->num_glyphs == collection->max_glyph + 1);
subset.scaled_font = sub_font->scaled_font;
subset.is_composite = sub_font->is_composite;
subset.font_id = sub_font->font_id;
subset.subset_id = i;
subset.glyphs = collection->glyphs;
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 = malloc (collection->num_glyphs*sizeof(unsigned long));
subset.to_unicode = _cairo_malloc_ab (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 */
@ -355,9 +405,8 @@ _cairo_sub_font_collect (void *entry, void *closure)
}
}
cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
int max_glyphs_per_scaled_subset)
static cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type)
{
cairo_scaled_font_subsets_t *subsets;
@ -365,12 +414,9 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
if (subsets == NULL)
return NULL;
subsets->max_glyphs_per_unscaled_subset_limit = max_glyphs_per_unscaled_subset;
subsets->type = type;
subsets->max_glyphs_per_unscaled_subset_used = 0;
subsets->max_glyphs_per_scaled_subset_limit = max_glyphs_per_scaled_subset;
subsets->max_glyphs_per_scaled_subset_used = 0;
subsets->num_sub_fonts = 0;
subsets->unscaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
@ -381,7 +427,7 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
subsets->scaled_sub_fonts = _cairo_hash_table_create (_cairo_sub_fonts_equal);
if (! subsets->scaled_sub_fonts) {
free (subsets->unscaled_sub_fonts);
_cairo_hash_table_destroy (subsets->unscaled_sub_fonts);
free (subsets);
return NULL;
}
@ -389,6 +435,24 @@ _cairo_scaled_font_subsets_create (int max_glyphs_per_unscaled_subset,
return subsets;
}
cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create_scaled (void)
{
return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SCALED);
}
cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create_simple (void)
{
return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_SIMPLE);
}
cairo_scaled_font_subsets_t *
_cairo_scaled_font_subsets_create_composite (void)
{
return _cairo_scaled_font_subsets_create_internal (CAIRO_SUBSETS_COMPOSITE);
}
void
_cairo_scaled_font_subsets_destroy (cairo_scaled_font_subsets_t *subsets)
{
@ -404,44 +468,44 @@ cairo_private cairo_status_t
_cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
unsigned int *font_id,
unsigned int *subset_id,
unsigned int *subset_glyph_index)
cairo_scaled_font_subsets_glyph_t *subset_glyph)
{
cairo_sub_font_t key, *sub_font;
cairo_scaled_glyph_t *scaled_glyph;
cairo_font_face_t *font_face;
cairo_matrix_t identity;
cairo_font_options_t font_options;
cairo_scaled_font_t *unscaled_font;
cairo_status_t status;
int max_glyphs;
cairo_bool_t type1_font;
/* Lookup glyph in unscaled subsets */
if (subsets->max_glyphs_per_unscaled_subset_limit > 0) {
if (subsets->type != CAIRO_SUBSETS_SCALED) {
key.is_scaled = FALSE;
_cairo_sub_font_init_key (&key, scaled_font);
if (_cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
subset_id, subset_glyph_index);
if (status == CAIRO_STATUS_SUCCESS) {
*font_id = sub_font->font_id;
status = _cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
subset_glyph);
if (status == CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SUCCESS;
}
}
}
/* Lookup glyph in scaled subsets */
if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
key.is_scaled = TRUE;
_cairo_sub_font_init_key (&key, scaled_font);
if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
status = _cairo_sub_font_lookup_glyph (sub_font, scaled_font_glyph_index,
subset_id, subset_glyph_index);
if (status == CAIRO_STATUS_SUCCESS) {
*font_id = sub_font->font_id;
return CAIRO_STATUS_SUCCESS;
}
}
key.is_scaled = TRUE;
_cairo_sub_font_init_key (&key, scaled_font);
if (_cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
status = _cairo_sub_font_lookup_glyph (sub_font,
scaled_font_glyph_index,
subset_glyph);
if (status == CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_SUCCESS;
}
/* Glyph not found. Determine whether the glyph is outline or
@ -450,51 +514,96 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
if (status == 0 && subsets->max_glyphs_per_unscaled_subset_limit > 0) {
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
if (status == 0 && subsets->type != CAIRO_SUBSETS_SCALED) {
/* Path available. Add to unscaled subset. */
key.is_scaled = FALSE;
_cairo_sub_font_init_key (&key, scaled_font);
if (! _cairo_hash_table_lookup (subsets->unscaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
sub_font = _cairo_sub_font_create (subsets, scaled_font,
font_face = cairo_scaled_font_get_font_face (scaled_font);
cairo_matrix_init_identity (&identity);
_cairo_font_options_init_default (&font_options);
cairo_font_options_set_hint_style (&font_options, CAIRO_HINT_STYLE_NONE);
cairo_font_options_set_hint_metrics (&font_options, CAIRO_HINT_METRICS_OFF);
unscaled_font = cairo_scaled_font_create (font_face,
&identity,
&identity,
&font_options);
if (unscaled_font->status)
return unscaled_font->status;
subset_glyph->is_scaled = FALSE;
type1_font = FALSE;
#if CAIRO_HAS_FT_FONT
type1_font = _cairo_type1_scaled_font_is_type1 (unscaled_font);
#endif
if (subsets->type == CAIRO_SUBSETS_COMPOSITE && !type1_font) {
max_glyphs = MAX_GLYPHS_PER_COMPOSITE_FONT;
subset_glyph->is_composite = TRUE;
} else {
max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
subset_glyph->is_composite = FALSE;
}
sub_font = _cairo_sub_font_create (subsets,
unscaled_font,
subsets->num_sub_fonts++,
subsets->max_glyphs_per_unscaled_subset_limit,
FALSE);
if (sub_font == NULL)
max_glyphs,
subset_glyph->is_scaled,
subset_glyph->is_composite);
if (sub_font == NULL) {
cairo_scaled_font_destroy (unscaled_font);
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_hash_table_insert (subsets->unscaled_sub_fonts,
&sub_font->base);
if (status)
if (status) {
_cairo_sub_font_destroy (sub_font);
return status;
}
}
} else if (subsets->max_glyphs_per_scaled_subset_limit > 0) {
} else {
/* No path available. Add to scaled subset. */
key.is_scaled = TRUE;
_cairo_sub_font_init_key (&key, scaled_font);
if (! _cairo_hash_table_lookup (subsets->scaled_sub_fonts, &key.base,
(cairo_hash_entry_t **) &sub_font))
{
sub_font = _cairo_sub_font_create (subsets, scaled_font,
subset_glyph->is_scaled = TRUE;
subset_glyph->is_composite = FALSE;
if (subsets->type == CAIRO_SUBSETS_SCALED)
max_glyphs = INT_MAX;
else
max_glyphs = MAX_GLYPHS_PER_SIMPLE_FONT;
sub_font = _cairo_sub_font_create (subsets,
cairo_scaled_font_reference (scaled_font),
subsets->num_sub_fonts++,
subsets->max_glyphs_per_scaled_subset_limit,
TRUE);
if (sub_font == NULL)
max_glyphs,
subset_glyph->is_scaled,
subset_glyph->is_composite);
if (sub_font == NULL) {
cairo_scaled_font_destroy (scaled_font);
return CAIRO_STATUS_NO_MEMORY;
}
status = _cairo_hash_table_insert (subsets->scaled_sub_fonts,
&sub_font->base);
if (status)
if (status) {
_cairo_sub_font_destroy (sub_font);
return status;
}
}
} else {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
*font_id = sub_font->font_id;
return _cairo_sub_font_map_glyph (sub_font, scaled_font_glyph_index,
subset_id, subset_glyph_index);
return _cairo_sub_font_map_glyph (sub_font,
scaled_font_glyph_index,
subset_glyph);
}
static cairo_status_t
@ -509,7 +618,11 @@ _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;
collection.glyphs = malloc (collection.glyphs_size * sizeof(unsigned long));
if (! collection.glyphs_size)
return CAIRO_STATUS_SUCCESS;
collection.glyphs = _cairo_malloc_ab (collection.glyphs_size, sizeof(unsigned long));
if (collection.glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -540,7 +653,7 @@ _cairo_scaled_font_subsets_foreach_scaled (cairo_scaled_font_subsets_t *fon
}
cairo_private cairo_status_t
_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
_cairo_scaled_font_subsets_foreach_unscaled (cairo_scaled_font_subsets_t *font_subsets,
cairo_scaled_font_subset_callback_func_t font_subset_callback,
void *closure)
{

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

@ -1,49 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_SCALED_FONT_TEST_H
#define CAIRO_SCALED_FONT_TEST_H
#include <cairo.h>
CAIRO_BEGIN_DECLS
cairo_public void
_cairo_scaled_font_test_set_max_glyphs_cached_per_font (int max);
CAIRO_END_DECLS
#endif /* CAIRO_SCALED_FONT_TEST_H */

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

@ -37,7 +37,7 @@
*/
#include "cairoint.h"
#include "cairo-scaled-font-test.h"
#include "cairo-scaled-font-private.h"
static cairo_bool_t
_cairo_scaled_glyph_keys_equal (const void *abstract_key_a, const void *abstract_key_b)
@ -135,6 +135,9 @@ _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
cairo_font_type_t
cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font)
{
if (scaled_font->ref_count == CAIRO_REF_COUNT_INVALID)
return CAIRO_FONT_TYPE_TOY;
return scaled_font->backend->type;
}
@ -153,6 +156,7 @@ cairo_scaled_font_status (cairo_scaled_font_t *scaled_font)
{
return scaled_font->status;
}
slim_hidden_def (cairo_scaled_font_status);
/* Here we keep a unique mapping from
* cairo_font_face_t/matrix/ctm/options => cairo_scaled_font_t.
@ -185,8 +189,6 @@ typedef struct _cairo_scaled_font_map {
static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL;
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_map_mutex);
static int
_cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b);
@ -213,6 +215,7 @@ _cairo_scaled_font_map_lock (void)
CLEANUP_SCALED_FONT_MAP:
free (cairo_scaled_font_map);
cairo_scaled_font_map = NULL;
CLEANUP_MUTEX_LOCK:
CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
return NULL;
@ -331,14 +334,7 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_
* separately is probably not what we want anyway. Would probably be
* much better to have a single cache for glyphs with random
* replacement across all glyphs of all fonts. */
static int max_glyphs_cached_per_font = 256;
/* For internal testing purposes only. Not part of the supported API. */
void
_cairo_scaled_font_test_set_max_glyphs_cached_per_font (int max)
{
max_glyphs_cached_per_font = max;
}
#define MAX_GLYPHS_CACHED_PER_FONT 256
/*
* Basic cairo_scaled_font_t object management
@ -352,23 +348,40 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font,
const cairo_font_options_t *options,
const cairo_scaled_font_backend_t *backend)
{
scaled_font->ref_count = 1;
cairo_matrix_t inverse;
cairo_status_t status;
_cairo_user_data_array_init (&scaled_font->user_data);
status = cairo_font_options_status ((cairo_font_options_t *) options);
if (status)
return status;
/* Initialize scaled_font->scale early for easier bail out on an
* invalid matrix. */
_cairo_scaled_font_init_key (scaled_font, font_face,
font_matrix, ctm, options);
cairo_font_face_reference (font_face);
cairo_matrix_multiply (&scaled_font->scale,
&scaled_font->font_matrix,
&scaled_font->ctm);
CAIRO_MUTEX_INIT (&scaled_font->mutex);
inverse = scaled_font->scale;
status = cairo_matrix_invert (&inverse);
if (status)
return status;
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
_cairo_scaled_glyph_destroy,
max_glyphs_cached_per_font);
MAX_GLYPHS_CACHED_PER_FONT);
if (scaled_font->glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
scaled_font->ref_count = 1;
_cairo_user_data_array_init (&scaled_font->user_data);
cairo_font_face_reference (font_face);
CAIRO_MUTEX_INIT (scaled_font->mutex);
scaled_font->surface_backend = NULL;
scaled_font->surface_private = NULL;
@ -396,7 +409,7 @@ _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
_cairo_cache_destroy (scaled_font->glyphs);
scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal,
_cairo_scaled_glyph_destroy,
max_glyphs_cached_per_font);
MAX_GLYPHS_CACHED_PER_FONT);
}
void
@ -430,7 +443,7 @@ _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
if (scaled_font->glyphs != NULL)
_cairo_cache_destroy (scaled_font->glyphs);
CAIRO_MUTEX_FINI (&scaled_font->mutex);
CAIRO_MUTEX_FINI (scaled_font->mutex);
if (scaled_font->surface_backend != NULL &&
scaled_font->surface_backend->scaled_font_fini != NULL)
@ -474,9 +487,12 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
if (font_face->status)
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
if (cairo_font_options_status ((cairo_font_options_t *) options))
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
font_map = _cairo_scaled_font_map_lock ();
if (font_map == NULL)
return NULL;
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
_cairo_scaled_font_init_key (&key, font_face,
font_matrix, ctm, options);
@ -501,35 +517,44 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
memmove (&font_map->holdovers[i],
&font_map->holdovers[i+1],
(font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
/* reset any error status */
scaled_font->status = CAIRO_STATUS_SUCCESS;
}
/* We increment the reference count manually here, (rather
* than calling into cairo_scaled_font_reference), since we
* must modify the reference count while our lock is still
* held. */
scaled_font->ref_count++;
_cairo_scaled_font_map_unlock ();
} else {
/* Otherwise create it and insert it into the hash table. */
status = font_face->backend->scaled_font_create (font_face, font_matrix,
ctm, options, &scaled_font);
if (status) {
if (scaled_font->status == CAIRO_STATUS_SUCCESS) {
/* We increment the reference count manually here, (rather
* than calling into cairo_scaled_font_reference), since we
* must modify the reference count while our lock is still
* held. */
scaled_font->ref_count++;
_cairo_scaled_font_map_unlock ();
return NULL;
return scaled_font;
}
status = _cairo_hash_table_insert (font_map->hash_table,
&scaled_font->hash_entry);
/* the font has been put into an error status - abandon the cache */
_cairo_hash_table_remove (font_map->hash_table, &key.hash_entry);
}
/* Otherwise create it and insert it into the hash table. */
status = font_face->backend->scaled_font_create (font_face, font_matrix,
ctm, options, &scaled_font);
if (status) {
_cairo_scaled_font_map_unlock ();
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
}
if (status) {
/* We can't call _cairo_scaled_font_destroy here since it expects
* that the font has already been successfully inserted into the
* hash table. */
_cairo_scaled_font_fini (scaled_font);
free (scaled_font);
return NULL;
}
status = _cairo_hash_table_insert (font_map->hash_table,
&scaled_font->hash_entry);
_cairo_scaled_font_map_unlock ();
if (status) {
/* We can't call _cairo_scaled_font_destroy here since it expects
* that the font has already been successfully inserted into the
* hash table. */
_cairo_scaled_font_fini (scaled_font);
free (scaled_font);
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
}
return scaled_font;
@ -748,10 +773,13 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
const char *utf8,
cairo_text_extents_t *extents)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_status_t status;
cairo_glyph_t *glyphs;
int num_glyphs;
if (scaled_font->status)
return;
status = _cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., utf8, &glyphs, &num_glyphs);
if (status) {
_cairo_scaled_font_set_error (scaled_font, status);
@ -774,7 +802,7 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
* graphics state were set to the same font_face, font_matrix, ctm,
* and font_options as @scaled_font). Additionally, the x_advance and
* y_advance values indicate the amount by which the current point
* would be advanced by cairo_show_glyphs.
* would be advanced by cairo_show_glyphs().
*
* Note that whitespace glyphs do not contribute to the size of the
* rectangle (extents.width and extents.height).
@ -785,7 +813,7 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
int num_glyphs,
cairo_text_extents_t *extents)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_status_t status;
int i;
double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0;
cairo_bool_t visible = FALSE;
@ -899,7 +927,7 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
if (status)
goto DONE;
*glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t)));
*glyphs = (cairo_glyph_t *) _cairo_malloc_ab ((*num_glyphs), sizeof (cairo_glyph_t));
if (*glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
@ -946,8 +974,8 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
int i;
int min_x = INT16_MAX, max_x = INT16_MIN;
int min_y = INT16_MAX, max_y = INT16_MIN;
short min_x = INT16_MAX, max_x = INT16_MIN;
short min_y = INT16_MAX, max_y = INT16_MIN;
if (scaled_font->status)
return scaled_font->status;
@ -1100,7 +1128,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
_cairo_pattern_fini (&glyph_pattern.base);
if (status)
break;
goto CLEANUP_MASK;
}
if (mask != NULL) {
@ -1176,6 +1204,42 @@ _scaled_glyph_path_close_path (void *abstract_closure)
return _cairo_path_fixed_close_path (closure->path);
}
/* Add a single-device-unit rectangle to a path. */
static cairo_status_t
_add_unit_rectangle_to_path (cairo_path_fixed_t *path, int x, int y)
{
cairo_status_t status;
status = _cairo_path_fixed_move_to (path,
_cairo_fixed_from_int (x),
_cairo_fixed_from_int (y));
if (status)
return status;
status = _cairo_path_fixed_rel_line_to (path,
_cairo_fixed_from_int (1),
_cairo_fixed_from_int (0));
if (status)
return status;
status = _cairo_path_fixed_rel_line_to (path,
_cairo_fixed_from_int (0),
_cairo_fixed_from_int (1));
if (status)
return status;
status = _cairo_path_fixed_rel_line_to (path,
_cairo_fixed_from_int (-1),
_cairo_fixed_from_int (0));
if (status)
return status;
status = _cairo_path_fixed_close_path (path);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
/**
* _trace_mask_to_path:
@ -1198,6 +1262,7 @@ static cairo_status_t
_trace_mask_to_path (cairo_image_surface_t *mask,
cairo_path_fixed_t *path)
{
cairo_status_t status;
cairo_image_surface_t *a1_mask;
unsigned char *row, *byte_ptr, byte;
int rows, cols, bytes_per_row;
@ -1220,19 +1285,10 @@ _trace_mask_to_path (cairo_image_surface_t *mask,
byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte_ptr);
for (bit = 7; bit >= 0 && x < a1_mask->width; bit--, x++) {
if (byte & (1 << bit)) {
_cairo_path_fixed_move_to (path,
_cairo_fixed_from_int (x + xoff),
_cairo_fixed_from_int (y + yoff));
_cairo_path_fixed_rel_line_to (path,
_cairo_fixed_from_int (1),
_cairo_fixed_from_int (0));
_cairo_path_fixed_rel_line_to (path,
_cairo_fixed_from_int (0),
_cairo_fixed_from_int (1));
_cairo_path_fixed_rel_line_to (path,
_cairo_fixed_from_int (-1),
_cairo_fixed_from_int (0));
_cairo_path_fixed_close_path (path);
status = _add_unit_rectangle_to_path (path,
x + xoff, y + yoff);
if (status)
return status;
}
}
}
@ -1278,6 +1334,8 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (status)
return status;
glyph_path = _cairo_path_fixed_create ();
if (glyph_path == NULL)
@ -1302,6 +1360,9 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
&closure);
if (glyph_path != scaled_glyph->path)
_cairo_path_fixed_destroy (glyph_path);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
@ -1601,6 +1662,9 @@ void
cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font,
cairo_font_options_t *options)
{
if (cairo_font_options_status (options))
return;
if (scaled_font->status) {
_cairo_font_options_init_default (options);
return;

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

@ -26,7 +26,24 @@
#include "cairoint.h"
#define MAX_LEVEL 31
/*
* Skip lists are described in detail here:
*
* http://citeseer.ist.psu.edu/pugh90skip.html
*/
/* Note that random_level() called from alloc_node_for_level() depends on
* this being not more than 16.
*/
#define MAX_LEVEL 15
/* Returns the index of the free-list to use for a node at level 'level' */
#define FREELIST_FOR_LEVEL(level) (((level) - 1) / 2)
/* Returns the maximum level that uses the same free-list as 'level' does */
#define FREELIST_MAX_LEVEL_FOR(level) (((level) + 1) & ~1)
#define MAX_FREELIST_LEVEL (FREELIST_FOR_LEVEL (MAX_LEVEL - 1) + 1)
/*
* Skip list element. In order to use the skip list, the caller must
@ -52,7 +69,7 @@ typedef struct _skip_list {
size_t elt_size;
size_t data_size;
skip_elt_t *chains[MAX_LEVEL];
skip_elt_t *freelists[MAX_LEVEL];
skip_elt_t *freelists[MAX_FREELIST_LEVEL];
int max_level;
} cairo_skip_list_t;

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

@ -21,11 +21,7 @@
* OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include "cairoint.h"
#include "cairo-skiplist-private.h"
@ -236,6 +232,9 @@ _cairo_skip_list_init (cairo_skip_list_t *list,
for (i = 0; i < MAX_LEVEL; i++) {
list->chains[i] = NULL;
}
for (i = 0; i < MAX_FREELIST_LEVEL; i++) {
list->freelists[i] = NULL;
}
@ -251,7 +250,7 @@ _cairo_skip_list_fini (cairo_skip_list_t *list)
while ((elt = list->chains[0])) {
_cairo_skip_list_delete_given (list, elt);
}
for (i=0; i<MAX_LEVEL; i++) {
for (i=0; i<MAX_FREELIST_LEVEL; i++) {
elt = list->freelists[i];
while (elt) {
skip_elt_t *nextfree = elt->prev;
@ -265,14 +264,17 @@ _cairo_skip_list_fini (cairo_skip_list_t *list)
* Generate a random level number, distributed
* so that each level is 1/4 as likely as the one before
*
* Note that level numbers run 1 <= level <= MAX_LEVEL
* Note that level numbers run 1 <= level < MAX_LEVEL
*/
static int
random_level (void)
{
/* tricky bit -- each bit is '1' 75% of the time */
long int bits = lfsr_random() | lfsr_random();
int level = 0;
/* tricky bit -- each bit is '1' 75% of the time.
* This works because we only use the lower MAX_LEVEL
* bits, and MAX_LEVEL < 16 */
long int bits = lfsr_random();
bits |= bits >> 16;
while (++level < MAX_LEVEL)
{
@ -286,19 +288,23 @@ random_level (void)
static void *
alloc_node_for_level (cairo_skip_list_t *list, unsigned level)
{
if (list->freelists[level-1]) {
skip_elt_t *elt = list->freelists[level-1];
list->freelists[level-1] = elt->prev;
int freelist_level = FREELIST_FOR_LEVEL (level);
if (list->freelists[freelist_level]) {
skip_elt_t *elt = list->freelists[freelist_level];
list->freelists[freelist_level] = elt->prev;
return ELT_DATA(elt);
}
return malloc (list->elt_size + (level-1) * sizeof (skip_elt_t *));
return malloc (list->elt_size
+ (FREELIST_MAX_LEVEL_FOR (level) - 1) * sizeof (skip_elt_t *));
}
static void
free_elt (cairo_skip_list_t *list, skip_elt_t *elt)
{
elt->prev = list->freelists[elt->prev_index];
list->freelists[elt->prev_index] = elt;
int level = elt->prev_index + 1;
int freelist_level = FREELIST_FOR_LEVEL (level);
elt->prev = list->freelists[freelist_level];
list->freelists[freelist_level] = elt;
}
/*
@ -349,6 +355,8 @@ _cairo_skip_list_insert (cairo_skip_list_t *list, void *data, int unique)
}
data_and_elt = alloc_node_for_level (list, level);
if (data_and_elt == NULL)
return NULL;
memcpy (data_and_elt, data, list->data_size);
elt = (skip_elt_t *) (data_and_elt + list->data_size);

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

@ -80,9 +80,9 @@ _cairo_spline_init (cairo_spline_t *spline,
else
_cairo_slope_init (&spline->final_slope, &spline->a, &spline->d);
spline->points = spline->points_embedded;
spline->points_size = ARRAY_LENGTH (spline->points_embedded);
spline->num_points = 0;
spline->points_size = 0;
spline->points = NULL;
return CAIRO_STATUS_SUCCESS;
}
@ -90,11 +90,11 @@ _cairo_spline_init (cairo_spline_t *spline,
void
_cairo_spline_fini (cairo_spline_t *spline)
{
if (spline->points && spline->points != spline->points_embedded)
if (spline->points != spline->points_embedded)
free (spline->points);
spline->points = NULL;
spline->points_size = 0;
spline->points = spline->points_embedded;
spline->points_size = ARRAY_LENGTH (spline->points_embedded);
spline->num_points = 0;
}
@ -104,21 +104,12 @@ _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 = malloc (new_size * sizeof (cairo_point_t));
new_points = _cairo_malloc_ab (new_size, sizeof (cairo_point_t));
if (new_points)
memcpy (new_points, spline->points, old_size * sizeof (cairo_point_t));
} else {
@ -284,9 +275,8 @@ _cairo_spline_decompose (cairo_spline_t *spline, double tolerance)
{
cairo_status_t status;
if (spline->points_size) {
_cairo_spline_fini (spline);
}
/* reset the spline, but keep the buffer */
spline->num_points = 0;
status = _cairo_spline_decompose_into (spline, tolerance * tolerance, spline);
if (status)

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

@ -62,7 +62,7 @@ _cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
if (other->dash == NULL) {
style->dash = NULL;
} else {
style->dash = malloc (style->num_dashes * sizeof (double));
style->dash = _cairo_malloc_ab (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_int16_t *rects,
cairo_rectangle_int_t *rects,
int num_rects);
cairo_private cairo_status_t

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

@ -35,14 +35,16 @@
* 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_int16_t extents;
cairo_rectangle_int_t extents;
cairo_image_surface_t *image;
cairo_rectangle_int16_t image_rect;
cairo_rectangle_int_t image_rect;
void *image_extra;
} fallback_state_t;
@ -104,7 +106,7 @@ typedef cairo_status_t (*cairo_draw_func_t) (void *clos
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int16_t *extents);
const cairo_rectangle_int_t *extents);
static cairo_status_t
_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
@ -112,7 +114,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_int16_t *extents)
const cairo_rectangle_int_t *extents)
{
cairo_surface_t *mask;
cairo_status_t status;
@ -157,7 +159,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_int16_t *extents)
const cairo_rectangle_int_t *extents)
{
cairo_surface_pattern_t mask_pattern;
cairo_status_t status;
@ -191,7 +193,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_int16_t *extents)
const cairo_rectangle_int_t *extents)
{
cairo_surface_t *intermediate;
cairo_surface_pattern_t dst_pattern;
@ -279,7 +281,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_int16_t *extents)
const cairo_rectangle_int_t *extents)
{
cairo_surface_pattern_t mask_pattern;
cairo_status_t status;
@ -320,7 +322,7 @@ _clip_and_composite_source (cairo_clip_t *clip,
}
static int
_cairo_rectangle_empty (const cairo_rectangle_int16_t *rect)
_cairo_rectangle_empty (const cairo_rectangle_int_t *rect)
{
return rect->width == 0 || rect->height == 0;
}
@ -353,7 +355,7 @@ _clip_and_composite (cairo_clip_t *clip,
cairo_draw_func_t draw_func,
void *draw_closure,
cairo_surface_t *dst,
const cairo_rectangle_int16_t *extents)
const cairo_rectangle_int_t *extents)
{
cairo_pattern_union_t solid_pattern;
cairo_status_t status;
@ -363,7 +365,8 @@ _clip_and_composite (cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
if (op == CAIRO_OPERATOR_CLEAR) {
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
src = &solid_pattern.base;
op = CAIRO_OPERATOR_DEST_OUT;
}
@ -407,18 +410,19 @@ _composite_trap_region (cairo_clip_t *clip,
cairo_pattern_t *src,
cairo_operator_t op,
cairo_surface_t *dst,
pixman_region16_t *trap_region,
cairo_rectangle_int16_t *extents)
cairo_region_t *trap_region,
cairo_rectangle_int_t *extents)
{
cairo_status_t status;
cairo_pattern_union_t solid_pattern;
cairo_pattern_union_t mask;
int num_rects = pixman_region_num_rects (trap_region);
int num_rects = _cairo_region_num_boxes (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_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
src = &solid_pattern.base;
op = CAIRO_OPERATOR_DEST_OUT;
}
@ -452,8 +456,11 @@ _composite_trap_region (cairo_clip_t *clip,
extents->width, extents->height);
/* Restore the original clip if we modified it temporarily. */
if (num_rects >1)
_cairo_surface_set_clip (dst, clip);
if (num_rects > 1) {
cairo_status_t status2 = _cairo_surface_set_clip (dst, clip);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
}
if (clip_surface)
_cairo_pattern_fini (&mask.base);
@ -476,7 +483,7 @@ _composite_traps_draw_func (void *closure,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int16_t *extents)
const cairo_rectangle_int_t *extents)
{
cairo_composite_traps_info_t *info = closure;
cairo_pattern_union_t pattern;
@ -485,7 +492,8 @@ _composite_traps_draw_func (void *closure,
if (dst_x != 0 || dst_y != 0)
_cairo_traps_translate (info->traps, - dst_x, - dst_y);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
if (!src)
src = &pattern.base;
@ -511,145 +519,152 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
cairo_antialias_t antialias)
{
cairo_status_t status;
pixman_region16_t *trap_region = NULL;
pixman_region16_t *clear_region = NULL;
cairo_rectangle_int16_t extents;
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;
cairo_composite_traps_info_t traps_info;
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_get_extents (dst, &extents);
if (status)
return status;
return status;
status = _cairo_traps_extract_region (traps, &trap_region);
if (status)
return status;
if (_cairo_operator_bounded_by_mask (op))
{
cairo_rectangle_int16_t trap_extents;
if (trap_region) {
status = _cairo_clip_intersect_to_region (clip, trap_region);
if (status)
goto out;
_cairo_region_extents_rectangle (trap_region, &trap_extents);
} else {
cairo_box_t trap_box;
_cairo_traps_extents (traps, &trap_box);
_cairo_box_round_to_rectangle (&trap_box, &trap_extents);
}
_cairo_rectangle_intersect (&extents, &trap_extents);
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
if (status)
goto out;
if (CAIRO_INT_STATUS_UNSUPPORTED == status) {
has_trap_region = FALSE;
} else if (status) {
return status;
} else {
has_trap_region = TRUE;
}
else
{
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (trap_region && !clip_surface) {
/* If we optimize drawing with an unbounded operator to
* _cairo_surface_fill_rectangles() or to drawing with a
* clip region, then we have an additional region to clear.
*/
clear_region = _cairo_region_create_from_rectangle (&extents);
if (clear_region == NULL)
return CAIRO_STATUS_NO_MEMORY;
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int_t trap_extents;
status = _cairo_clip_intersect_to_region (clip, clear_region);
if (status)
return status;
if (has_trap_region) {
status = _cairo_clip_intersect_to_region (clip, &trap_region);
_cairo_region_extents_rectangle (clear_region, &extents);
if (status)
goto out;
if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
return CAIRO_STATUS_NO_MEMORY;
_cairo_region_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_not_empty (clear_region)) {
pixman_region_destroy (clear_region);
clear_region = NULL;
}
} else {
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
if (status)
return status;
}
_cairo_rectangle_intersect (&extents, &trap_extents);
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
if (status)
goto out;
} else {
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (has_trap_region && !clip_surface) {
/* If we optimize drawing with an unbounded operator to
* _cairo_surface_fill_rectangles() or to drawing with a
* clip region, then we have an additional region to clear.
*/
_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 (status)
goto out;
goto out;
if (trap_region)
{
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if (has_trap_region) {
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
!clip_surface)
{
const cairo_color_t *color;
if ((src->type == CAIRO_PATTERN_TYPE_SOLID ||
op == CAIRO_OPERATOR_CLEAR) && !clip_surface) {
const cairo_color_t *color;
if (op == CAIRO_OPERATOR_CLEAR)
color = CAIRO_COLOR_TRANSPARENT;
else
color = &((cairo_solid_pattern_t *)src)->color;
if (op == CAIRO_OPERATOR_CLEAR) {
color = CAIRO_COLOR_TRANSPARENT;
} else {
color = &((cairo_solid_pattern_t *)src)->color;
}
/* Solid rectangles special case */
status = _cairo_surface_fill_region (dst, op, color, trap_region);
if (!status && clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
clear_region);
/* Solid rectangles special case */
status = _cairo_surface_fill_region (dst, op, color, &trap_region);
goto out;
}
if (!status && has_clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
&clear_region);
if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) ||
!clip_surface)
{
/* For a simple rectangle, we can just use composite(), for more
* rectangles, we have to set a clip region. The cost of rasterizing
* trapezoids is pretty high for most backends currently, so it's
* worthwhile even if a region is needed.
*
* If we have a clip surface, we set it as the mask; this only works
* for bounded operators other than SOURCE; for unbounded operators,
* clip and mask cannot be interchanged. For SOURCE, the operator
* as implemented by the backends is different in it's handling
* of the mask then what we want.
*
* CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
* more than rectangle and the destination doesn't support clip
* regions. In that case, we fall through.
*/
status = _composite_trap_region (clip, src, op, dst,
trap_region, &extents);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
{
if (!status && clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
clear_region);
goto out;
}
}
goto out;
}
if ((_cairo_operator_bounded_by_mask (op) &&
op != CAIRO_OPERATOR_SOURCE) || !clip_surface) {
/* For a simple rectangle, we can just use composite(), for more
* rectangles, we have to set a clip region. The cost of rasterizing
* trapezoids is pretty high for most backends currently, so it's
* worthwhile even if a region is needed.
*
* If we have a clip surface, we set it as the mask; this only works
* for bounded operators other than SOURCE; for unbounded operators,
* clip and mask cannot be interchanged. For SOURCE, the operator
* as implemented by the backends is different in it's handling
* of the mask then what we want.
*
* CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
* more than rectangle and the destination doesn't support clip
* regions. In that case, we fall through.
*/
status = _composite_trap_region (clip, src, op, dst,
&trap_region, &extents);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
if (!status && has_clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
&clear_region);
goto out;
}
}
}
traps_info.traps = traps;
traps_info.antialias = antialias;
status = _clip_and_composite (clip, op, src,
_composite_traps_draw_func, &traps_info,
dst, &extents);
_composite_traps_draw_func,
&traps_info, dst, &extents);
out:
if (trap_region)
pixman_region_destroy (trap_region);
if (clear_region)
pixman_region_destroy (clear_region);
out:
if (has_trap_region)
_cairo_region_fini (&trap_region);
if (has_clear_region)
_cairo_region_fini (&clear_region);
return status;
}
@ -660,7 +675,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
cairo_pattern_t *source)
{
cairo_status_t status;
cairo_rectangle_int16_t extents;
cairo_rectangle_int_t extents;
cairo_box_t box;
cairo_traps_t traps;
@ -669,7 +684,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int16_t source_extents;
cairo_rectangle_int_t source_extents;
status = _cairo_pattern_get_extents (source, &source_extents);
if (status)
return status;
@ -690,16 +705,16 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
if (status)
return status;
_clip_and_composite_trapezoids (source,
op,
surface,
&traps,
surface->clip,
CAIRO_ANTIALIAS_NONE);
status = _clip_and_composite_trapezoids (source,
op,
surface,
&traps,
surface->clip,
CAIRO_ANTIALIAS_NONE);
_cairo_traps_fini (&traps);
return CAIRO_STATUS_SUCCESS;
return status;
}
static cairo_status_t
@ -709,7 +724,7 @@ _cairo_surface_mask_draw_func (void *closure,
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int16_t *extents)
const cairo_rectangle_int_t *extents)
{
cairo_pattern_t *mask = closure;
@ -736,7 +751,7 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
cairo_pattern_t *mask)
{
cairo_status_t status;
cairo_rectangle_int16_t extents, source_extents, mask_extents;
cairo_rectangle_int_t extents, source_extents, mask_extents;
status = _cairo_surface_get_extents (surface, &extents);
if (status)
@ -785,9 +800,35 @@ _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,
@ -798,16 +839,16 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
return status;
}
_clip_and_composite_trapezoids (source,
op,
surface,
&traps,
surface->clip,
antialias);
status = _clip_and_composite_trapezoids (source,
op,
surface,
&traps,
surface->clip,
antialias);
_cairo_traps_fini (&traps);
return CAIRO_STATUS_SUCCESS;
return status;
}
cairo_status_t
@ -821,9 +862,35 @@ _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,
@ -858,7 +925,7 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
cairo_surface_t *dst,
int dst_x,
int dst_y,
const cairo_rectangle_int16_t *extents)
const cairo_rectangle_int_t *extents)
{
cairo_show_glyphs_info_t *glyph_info = closure;
cairo_pattern_union_t pattern;
@ -878,7 +945,8 @@ _cairo_surface_old_show_glyphs_draw_func (void *closure
}
}
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
if (!src)
src = &pattern.base;
@ -920,7 +988,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
cairo_scaled_font_t *scaled_font)
{
cairo_status_t status;
cairo_rectangle_int16_t extents, glyph_extents;
cairo_rectangle_int_t extents;
cairo_show_glyphs_info_t glyph_info;
status = _cairo_surface_get_extents (surface, &extents);
@ -928,6 +996,8 @@ _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,
@ -935,7 +1005,11 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
if (status)
return status;
_cairo_rectangle_intersect (&extents, &glyph_extents);
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);
}
status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
@ -979,17 +1053,21 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
_cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
&pattern.base,
NULL,
snapshot,
0, 0,
0, 0,
0, 0,
image->width,
image->height);
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
&pattern.base,
NULL,
snapshot,
0, 0,
0, 0,
0, 0,
image->width,
image->height);
_cairo_pattern_fini (&pattern.base);
if (status) {
cairo_surface_destroy (snapshot);
return (cairo_surface_t *) &_cairo_surface_nil;
}
_cairo_surface_release_source_image (surface,
image, &image_extra);
@ -1046,11 +1124,11 @@ cairo_status_t
_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int16_t *rects,
cairo_rectangle_int_t *rects,
int num_rects)
{
fallback_state_t state;
cairo_rectangle_int16_t *offset_rects = NULL;
cairo_rectangle_int_t *offset_rects = NULL;
cairo_status_t status;
int x1, y1, x2, y2;
int i;
@ -1090,7 +1168,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 = malloc (sizeof (cairo_rectangle_int16_t) * num_rects);
offset_rects = _cairo_malloc_ab (num_rects, sizeof (cairo_rectangle_int_t));
if (offset_rects == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto DONE;
@ -1146,7 +1224,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 = malloc (sizeof (cairo_trapezoid_t) * num_traps);
offset_traps = _cairo_malloc_ab (num_traps, sizeof (cairo_trapezoid_t));
if (!offset_traps) {
status = CAIRO_STATUS_NO_MEMORY;
goto DONE;
@ -1158,13 +1236,14 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
traps = offset_traps;
}
_cairo_surface_composite_trapezoids (op, pattern,
&state.image->base,
antialias,
src_x, src_y,
dst_x - state.image_rect.x,
dst_y - state.image_rect.y,
width, height, traps, num_traps);
status = _cairo_surface_composite_trapezoids (op, pattern,
&state.image->base,
antialias,
src_x, src_y,
dst_x - state.image_rect.x,
dst_y - state.image_rect.y,
width, height,
traps, num_traps);
if (offset_traps)
free (offset_traps);

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

@ -1,3 +1,4 @@
/* -*- 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
@ -35,9 +36,8 @@
* Carl D. Worth <cworth@cworth.org>
*/
#include <stdlib.h>
#include "cairoint.h"
#include "cairo-surface-fallback-private.h"
#include "cairo-clip-private.h"
@ -81,7 +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 void
static cairo_status_t
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
cairo_surface_t *destination,
cairo_pattern_t *pattern_out);
@ -180,10 +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,7 +289,8 @@ cairo_surface_create_similar (cairo_surface_t *other,
return _cairo_surface_create_similar_solid (other, content,
width, height,
CAIRO_COLOR_TRANSPARENT);
CAIRO_COLOR_TRANSPARENT,
NULL);
}
slim_hidden_def (cairo_surface_create_similar);
@ -298,7 +299,8 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
cairo_content_t content,
int width,
int height,
const cairo_color_t *color)
const cairo_color_t *color,
cairo_pattern_t *pattern)
{
cairo_status_t status;
cairo_surface_t *surface;
@ -311,19 +313,23 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
return (cairo_surface_t*) &_cairo_surface_nil;
}
source = _cairo_pattern_create_solid (color);
if (source->status) {
cairo_surface_destroy (surface);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
if (pattern == NULL) {
source = _cairo_pattern_create_solid (color, content);
if (source->status) {
cairo_surface_destroy (surface);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
} else
source = pattern;
status = _cairo_surface_paint (surface,
color == CAIRO_COLOR_TRANSPARENT ?
CAIRO_OPERATOR_CLEAR :
CAIRO_OPERATOR_SOURCE, source);
cairo_pattern_destroy (source);
if (source != pattern)
cairo_pattern_destroy (source);
if (status) {
cairo_surface_destroy (surface);
@ -374,7 +380,7 @@ slim_hidden_def (cairo_surface_reference);
/**
* cairo_surface_destroy:
* @surface: a #cairo_t
* @surface: a #cairo_surface_t
*
* Decreases the reference count on @surface by one. If the result is
* zero, then @surface and all associated resources are freed. See
@ -401,6 +407,34 @@ cairo_surface_destroy (cairo_surface_t *surface)
}
slim_hidden_def(cairo_surface_destroy);
/**
* cairo_surface_reset:
* @surface: a #cairo_surface_t
*
* Resets the surface back to defaults such that it may be reused in lieu
* of creating a new surface.
**/
cairo_status_t
_cairo_surface_reset (cairo_surface_t *surface)
{
if (surface == NULL || surface->ref_count == CAIRO_REF_COUNT_INVALID)
return CAIRO_STATUS_SUCCESS;
assert (surface->ref_count == 1);
_cairo_user_data_array_fini (&surface->user_data);
if (surface->backend->reset != NULL) {
cairo_status_t status = surface->backend->reset (surface);
if (status)
return status;
}
_cairo_surface_init (surface, surface->backend, surface->content);
return CAIRO_STATUS_SUCCESS;
}
/**
* cairo_surface_get_reference_count:
* @surface: a #cairo_surface_t
@ -469,10 +503,8 @@ cairo_surface_finish (cairo_surface_t *surface)
}
status = surface->backend->finish (surface);
if (status) {
if (status)
_cairo_surface_set_error (surface, status);
return;
}
surface->finished = TRUE;
}
@ -570,13 +602,16 @@ void
cairo_surface_get_font_options (cairo_surface_t *surface,
cairo_font_options_t *options)
{
if (cairo_font_options_status (options))
return;
if (!surface->has_font_options) {
surface->has_font_options = TRUE;
_cairo_font_options_init_default (&surface->font_options);
if (!surface->finished && surface->backend->get_font_options) {
surface->backend->get_font_options (surface, &surface->font_options);
} else {
_cairo_font_options_init_default (&surface->font_options);
}
}
@ -922,9 +957,9 @@ _cairo_surface_release_source_image (cairo_surface_t *surface,
**/
cairo_status_t
_cairo_surface_acquire_dest_image (cairo_surface_t *surface,
cairo_rectangle_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void **image_extra)
{
assert (!surface->finished);
@ -948,9 +983,9 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface,
**/
void
_cairo_surface_release_dest_image (cairo_surface_t *surface,
cairo_rectangle_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
assert (!surface->finished);
@ -1057,6 +1092,35 @@ _cairo_surface_snapshot (cairo_surface_t *surface)
return _cairo_surface_fallback_snapshot (surface);
}
/**
* _cairo_surface_is_similar
* @surface_a: a #cairo_surface_t
* @surface_b: a #cairo_surface_t
* @content: a #cairo_content_t
*
* Find out whether the given surfaces share the same backend,
* and if so, whether they can be considered similar.
*
* The definition of "similar" depends on the backend. In
* general, it means that the surface is equivalent to one
* that would have been generated by a call to cairo_surface_create_similar.
*
* Return value: TRUE if the surfaces are similar.
**/
cairo_bool_t
_cairo_surface_is_similar (cairo_surface_t *surface_a,
cairo_surface_t *surface_b,
cairo_content_t content)
{
if (surface_a->backend != surface_b->backend)
return FALSE;
if (surface_a->backend->is_similar != NULL)
return surface_a->backend->is_similar (surface_a, surface_b, content);
return TRUE;
}
cairo_status_t
_cairo_surface_composite (cairo_operator_t op,
cairo_pattern_t *src,
@ -1131,7 +1195,7 @@ _cairo_surface_fill_rectangle (cairo_surface_t *surface,
int width,
int height)
{
cairo_rectangle_int16_t rect;
cairo_rectangle_int_t rect;
assert (! surface->is_snapshot);
@ -1157,7 +1221,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
* #pixman_region16_t using a solid color as the source.
* #cairo_region_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
@ -1166,34 +1230,47 @@ cairo_status_t
_cairo_surface_fill_region (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
pixman_region16_t *region)
cairo_region_t *region)
{
int num_rects = pixman_region_num_rects (region);
pixman_box16_t *boxes = pixman_region_rects (region);
cairo_rectangle_int16_t *rects;
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;
cairo_status_t status;
int i;
assert (! surface->is_snapshot);
if (!num_rects)
status = _cairo_region_get_boxes (region, &num_boxes, &boxes);
if (status)
return status;
if (num_boxes == 0)
return CAIRO_STATUS_SUCCESS;
rects = malloc (sizeof (pixman_rectangle_t) * num_rects);
if (!rects)
return CAIRO_STATUS_NO_MEMORY;
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;
}
}
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;
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;
}
status = _cairo_surface_fill_rectangles (surface, op,
color, rects, num_rects);
color, rects, num_boxes);
free (rects);
_cairo_region_boxes_fini (region, boxes);
if (rects != stack_rects)
free (rects);
return status;
}
@ -1218,7 +1295,7 @@ cairo_status_t
_cairo_surface_fill_rectangles (cairo_surface_t *surface,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int16_t *rects,
cairo_rectangle_int_t *rects,
int num_rects)
{
cairo_int_status_t status;
@ -1255,7 +1332,9 @@ _cairo_surface_paint (cairo_surface_t *surface,
assert (! surface->is_snapshot);
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (status)
return status;
if (surface->backend->paint) {
status = surface->backend->paint (surface, op, &dev_source.base);
@ -1283,20 +1362,26 @@ _cairo_surface_mask (cairo_surface_t *surface,
assert (! surface->is_snapshot);
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
_cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (status)
goto FINISH;
status = _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
if (status)
goto CLEANUP_SOURCE;
if (surface->backend->mask) {
status = surface->backend->mask (surface, op, &dev_source.base, &dev_mask.base);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto FINISH;
goto CLEANUP_MASK;
}
status = _cairo_surface_fallback_mask (surface, op, &dev_source.base, &dev_mask.base);
FINISH:
CLEANUP_MASK:
_cairo_pattern_fini (&dev_mask.base);
CLEANUP_SOURCE:
_cairo_pattern_fini (&dev_source.base);
FINISH:
return status;
}
@ -1321,7 +1406,9 @@ _cairo_surface_stroke (cairo_surface_t *surface,
assert (! surface->is_snapshot);
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (status)
return status;
if (surface->backend->stroke) {
status = surface->backend->stroke (surface, op, &dev_source.base,
@ -1360,7 +1447,9 @@ _cairo_surface_fill (cairo_surface_t *surface,
assert (! surface->is_snapshot);
_cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
status = _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
if (status)
return status;
if (surface->backend->fill) {
status = surface->backend->fill (surface, op, &dev_source.base,
@ -1430,10 +1519,7 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
traps, num_traps);
}
/* _copy_page and _show_page are unique among _cairo_surface functions
* in that they will actually return CAIRO_INT_STATUS_UNSUPPORTED
* rather than performing any fallbacks. */
cairo_int_status_t
cairo_status_t
_cairo_surface_copy_page (cairo_surface_t *surface)
{
assert (! surface->is_snapshot);
@ -1444,16 +1530,14 @@ _cairo_surface_copy_page (cairo_surface_t *surface)
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
/* It's fine if some backends don't implement copy_page */
if (surface->backend->copy_page == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_SUCCESS;
return surface->backend->copy_page (surface);
}
/* _show_page and _copy_page are unique among _cairo_surface functions
* in that they will actually return CAIRO_INT_STATUS_UNSUPPORTED
* rather than performing any fallbacks. */
cairo_int_status_t
cairo_status_t
_cairo_surface_show_page (cairo_surface_t *surface)
{
assert (! surface->is_snapshot);
@ -1464,8 +1548,9 @@ _cairo_surface_show_page (cairo_surface_t *surface)
if (surface->finished)
return CAIRO_STATUS_SURFACE_FINISHED;
/* It's fine if some backends don't implement show_page */
if (surface->backend->show_page == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_SUCCESS;
return surface->backend->show_page (surface);
}
@ -1552,7 +1637,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 #pixman_region16_t to use for clipping
* @region: the #cairo_region_t to use for clipping
* @serial: the clip serial number associated with the region
*
* This function sets the clipping for the surface to
@ -1561,7 +1646,7 @@ _cairo_surface_reset_clip (cairo_surface_t *surface)
*/
cairo_status_t
_cairo_surface_set_clip_region (cairo_surface_t *surface,
pixman_region16_t *region,
cairo_region_t *region,
unsigned int serial)
{
cairo_status_t status;
@ -1700,9 +1785,9 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
clip->path,
clip->serial);
if (clip->region)
if (clip->has_region)
return _cairo_surface_set_clip_region (surface,
clip->region,
&clip->region,
clip->serial);
}
@ -1735,7 +1820,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
if (surface->status)
return surface->status;
@ -1764,9 +1849,11 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
if (!num_glyphs)
return CAIRO_STATUS_SUCCESS;
_cairo_surface_copy_pattern_for_destination (source,
surface,
&dev_source.base);
status = _cairo_surface_copy_pattern_for_destination (source,
surface,
&dev_source.base);
if (status)
return status;
cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
@ -1787,6 +1874,11 @@ _cairo_surface_show_glyphs (cairo_surface_t *surface,
font_options);
cairo_font_options_destroy (font_options);
}
status = cairo_scaled_font_status (dev_scaled_font);
if (status) {
_cairo_pattern_fini (&dev_source.base);
return status;
}
CAIRO_MUTEX_LOCK (dev_scaled_font->mutex);
@ -1856,18 +1948,20 @@ _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_int16_t *src_rectangle,
cairo_rectangle_int16_t *mask_rectangle,
cairo_rectangle_int_t *src_rectangle,
cairo_rectangle_int_t *mask_rectangle,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height)
{
cairo_rectangle_int16_t dst_rectangle;
cairo_rectangle_int16_t drawn_rectangle;
pixman_region16_t *drawn_region;
pixman_region16_t *clear_region;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_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;
/* The area that was drawn is the area in the destination rectangle but not within
* the source or the mask.
@ -1880,34 +1974,35 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
drawn_rectangle = dst_rectangle;
if (src_rectangle)
_cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
_cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
if (mask_rectangle)
_cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
_cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
/* Now compute the area that is in dst_rectangle but not in drawn_rectangle
*/
drawn_region = _cairo_region_create_from_rectangle (&drawn_rectangle);
clear_region = _cairo_region_create_from_rectangle (&dst_rectangle);
if (!drawn_region || !clear_region) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_REGIONS;
}
_cairo_region_init_rect (&drawn_region, &drawn_rectangle);
_cairo_region_init_rect (&clear_region, &dst_rectangle);
if (pixman_region_subtract (clear_region, clear_region, drawn_region) != PIXMAN_REGION_STATUS_SUCCESS) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_REGIONS;
has_drawn_region = TRUE;
has_clear_region = TRUE;
if (_cairo_region_subtract (&clear_region, &clear_region, &drawn_region)
!= CAIRO_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 (drawn_region)
pixman_region_destroy (drawn_region);
if (clear_region)
pixman_region_destroy (clear_region);
CLEANUP_REGIONS:
if (has_drawn_region)
_cairo_region_fini (&drawn_region);
if (has_clear_region)
_cairo_region_fini (&clear_region);
return status;
}
@ -1953,9 +2048,9 @@ _cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
unsigned int width,
unsigned int height)
{
cairo_rectangle_int16_t src_tmp, mask_tmp;
cairo_rectangle_int16_t *src_rectangle = NULL;
cairo_rectangle_int16_t *mask_rectangle = NULL;
cairo_rectangle_int_t src_tmp, mask_tmp;
cairo_rectangle_int_t *src_rectangle = NULL;
cairo_rectangle_int_t *mask_rectangle = NULL;
assert (! dst->is_snapshot);
@ -2028,9 +2123,9 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
unsigned int width,
unsigned int height)
{
cairo_rectangle_int16_t src_tmp, mask_tmp;
cairo_rectangle_int16_t *src_rectangle = NULL;
cairo_rectangle_int16_t *mask_rectangle = NULL;
cairo_rectangle_int_t src_tmp, mask_tmp;
cairo_rectangle_int_t *src_rectangle = NULL;
cairo_rectangle_int_t *mask_rectangle = NULL;
assert (! dst->is_snapshot);
@ -2068,16 +2163,19 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
* Copies the given pattern, taking into account device scale and offsets
* of the destination surface.
*/
void
static cairo_status_t
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
cairo_surface_t *destination,
cairo_pattern_t *pattern_out)
{
_cairo_pattern_init_copy (pattern_out, pattern);
cairo_status_t status;
status = _cairo_pattern_init_copy (pattern_out, pattern);
if (status)
return status;
if (_cairo_surface_has_device_transform (destination)) {
cairo_matrix_t device_to_surface = destination->device_transform;
cairo_status_t status;
status = cairo_matrix_invert (&device_to_surface);
/* We only ever allow for scaling (under the implementation's
@ -2087,6 +2185,8 @@ _cairo_surface_copy_pattern_for_destination (const cairo_pattern_t *pattern,
_cairo_pattern_transform (pattern_out, &device_to_surface);
}
return CAIRO_STATUS_SUCCESS;
}
/* LocalWords: rasterized

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

@ -1,3 +1,4 @@
/* -*- 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
@ -40,15 +41,13 @@
#include "cairoint.h"
#include "cairo-svg.h"
#include "cairo-svg-test.h"
#include "cairo-svg-surface-private.h"
#include "cairo-path-fixed-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-paginated-surface-private.h"
#include "cairo-paginated-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-output-stream-private.h"
typedef struct cairo_svg_document cairo_svg_document_t;
typedef struct cairo_svg_surface cairo_svg_surface_t;
typedef struct cairo_svg_page cairo_svg_page_t;
static const int invalid_pattern_id = -1;
@ -59,7 +58,7 @@ static const cairo_svg_version_t _cairo_svg_versions[] =
CAIRO_SVG_VERSION_1_2
};
#define CAIRO_SVG_VERSION_LAST ((int)(sizeof (_cairo_svg_versions) / sizeof (_cairo_svg_versions[0])))
#define CAIRO_SVG_VERSION_LAST ARRAY_LENGTH (_cairo_svg_versions)
static cairo_bool_t
_cairo_svg_version_has_page_set_support (cairo_svg_version_t version)
@ -81,7 +80,6 @@ static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST]
struct cairo_svg_page {
unsigned int surface_id;
unsigned int clip_id;
unsigned int clip_level;
cairo_output_stream_t *xml_node;
};
@ -115,27 +113,6 @@ struct cairo_svg_document {
cairo_scaled_font_subsets_t *font_subsets;
};
struct cairo_svg_surface {
cairo_surface_t base;
cairo_content_t content;
unsigned int id;
double width;
double height;
cairo_svg_document_t *document;
cairo_output_stream_t *xml_node;
cairo_array_t page_set;
unsigned int clip_level;
unsigned int base_clip;
cairo_paginated_mode_t paginated_mode;
};
typedef struct {
unsigned int id;
cairo_meta_surface_t *meta;
@ -378,13 +355,7 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
surface->id = document->surface_id++;
surface->base_clip = document->clip_id++;
_cairo_output_stream_printf (document->xml_node_defs,
"<clipPath id=\"clip%d\">\n"
" <rect width=\"%f\" height=\"%f\"/>\n"
"</clipPath>\n",
surface->base_clip,
width, height);
surface->is_base_clip_emitted = FALSE;
surface->xml_node = _cairo_memory_stream_create ();
_cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t));
@ -398,6 +369,7 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
}
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
surface->force_fallbacks = FALSE;
surface->content = content;
return _cairo_paginated_surface_create (&surface->base,
@ -437,7 +409,6 @@ _cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
cairo_svg_page_t page;
page.surface_id = surface->id;
page.clip_id = surface->base_clip;
page.clip_level = surface->clip_level;
page.xml_node = surface->xml_node;
@ -447,7 +418,8 @@ _cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
for (i = 0; i < page.clip_level; i++)
_cairo_output_stream_printf (page.xml_node, "</g>\n");
_cairo_array_append (&surface->page_set, &page);
if (_cairo_array_append (&surface->page_set, &page) != CAIRO_STATUS_SUCCESS)
return NULL;
return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
}
@ -706,38 +678,27 @@ _cairo_svg_document_emit_font_subset (cairo_scaled_font_subset_t *font_subset,
}
}
static void
static cairo_status_t
_cairo_svg_document_emit_font_subsets (cairo_svg_document_t *document)
{
_cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
_cairo_svg_document_emit_font_subset,
document);
cairo_status_t status;
status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
_cairo_svg_document_emit_font_subset,
document);
if (status)
return status;
_cairo_scaled_font_subsets_destroy (document->font_subsets);
document->font_subsets = NULL;
return CAIRO_STATUS_SUCCESS;
}
static cairo_bool_t cairo_svg_force_fallbacks = FALSE;
/**
* _cairo_svg_test_force_fallbacks
*
* Force the SVG surface backend to use image fallbacks for every
* operation.
*
* <note>
* This function is <emphasis>only</emphasis> intended for internal
* testing use within the cairo distribution. It is not installed in
* any public header file.
* </note>
**/
void
_cairo_svg_test_force_fallbacks (void)
{
cairo_svg_force_fallbacks = TRUE;
}
static cairo_int_status_t
__cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface,
_cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *pattern)
{
@ -758,7 +719,7 @@ _cairo_svg_surface_analyze_operation (cairo_svg_surface_t *surface,
cairo_operator_t op,
const cairo_pattern_t *pattern)
{
if (__cairo_svg_surface_operation_supported (surface, op, pattern))
if (_cairo_svg_surface_operation_supported (surface, op, pattern))
return CAIRO_STATUS_SUCCESS;
else
return CAIRO_INT_STATUS_UNSUPPORTED;
@ -776,7 +737,7 @@ _cairo_svg_surface_create_similar (void *abstract_src,
static cairo_status_t
_cairo_svg_surface_finish (void *abstract_surface)
{
cairo_status_t status;
cairo_status_t status, status2;
cairo_svg_surface_t *surface = abstract_surface;
cairo_svg_document_t *document = surface->document;
cairo_svg_page_t *page;
@ -787,11 +748,15 @@ _cairo_svg_surface_finish (void *abstract_surface)
else
status = CAIRO_STATUS_SUCCESS;
_cairo_output_stream_destroy (surface->xml_node);
status2 = _cairo_output_stream_destroy (surface->xml_node);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
for (i = 0; i < surface->page_set.num_elements; i++) {
page = _cairo_array_index (&surface->page_set, i);
_cairo_output_stream_destroy (page->xml_node);
status2 = _cairo_output_stream_destroy (page->xml_node);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
}
_cairo_array_fini (&surface->page_set);
@ -924,7 +889,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_int16_t extents;
cairo_rectangle_int_t extents;
cairo_status_t status;
cairo_matrix_t p2u;
@ -941,7 +906,9 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *outp
return status;
p2u = pattern->base.matrix;
cairo_matrix_invert (&p2u);
status = cairo_matrix_invert (&p2u);
if (status)
return status;
if (pattern_id != invalid_pattern_id) {
_cairo_output_stream_printf (output,
@ -978,12 +945,14 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *outp
return status;
}
static int
static cairo_status_t
_cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
cairo_meta_surface_t *surface)
cairo_meta_surface_t *surface,
int *id)
{
cairo_status_t status;
cairo_surface_t *paginated_surface;
cairo_surface_t *svg_surface;
cairo_svg_surface_t *svg_surface;
cairo_meta_snapshot_t new_snapshot;
cairo_array_t *page_set;
@ -991,7 +960,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
cairo_meta_surface_t *meta;
cairo_meta_snapshot_t *snapshot;
unsigned int num_elements;
unsigned int i, id;
unsigned int i;
/* search in already emitted meta snapshots */
num_elements = document->meta_snapshots.num_elements;
@ -1000,7 +969,8 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
meta = snapshot->meta;
if (meta->commands.num_elements == surface->commands.num_elements &&
_cairo_array_index (&meta->commands, 0) == _cairo_array_index (&surface->commands, 0)) {
return snapshot->id;
*id = snapshot->id;
return CAIRO_STATUS_SUCCESS;
}
}
@ -1009,16 +979,41 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
meta->content,
meta->width_pixels,
meta->height_pixels);
svg_surface = _cairo_paginated_surface_get_target (paginated_surface);
svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface);
cairo_surface_set_fallback_resolution (paginated_surface,
document->owner->x_fallback_resolution,
document->owner->y_fallback_resolution);
_cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
_cairo_surface_show_page (paginated_surface);
status = _cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
if (status) {
cairo_surface_destroy (&meta->base);
return status;
}
status = _cairo_surface_show_page (paginated_surface);
if (status) {
cairo_surface_destroy (&meta->base);
return status;
}
new_snapshot.meta = meta;
new_snapshot.id = ((cairo_svg_surface_t *) svg_surface)->id;
_cairo_array_append (&document->meta_snapshots, &new_snapshot);
new_snapshot.id = svg_surface->id;
status = _cairo_array_append (&document->meta_snapshots, &new_snapshot);
if (status) {
cairo_surface_destroy (&meta->base);
return status;
}
if (!svg_surface->is_base_clip_emitted) {
svg_surface->is_base_clip_emitted = TRUE;
_cairo_output_stream_printf (document->xml_node_defs,
"<clipPath id=\"clip%d\">\n"
" <rect width=\"%f\" height=\"%f\"/>\n"
"</clipPath>\n",
svg_surface->base_clip,
svg_surface->width,
svg_surface->height);
}
if (meta->content == CAIRO_CONTENT_ALPHA) {
_cairo_svg_surface_emit_alpha_filter (document);
@ -1026,21 +1021,21 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\" "
"filter=\"url(#alpha)\">\n",
((cairo_svg_surface_t *) svg_surface)->id,
((cairo_svg_surface_t *) svg_surface)->base_clip);
svg_surface->id,
svg_surface->base_clip);
} else {
_cairo_output_stream_printf (document->xml_node_defs,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
((cairo_svg_surface_t *) svg_surface)->id,
((cairo_svg_surface_t *) svg_surface)->base_clip);
svg_surface->id,
svg_surface->base_clip);
}
contents = ((cairo_svg_surface_t *) svg_surface)->xml_node;
page_set = &((cairo_svg_surface_t *) svg_surface)->page_set;
contents = svg_surface->xml_node;
page_set = &svg_surface->page_set;
if (_cairo_memory_stream_length (contents) > 0)
_cairo_svg_surface_store_page ((cairo_svg_surface_t *) svg_surface);
_cairo_svg_surface_store_page (svg_surface);
if (page_set->num_elements > 0) {
cairo_svg_page_t *page;
@ -1051,7 +1046,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
id = new_snapshot.id;
*id = new_snapshot.id;
cairo_surface_destroy (paginated_surface);
@ -1062,7 +1057,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
/* cairo_surface_destroy (svg_surface); */
return id;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@ -1075,14 +1070,19 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
cairo_svg_document_t *document = surface->document;
cairo_meta_surface_t *meta_surface;
cairo_matrix_t p2u;
cairo_status_t status;
int id;
p2u = pattern->base.matrix;
status = cairo_matrix_invert (&p2u);
if (status)
return status;
meta_surface = (cairo_meta_surface_t *) pattern->surface;
id = _cairo_svg_surface_emit_meta_surface (document, meta_surface);
p2u = pattern->base.matrix;
cairo_matrix_invert (&p2u);
status = _cairo_svg_surface_emit_meta_surface (document, meta_surface, &id);
if (status)
return status;
if (pattern_id != invalid_pattern_id) {
_cairo_output_stream_printf (output,
@ -1152,7 +1152,7 @@ _cairo_svg_surface_emit_operator (cairo_output_stream_t *output,
_cairo_output_stream_printf (output, "comp-op: %s; ", op_str[op]);
}
static void
static cairo_status_t
_cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
cairo_solid_pattern_t *pattern,
cairo_output_stream_t *style,
@ -1166,9 +1166,11 @@ _cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface,
pattern->color.green * 100.0,
pattern->color.blue * 100.0,
pattern->color.alpha);
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
_cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface,
cairo_surface_pattern_t *pattern,
cairo_output_stream_t *style,
@ -1185,6 +1187,8 @@ _cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface,
"%s: url(#pattern%d);",
is_stroke ? "color" : "fill",
pattern_id);
return CAIRO_STATUS_SUCCESS;
}
static void
@ -1194,7 +1198,7 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
cairo_bool_t reverse_stops,
cairo_bool_t emulate_reflect)
{
pixman_gradient_stop_t *stops;
cairo_gradient_stop_t *stops;
double offset;
unsigned int n_stops;
unsigned int i;
@ -1208,16 +1212,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 / 655.35,
pattern->stops[0].color.green / 655.35,
pattern->stops[0].color.blue / 655.35,
pattern->stops[0].color.alpha / 65535.0);
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);
return;
}
if (emulate_reflect || reverse_stops) {
n_stops = emulate_reflect ? pattern->n_stops * 2 - 2: pattern->n_stops;
stops = malloc (sizeof (pixman_gradient_stop_t) * n_stops);
stops = _cairo_malloc_ab (n_stops, sizeof (cairo_gradient_stop_t));
for (i = 0; i < pattern->n_stops; i++) {
if (reverse_stops) {
@ -1256,22 +1260,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 / 655.35,
stops[i].color.green / 655.35,
stops[i].color.blue / 655.35,
stops[i].color.alpha / 65535.0);
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
stops[i].color.blue * 100.0,
stops[i].color.alpha);
}
else {
cairo_bool_t found = FALSE;
unsigned int offset_index;
pixman_color_t offset_color_start, offset_color_stop;
cairo_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;
pixman_color_t *color0, *color1;
cairo_color_t *color0, *color1;
x0 = _cairo_fixed_to_double (stops[i-1].x);
x1 = _cairo_fixed_to_double (stops[i].x);
@ -1307,20 +1311,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 / 655.35,
offset_color_start.green / 655.35,
offset_color_start.blue / 655.35,
offset_color_start.alpha / 65535.0);
offset_color_start.red * 100.0,
offset_color_start.green * 100.0,
offset_color_start.blue * 100.0,
offset_color_start.alpha);
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 / 655.35,
stops[i].color.green / 655.35,
stops[i].color.blue / 655.35,
stops[i].color.alpha / 65535.0);
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
stops[i].color.blue * 100.0,
stops[i].color.alpha);
}
for (i = 0; i < offset_index; i++) {
_cairo_output_stream_printf (output,
@ -1328,20 +1332,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 / 655.35,
stops[i].color.green / 655.35,
stops[i].color.blue / 655.35,
stops[i].color.alpha / 65535.0);
stops[i].color.red * 100.0,
stops[i].color.green * 100.0,
stops[i].color.blue * 100.0,
stops[i].color.alpha);
}
_cairo_output_stream_printf (output,
"<stop offset=\"1\" style=\""
"stop-color: rgb(%f%%,%f%%,%f%%); "
"stop-opacity: %f;\"/>\n",
offset_color_stop.red / 655.35,
offset_color_stop.green / 655.35,
offset_color_stop.blue / 655.35,
offset_color_stop.alpha / 65535.0);
offset_color_stop.red * 100.0,
offset_color_stop.green * 100.0,
offset_color_stop.blue * 100.0,
offset_color_stop.alpha);
}
@ -1366,7 +1370,7 @@ _cairo_svg_surface_emit_pattern_extend (cairo_output_stream_t *output,
}
}
static void
static cairo_status_t
_cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
cairo_linear_pattern_t *pattern,
cairo_output_stream_t *style,
@ -1375,11 +1379,17 @@ _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;
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);
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);
_cairo_output_stream_printf (document->xml_node_defs,
"<linearGradient id=\"linear%d\" "
@ -1389,8 +1399,6 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
x0, y0, x1, y1);
_cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base),
p2u = pattern->base.base.matrix;
cairo_matrix_invert (&p2u);
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
_cairo_svg_surface_emit_pattern_stops (document->xml_node_defs ,&pattern->base, 0.0, FALSE, FALSE);
@ -1404,9 +1412,11 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
document->linear_pattern_id);
document->linear_pattern_id++;
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
_cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
cairo_radial_pattern_t *pattern,
cairo_output_stream_t *style,
@ -1418,31 +1428,39 @@ _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;
pixman_circle_t *c0, *c1;
cairo_status_t status;
cairo_point_t *c0, *c1;
cairo_fixed_t radius0, radius1;
extend = pattern->base.base.extend;
if (pattern->gradient.c1.radius < pattern->gradient.c2.radius) {
c0 = &pattern->gradient.c1;
c1 = &pattern->gradient.c2;
if (pattern->r1 < pattern->r2) {
c0 = &pattern->c1;
c1 = &pattern->c2;
radius0 = pattern->r1;
radius1 = pattern->r2;
reverse_stops = FALSE;
} else {
c0 = &pattern->gradient.c2;
c1 = &pattern->gradient.c1;
c0 = &pattern->c2;
c1 = &pattern->c1;
radius0 = pattern->r2;
radius1 = pattern->r1;
reverse_stops = TRUE;
}
x0 = _cairo_fixed_to_double (c0->x);
y0 = _cairo_fixed_to_double (c0->y);
r0 = _cairo_fixed_to_double (c0->radius);
r0 = _cairo_fixed_to_double (radius0);
x1 = _cairo_fixed_to_double (c1->x);
y1 = _cairo_fixed_to_double (c1->y);
r1 = _cairo_fixed_to_double (c1->radius);
r1 = _cairo_fixed_to_double (radius1);
p2u = pattern->base.base.matrix;
cairo_matrix_invert (&p2u);
status = cairo_matrix_invert (&p2u);
if (status)
return status;
if (pattern->gradient.c1.radius == pattern->gradient.c2.radius) {
if (pattern->r1 == pattern->r2) {
_cairo_output_stream_printf (document->xml_node_defs,
"<radialGradient id=\"radial%d\" "
"gradientUnits=\"userSpaceOnUse\" "
@ -1465,19 +1483,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 / 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);
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);
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 / 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);
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);
}
} else {
@ -1571,29 +1589,28 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
document->radial_pattern_id);
document->radial_pattern_id++;
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
_cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface, cairo_pattern_t *pattern,
cairo_output_stream_t *output, cairo_bool_t is_stroke)
{
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
_cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke);
break;
return _cairo_svg_surface_emit_solid_pattern (surface, (cairo_solid_pattern_t *) pattern, output, is_stroke);
case CAIRO_PATTERN_TYPE_SURFACE:
_cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke);
break;
return _cairo_svg_surface_emit_surface_pattern (surface, (cairo_surface_pattern_t *) pattern, output, is_stroke);
case CAIRO_PATTERN_TYPE_LINEAR:
_cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
break;
return _cairo_svg_surface_emit_linear_pattern (surface, (cairo_linear_pattern_t *) pattern, output, is_stroke);
case CAIRO_PATTERN_TYPE_RADIAL:
_cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
break;
return _cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@ -1611,7 +1628,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; "
@ -1631,7 +1648,7 @@ _cairo_svg_surface_fill (void *abstract_surface,
static cairo_int_status_t
_cairo_svg_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_svg_surface_t *surface = abstract_surface;
@ -1686,6 +1703,7 @@ _cairo_svg_surface_paint (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source)
{
cairo_status_t status;
cairo_svg_surface_t *surface = abstract_surface;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
@ -1698,7 +1716,7 @@ _cairo_svg_surface_paint (void *abstract_surface,
* possible only because there is nothing between the fallback
* images and the paper, nor is anything painted above. */
/*
assert (__cairo_svg_surface_operation_supported (surface, op, source));
assert (_cairo_svg_surface_operation_supported (surface, op, source));
*/
/* Emulation of clear and source operators, when no clipping region
@ -1711,8 +1729,12 @@ _cairo_svg_surface_paint (void *abstract_surface,
* and an optimiszation in meta surface. */
if (surface->clip_level == 0 &&
(op == CAIRO_OPERATOR_CLEAR ||
op == CAIRO_OPERATOR_SOURCE)) {
_cairo_output_stream_destroy (surface->xml_node);
op == CAIRO_OPERATOR_SOURCE))
{
status = _cairo_output_stream_destroy (surface->xml_node);
if (status)
return status;
surface->xml_node = _cairo_memory_stream_create ();
if (op == CAIRO_OPERATOR_CLEAR) {
@ -1740,6 +1762,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
cairo_pattern_t *source,
cairo_pattern_t *mask)
{
cairo_status_t status;
cairo_svg_surface_t *surface = abstract_surface;
cairo_svg_document_t *document = surface->document;
cairo_output_stream_t *mask_stream;
@ -1748,7 +1771,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_svg_surface_analyze_operation (surface, op, source);
assert (__cairo_svg_surface_operation_supported (surface, op, source));
assert (_cairo_svg_surface_operation_supported (surface, op, source));
_cairo_svg_surface_emit_alpha_filter (document);
@ -1765,7 +1788,10 @@ _cairo_svg_surface_mask (void *abstract_surface,
" </g>\n"
"</mask>\n");
_cairo_memory_stream_copy (mask_stream, document->xml_node_defs);
_cairo_output_stream_destroy (mask_stream);
status = _cairo_output_stream_destroy (mask_stream);
if (status)
return status;
snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d);\"",
document->mask_id);
@ -1795,7 +1821,7 @@ _cairo_svg_surface_stroke (void *abstract_dst,
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_svg_surface_analyze_operation (surface, op, source);
assert (__cairo_svg_surface_operation_supported (surface, op, source));
assert (_cairo_svg_surface_operation_supported (surface, op, source));
switch (stroke_style->line_cap) {
case CAIRO_LINE_CAP_BUTT:
@ -1877,13 +1903,13 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
cairo_svg_document_t *document = surface->document;
cairo_path_fixed_t path;
cairo_status_t status;
unsigned int font_id, subset_id, subset_glyph_index;
cairo_scaled_font_subsets_glyph_t subset_glyph;
int i;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _cairo_svg_surface_analyze_operation (surface, op, pattern);
assert (__cairo_svg_surface_operation_supported (surface, op, pattern));
assert (_cairo_svg_surface_operation_supported (surface, op, pattern));
if (num_glyphs <= 0)
return CAIRO_STATUS_SUCCESS;
@ -1901,7 +1927,7 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets,
scaled_font, glyphs[i].index,
&font_id, &subset_id, &subset_glyph_index);
&subset_glyph);
if (status) {
glyphs += i;
num_glyphs -= i;
@ -1911,7 +1937,8 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
_cairo_output_stream_printf (surface->xml_node,
" <use xlink:href=\"#glyph%d-%d\" "
"x=\"%f\" y=\"%f\"/>\n",
font_id, subset_glyph_index,
subset_glyph.font_id,
subset_glyph.subset_glyph_index,
glyphs[i].x, glyphs[i].y);
}
@ -2034,7 +2061,7 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream,
}
/* The use of defs for font glyphs imposes no per-subset limit. */
document->font_subsets = _cairo_scaled_font_subsets_create (0, INT_MAX);
document->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
if (document->font_subsets == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
free (document);
@ -2092,7 +2119,7 @@ _cairo_svg_document_destroy (cairo_svg_document_t *document)
static cairo_status_t
_cairo_svg_document_finish (cairo_svg_document_t *document)
{
cairo_status_t status;
cairo_status_t status, status2;
cairo_output_stream_t *output = document->output_stream;
cairo_meta_snapshot_t *snapshot;
cairo_svg_surface_t *surface;
@ -2112,7 +2139,10 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
document->width, document->height,
_cairo_svg_internal_version_strings [document->svg_version]);
_cairo_svg_document_emit_font_subsets (document);
status = _cairo_svg_document_emit_font_subsets (document);
if (status)
return status;
if (_cairo_memory_stream_length (document->xml_node_glyphs) > 0 ||
_cairo_memory_stream_length (document->xml_node_defs) > 0) {
_cairo_output_stream_printf (output, "<defs>\n");
@ -2136,10 +2166,8 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
page = _cairo_array_index (&surface->page_set, i);
_cairo_output_stream_printf (output, "<page>\n");
_cairo_output_stream_printf (output,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
page->surface_id,
page->clip_id);
"<g id=\"surface%d\">\n",
page->surface_id);
_cairo_memory_stream_copy (page->xml_node, output);
_cairo_output_stream_printf (output, "</g>\n</page>\n");
}
@ -2147,20 +2175,23 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
} else if (surface->page_set.num_elements > 0) {
page = _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
_cairo_output_stream_printf (output,
"<g id=\"surface%d\" "
"clip-path=\"url(#clip%d)\">\n",
page->surface_id,
page->clip_id);
"<g id=\"surface%d\">\n",
page->surface_id);
_cairo_memory_stream_copy (page->xml_node, output);
_cairo_output_stream_printf (output, "</g>\n");
}
_cairo_output_stream_printf (output, "</svg>\n");
_cairo_output_stream_destroy (document->xml_node_glyphs);
_cairo_output_stream_destroy (document->xml_node_defs);
status = _cairo_output_stream_destroy (document->xml_node_glyphs);
status = _cairo_output_stream_destroy (output);
status2 = _cairo_output_stream_destroy (document->xml_node_defs);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
status2 = _cairo_output_stream_destroy (output);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
for (i = 0; i < document->meta_snapshots.num_elements; i++) {
snapshot = _cairo_array_index (&document->meta_snapshots, i);

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

@ -1,54 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_SVG_TEST_H
#define CAIRO_SVG_TEST_H
#include <cairo.h>
#if CAIRO_HAS_SVG_SURFACE
#include <cairo-svg.h>
CAIRO_BEGIN_DECLS
cairo_public void
_cairo_svg_test_force_fallbacks (void);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_SVG_SURFACE */
#endif /* CAIRO_SVG_TEST_H */

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

@ -1,3 +1,4 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/*
* Copyright © 2002 Keith Packard
* Copyright © 2007 Red Hat, Inc.
@ -43,7 +44,7 @@
static cairo_status_t
_cairo_traps_grow (cairo_traps_t *traps);
static cairo_status_t
static void
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right);
@ -57,10 +58,21 @@ _cairo_traps_init (cairo_traps_t *traps)
traps->num_traps = 0;
traps->traps_size = 0;
traps->traps = NULL;
traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
traps->traps = traps->traps_embedded;
traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
traps->has_limits = FALSE;
}
void
_cairo_traps_limit (cairo_traps_t *traps,
cairo_box_t *limits)
{
traps->has_limits = TRUE;
traps->limits = *limits;
}
void
@ -87,45 +99,104 @@ cairo_status_t
_cairo_traps_init_box (cairo_traps_t *traps,
cairo_box_t *box)
{
_cairo_traps_init (traps);
_cairo_traps_init (traps);
assert (traps->traps_size >= 1);
traps->num_traps = 1;
traps->traps[0].top = box->p1.y;
traps->traps[0].bottom = box->p2.y;
traps->traps[0].left.p1 = box->p1;
traps->traps[0].left.p2.x = box->p1.x;
traps->traps[0].left.p2.y = box->p2.y;
traps->traps[0].right.p1.x = box->p2.x;
traps->traps[0].right.p1.y = box->p1.y;
traps->traps[0].right.p2 = box->p2;
traps->extents = *box;
traps->status = _cairo_traps_grow (traps);
if (traps->status)
return traps->status;
traps->num_traps = 1;
traps->traps[0].top = box->p1.y;
traps->traps[0].bottom = box->p2.y;
traps->traps[0].left.p1 = box->p1;
traps->traps[0].left.p2.x = box->p1.x;
traps->traps[0].left.p2.y = box->p2.y;
traps->traps[0].right.p1.x = box->p2.x;
traps->traps[0].right.p1.y = box->p1.y;
traps->traps[0].right.p2 = box->p2;
traps->extents = *box;
return traps->status;
}
static cairo_status_t
cairo_status_t
_cairo_traps_status (cairo_traps_t *traps)
{
return traps->status;
}
static void
_cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_line_t *left, cairo_line_t *right)
{
cairo_trapezoid_t *trap;
if (traps->status)
return traps->status;
return;
if (top == bottom) {
return CAIRO_STATUS_SUCCESS;
/* Note: With the goofy trapezoid specification, (where an
* arbitrary two points on the lines can specified for the left
* and right edges), these limit checks would not work in
* general. For example, one can imagine a trapezoid entirely
* within the limits, but with two points used to specify the left
* edge entirely to the right of the limits. Fortunately, for our
* purposes, cairo will never generate such a crazy
* trapezoid. Instead, cairo always uses for its points the
* extreme positions of the edge that are visible on at least some
* trapezoid. With this constraint, it's impossible for both
* points to be outside the limits while the relevant edge is
* entirely inside the limits.
*/
if (traps->has_limits) {
/* Trivially reject if trapezoid is entirely to the right or
* to the left of the limits. */
if (left->p1.x >= traps->limits.p2.x &&
left->p2.x >= traps->limits.p2.x)
{
return;
}
if (right->p1.x <= traps->limits.p1.x &&
right->p2.x <= traps->limits.p1.x)
{
return;
}
/* Otherwise, clip the trapezoid to the limits. We only clip
* where an edge is entirely outside the limits. If we wanted
* to be more clever, we could handle cases where a trapezoid
* edge intersects the edge of the limits, but that would
* require slicing this trapezoid into multiple trapezoids,
* and I'm not sure the effort would be worth it. */
if (top < traps->limits.p1.y)
top = traps->limits.p1.y;
if (bottom > traps->limits.p2.y)
bottom = traps->limits.p2.y;
if (left->p1.x < traps->limits.p1.x &&
left->p2.x < traps->limits.p1.x)
{
left->p1.x = traps->limits.p1.x;
left->p2.x = traps->limits.p1.x;
}
if (right->p1.x > traps->limits.p2.x &&
right->p2.x > traps->limits.p2.x)
{
right->p1.x = traps->limits.p2.x;
right->p2.x = traps->limits.p2.x;
}
}
if (top >= bottom) {
return;
}
if (traps->num_traps >= traps->traps_size) {
traps->status = _cairo_traps_grow (traps);
if (traps->status)
return traps->status;
return;
}
trap = &traps->traps[traps->num_traps];
@ -157,11 +228,9 @@ _cairo_traps_add_trap (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bo
traps->extents.p2.x = right->p2.x;
traps->num_traps++;
return traps->status;
}
cairo_status_t
void
_cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cairo_fixed_t bottom,
cairo_point_t left_p1, cairo_point_t left_p2,
cairo_point_t right_p1, cairo_point_t right_p2)
@ -170,7 +239,7 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair
cairo_line_t right;
if (traps->status)
return traps->status;
return;
left.p1 = left_p1;
left.p2 = left_p2;
@ -178,7 +247,7 @@ _cairo_traps_add_trap_from_points (cairo_traps_t *traps, cairo_fixed_t top, cair
right.p1 = right_p1;
right.p2 = right_p2;
return _cairo_traps_add_trap (traps, top, bottom, &left, &right);
_cairo_traps_add_trap (traps, top, bottom, &left, &right);
}
/* make room for at least one more trap */
@ -186,27 +255,15 @@ static cairo_status_t
_cairo_traps_grow (cairo_traps_t *traps)
{
cairo_trapezoid_t *new_traps;
int old_size = traps->traps_size;
int embedded_size = sizeof (traps->traps_embedded) / sizeof (traps->traps_embedded[0]);
int new_size = 2 * MAX (old_size, 16);
/* we have a local buffer at traps->traps_embedded. try to fulfill the request
* from there. */
if (old_size < embedded_size) {
traps->traps = traps->traps_embedded;
traps->traps_size = embedded_size;
return traps->status;
}
assert (traps->num_traps <= traps->traps_size);
int new_size = 2 * MAX (traps->traps_size, 16);
if (traps->status)
return traps->status;
if (traps->traps == traps->traps_embedded) {
new_traps = malloc (new_size * sizeof (cairo_trapezoid_t));
new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
if (new_traps)
memcpy (new_traps, traps->traps, old_size * sizeof (cairo_trapezoid_t));
memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
} else {
new_traps = realloc (traps->traps, new_size * sizeof (cairo_trapezoid_t));
}
@ -219,7 +276,7 @@ _cairo_traps_grow (cairo_traps_t *traps)
traps->traps = new_traps;
traps->traps_size = new_size;
return traps->status;
return CAIRO_STATUS_SUCCESS;
}
static int
@ -292,21 +349,16 @@ _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++) {
#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
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);
}
}
}
@ -523,32 +575,30 @@ _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: 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)
* @region: a #cairo_region_t
*
* Determines if a set of trapezoids are exactly representable as a
* pixman region, and if so creates such a region.
* 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.
*
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
* Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
* or %CAIRO_STATUS_NO_MEMORY
**/
cairo_status_t
_cairo_traps_extract_region (cairo_traps_t *traps,
pixman_region16_t **region)
cairo_int_status_t
_cairo_traps_extract_region (cairo_traps_t *traps,
cairo_region_t *region)
{
int i;
/* Bail early if we have lots of traps, until we fix the code
* below to not use Union()
*/
if (traps->num_traps > 200) {
*region = NULL;
return CAIRO_STATUS_SUCCESS;
}
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;
for (i = 0; i < traps->num_traps; i++)
if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
@ -557,31 +607,45 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
&& _cairo_fixed_is_integer(traps->traps[i].bottom)
&& _cairo_fixed_is_integer(traps->traps[i].left.p1.x)
&& _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) {
*region = NULL;
return CAIRO_STATUS_SUCCESS;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
*region = pixman_region_create ();
if (traps->num_traps > ARRAY_LENGTH(stack_boxes)) {
boxes = _cairo_malloc_ab (traps->num_traps, sizeof(cairo_box_int_t));
for (i = 0; i < traps->num_traps; i++) {
int x = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
int y = _cairo_fixed_integer_part(traps->traps[i].top);
int width = _cairo_fixed_integer_part(traps->traps[i].right.p1.x) - x;
int height = _cairo_fixed_integer_part(traps->traps[i].bottom) - y;
/* 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 (width == 0 || height == 0)
continue;
if (pixman_region_union_rect (*region, *region,
x, y, width, height) != PIXMAN_REGION_STATUS_SUCCESS) {
pixman_region_destroy (*region);
if (boxes == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
}
return CAIRO_STATUS_SUCCESS;
box_count = 0;
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);
/* XXX: Sometimes we get degenerate trapezoids from the tesellator;
* skip these.
*/
if (x1 == x2 || y1 == y2)
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++;
}
status = _cairo_region_init_boxes (region, boxes, box_count);
if (boxes != stack_boxes)
free (boxes);
if (status)
_cairo_region_fini (region);
return status;
}

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

@ -34,8 +34,8 @@
* Adrian Johnson <ajohnson@redneon.com>
*/
#include <string.h>
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-truetype-subset-private.h"
@ -75,8 +75,6 @@ typedef struct _cairo_truetype_font {
static int
cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, int glyph);
#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
#define SFNT_VERSION 0x00010000
#define SFNT_STRING_MAX_LENGTH 65535
@ -84,7 +82,7 @@ static cairo_status_t
_cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
cairo_truetype_font_t **font_return)
{
cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
cairo_status_t status;
cairo_truetype_font_t *font;
const cairo_scaled_font_backend_t *backend;
tt_head_t head;
@ -131,16 +129,22 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
TT_TAG_name, 0, NULL,
&size) != CAIRO_STATUS_SUCCESS)
return CAIRO_INT_STATUS_UNSUPPORTED;
name = malloc(size);
if (name == NULL)
return CAIRO_STATUS_NO_MEMORY;
backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_name, 0, (unsigned char *) name,
&size);
status = backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_name, 0, (unsigned char *) name,
&size);
if (status)
goto fail0;
font = malloc (sizeof (cairo_truetype_font_t));
if (font == NULL)
if (font == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail0;
}
font->backend = backend;
font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs);
@ -149,15 +153,21 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font->last_offset = 0;
font->last_boundary = 0;
_cairo_array_init (&font->output, sizeof (char));
if (_cairo_array_grow_by (&font->output, 4096) != CAIRO_STATUS_SUCCESS)
status = _cairo_array_grow_by (&font->output, 4096);
if (status)
goto fail1;
font->glyphs = calloc (font->num_glyphs_in_face + 1, sizeof (subset_glyph_t));
if (font->glyphs == NULL)
goto fail2;
if (font->glyphs == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail1;
}
font->parent_to_subset = calloc (font->num_glyphs_in_face, sizeof (int));
if (font->parent_to_subset == NULL)
goto fail3;
if (font->parent_to_subset == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail2;
}
font->base.num_glyphs = 0;
font->base.x_min = (int16_t) be16_to_cpu (head.x_min);
@ -198,8 +208,11 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
if (font->base.base_font == NULL) {
font->base.base_font = malloc (30);
if (font->base.base_font == NULL)
goto fail4;
if (font->base.base_font == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail3;
}
snprintf(font->base.base_font, 30, "CairoFont-%u-%u",
scaled_font_subset->font_id,
scaled_font_subset->subset_id);
@ -213,12 +226,15 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font->base.base_font[i] = '\0';
font->base.widths = calloc (font->num_glyphs_in_face, sizeof (int));
if (font->base.widths == NULL)
goto fail5;
if (font->base.widths == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail4;
}
_cairo_array_init (&font->string_offsets, sizeof (unsigned long));
if (_cairo_array_grow_by (&font->string_offsets, 10) != CAIRO_STATUS_SUCCESS)
goto fail6;
status = _cairo_array_grow_by (&font->string_offsets, 10);
if (status)
goto fail5;
font->status = CAIRO_STATUS_SUCCESS;
@ -226,21 +242,22 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
return CAIRO_STATUS_SUCCESS;
fail6:
free (font->base.widths);
fail5:
free (font->base.base_font);
_cairo_array_fini (&font->string_offsets);
free (font->base.widths);
fail4:
free (font->parent_to_subset);
free (font->base.base_font);
fail3:
free (font->glyphs);
free (font->parent_to_subset);
fail2:
_cairo_array_fini (&font->output);
free (font->glyphs);
fail1:
_cairo_array_fini (&font->output);
free (font);
fail0:
if (name)
free (name);
return status;
}
@ -322,19 +339,27 @@ cairo_truetype_font_align_output (cairo_truetype_font_t *font)
return aligned;
}
static void
static cairo_status_t
cairo_truetype_font_check_boundary (cairo_truetype_font_t *font,
unsigned long boundary)
{
cairo_status_t status;
if (boundary - font->last_offset > SFNT_STRING_MAX_LENGTH)
{
_cairo_array_append(&font->string_offsets, &font->last_boundary);
status = _cairo_array_append (&font->string_offsets,
&font->last_boundary);
if (status)
return status;
font->last_offset = font->last_boundary;
}
font->last_boundary = boundary;
return CAIRO_STATUS_SUCCESS;
}
static int
static cairo_status_t
cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -360,12 +385,12 @@ cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
cairo_truetype_font_write_be16 (font, 4); /* searchrange */
cairo_truetype_font_write_be16 (font, 1); /* entry selector */
cairo_truetype_font_write_be16 (font, 0); /* rangeshift */
cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 2); /* end count[0] */
cairo_truetype_font_write_be16 (font, 0xf000 + font->base.num_glyphs - 1); /* end count[0] */
cairo_truetype_font_write_be16 (font, 0xffff); /* end count[1] */
cairo_truetype_font_write_be16 (font, 0); /* reserved */
cairo_truetype_font_write_be16 (font, 0xf000); /* startCode[0] */
cairo_truetype_font_write_be16 (font, 0xffff); /* startCode[1] */
cairo_truetype_font_write_be16 (font, 0x1001); /* delta[0] */
cairo_truetype_font_write_be16 (font, 0x1000); /* delta[0] */
cairo_truetype_font_write_be16 (font, 1); /* delta[1] */
cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[0] */
cairo_truetype_font_write_be16 (font, 0); /* rangeOffset[1] */
@ -373,17 +398,17 @@ cairo_truetype_font_write_cmap_table (cairo_truetype_font_t *font,
/* Output a format 6 encoding table. */
cairo_truetype_font_write_be16 (font, 6);
cairo_truetype_font_write_be16 (font, 10 + 2 * (font->base.num_glyphs - 1));
cairo_truetype_font_write_be16 (font, 10 + 2 * font->base.num_glyphs);
cairo_truetype_font_write_be16 (font, 0);
cairo_truetype_font_write_be16 (font, 0); /* First character */
cairo_truetype_font_write_be16 (font, font->base.num_glyphs);
for (i = 0; i < font->base.num_glyphs; i++)
cairo_truetype_font_write_be16 (font, i + 1);
cairo_truetype_font_write_be16 (font, i);
return font->status;
}
static int
static cairo_status_t
cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -397,11 +422,17 @@ cairo_truetype_font_write_generic_table (cairo_truetype_font_t *font,
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
return font->status;
}
status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
/* XXX: Need to check status here. */
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, buffer, &size);
return 0;
if (status)
return status;
status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, buffer, &size);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
static void
@ -438,11 +469,10 @@ cairo_truetype_font_remap_composite_glyph (cairo_truetype_font_t *font,
} while (has_more_components);
}
static int
static cairo_status_t
cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned long start_offset, index, size, next;
tt_head_t header;
unsigned long begin, end;
@ -455,8 +485,11 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
} u;
size = sizeof (tt_head_t);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_head, 0, (unsigned char*) &header, &size);
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_head, 0,
(unsigned char*) &header, &size);
if (font->status)
return font->status;
if (be16_to_cpu (header.index_to_loc_format) == 0)
size = sizeof (int16_t) * (font->num_glyphs_in_face + 1);
@ -468,6 +501,7 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
font->status = CAIRO_STATUS_NO_MEMORY;
return font->status;
}
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_loca, 0, u.bytes, &size) != CAIRO_STATUS_SUCCESS) {
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
@ -489,15 +523,23 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
size = end - begin;
next = cairo_truetype_font_align_output (font);
cairo_truetype_font_check_boundary (font, next);
font->status = cairo_truetype_font_check_boundary (font, next);
if (font->status)
break;
font->glyphs[i].location = next - start_offset;
status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
if (status)
font->status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
if (font->status)
break;
if (size != 0) {
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_glyf, begin, buffer, &size);
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_glyf, begin, buffer, &size);
if (font->status)
break;
cairo_truetype_font_remap_composite_glyph (font, buffer);
}
}
@ -510,7 +552,7 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font,
return font->status;
}
static int
static cairo_status_t
cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -518,36 +560,52 @@ cairo_truetype_font_write_head_table (cairo_truetype_font_t *font,
unsigned long size;
size = 0;
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, NULL, &size);
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, NULL, &size);
if (font->status)
return font->status;
font->checksum_index = _cairo_array_num_elements (&font->output) + 8;
font->status = cairo_truetype_font_allocate_write_buffer (font, size, &buffer);
font->backend->load_truetype_table( font->scaled_font_subset->scaled_font,
tag, 0, buffer, &size);
if (font->status)
return font->status;
font->status = font->backend->load_truetype_table( font->scaled_font_subset->scaled_font,
tag, 0, buffer, &size);
if (font->status)
return font->status;
/* set checkSumAdjustment to 0 for table checksum calcualtion */
*(uint32_t *)(buffer + 8) = 0;
return font->status;
}
static int cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag)
static cairo_status_t
cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long tag)
{
tt_hhea_t *hhea;
unsigned long size;
size = sizeof (tt_hhea_t);
font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &hhea);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, (unsigned char *) hhea, &size);
if (font->status)
return font->status;
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, (unsigned char *) hhea, &size);
if (font->status)
return font->status;
hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs));
return font->status;
}
static int
static cairo_status_t
cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
unsigned long tag)
{
cairo_status_t status;
unsigned long size;
unsigned long long_entry_size;
unsigned long short_entry_size;
@ -557,15 +615,22 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
int num_hmetrics;
size = sizeof (tt_hhea_t);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hhea, 0, (unsigned char*) &hhea, &size);
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hhea, 0,
(unsigned char*) &hhea, &size);
if (font->status)
return font->status;
num_hmetrics = be16_to_cpu(hhea.num_hmetrics);
for (i = 0; i < font->base.num_glyphs; i++) {
long_entry_size = 2 * sizeof (int16_t);
short_entry_size = sizeof (int16_t);
status = cairo_truetype_font_allocate_write_buffer (font, long_entry_size,
(unsigned char **) &p);
font->status = cairo_truetype_font_allocate_write_buffer (font, long_entry_size,
(unsigned char **) &p);
if (font->status)
return font->status;
if (font->glyphs[i].parent_index < num_hmetrics) {
if (font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
@ -584,11 +649,13 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
font->status = CAIRO_INT_STATUS_UNSUPPORTED;
return font->status;
}
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
num_hmetrics * long_entry_size +
(font->glyphs[i].parent_index - num_hmetrics) * short_entry_size,
(unsigned char *) (p + 1), &short_entry_size);
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
num_hmetrics * long_entry_size +
(font->glyphs[i].parent_index - num_hmetrics) * short_entry_size,
(unsigned char *) (p + 1), &short_entry_size);
if (font->status)
return font->status;
}
font->base.widths[i] = be16_to_cpu (p[0]);
}
@ -596,7 +663,7 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font,
return font->status;
}
static int
static cairo_status_t
cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -605,8 +672,11 @@ cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
unsigned long size;
size = sizeof(tt_head_t);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_head, 0, (unsigned char*) &header, &size);
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_head, 0,
(unsigned char*) &header, &size);
if (font->status)
return font->status;
if (be16_to_cpu (header.index_to_loc_format) == 0)
{
@ -620,7 +690,7 @@ cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font,
return font->status;
}
static int
static cairo_status_t
cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
unsigned long tag)
{
@ -629,39 +699,15 @@ cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font,
size = sizeof (tt_maxp_t);
font->status = cairo_truetype_font_allocate_write_buffer (font, size, (unsigned char **) &maxp);
font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, (unsigned char *) maxp, &size);
if (font->status)
return font->status;
font->status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
tag, 0, (unsigned char *) maxp, &size);
if (font->status)
return font->status;
maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs);
return font->status;
}
static int
cairo_truetype_font_write_post_table (cairo_truetype_font_t *font,
unsigned long tag)
{
char buf[10];
int n;
unsigned i;
cairo_truetype_font_write_be32 (font, 0x00020000);
cairo_truetype_font_write_be32 (font, 0);
cairo_truetype_font_write_be16 (font, 0);
cairo_truetype_font_write_be16 (font, 1);
cairo_truetype_font_write_be32 (font, 0);
cairo_truetype_font_write_be32 (font, 0);
cairo_truetype_font_write_be32 (font, 0);
cairo_truetype_font_write_be32 (font, 0);
cairo_truetype_font_write_be32 (font, 0);
cairo_truetype_font_write_be16 (font, font->base.num_glyphs);
cairo_truetype_font_write_be16 (font, 0);
for (i = 1; i < font->base.num_glyphs; i++)
cairo_truetype_font_write_be16 (font, i + 257);
for (i = 1; i < font->base.num_glyphs; i++) {
n = snprintf(buf + 1, 9, "g%d", i - 1);
buf[0] = n;
cairo_truetype_font_write (font, buf, n + 1);
}
return font->status;
}
@ -669,7 +715,7 @@ cairo_truetype_font_write_post_table (cairo_truetype_font_t *font,
typedef struct table table_t;
struct table {
unsigned long tag;
int (*write) (cairo_truetype_font_t *font, unsigned long tag);
cairo_status_t (*write) (cairo_truetype_font_t *font, unsigned long tag);
int pos; /* position in the font directory */
};
@ -692,8 +738,7 @@ static const table_t truetype_tables[] = {
{ TT_TAG_loca, cairo_truetype_font_write_loca_table, 7 },
{ TT_TAG_maxp, cairo_truetype_font_write_maxp_table, 8 },
{ TT_TAG_name, cairo_truetype_font_write_generic_table, 9 },
{ TT_TAG_post, cairo_truetype_font_write_post_table, 10 },
{ TT_TAG_prep, cairo_truetype_font_write_generic_table, 11 },
{ TT_TAG_prep, cairo_truetype_font_write_generic_table, 10 },
};
static cairo_status_t
@ -776,6 +821,7 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font,
const unsigned long **string_offsets,
unsigned long *num_strings)
{
cairo_status_t status;
unsigned long start, end, next;
uint32_t checksum, *checksum_location;
unsigned int i;
@ -795,7 +841,12 @@ cairo_truetype_font_generate (cairo_truetype_font_t *font,
next = cairo_truetype_font_align_output (font);
cairo_truetype_font_update_entry (font, truetype_tables[i].pos, truetype_tables[i].tag,
start, end);
cairo_truetype_font_check_boundary (font, next);
status = cairo_truetype_font_check_boundary (font, next);
if (status) {
font->status = status;
goto fail;
}
start = next;
}
@ -832,7 +883,7 @@ cairo_status_t
_cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
cairo_scaled_font_subset_t *font_subset)
{
cairo_truetype_font_t *font;
cairo_truetype_font_t *font = NULL;
cairo_status_t status;
const char *data = NULL; /* squelch bogus compiler warning */
unsigned long length = 0; /* squelch bogus compiler warning */
@ -845,10 +896,6 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
if (status)
return status;
/* Add the notdef glyph. This is required at glyph index 0
* in the subsetted font. */
cairo_truetype_font_use_glyph (font, 0);
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
parent_glyph = font->scaled_font_subset->glyphs[i];
cairo_truetype_font_use_glyph (font, parent_glyph);
@ -860,19 +907,22 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
goto fail1;
truetype_subset->base_font = strdup (font->base.base_font);
if (truetype_subset->base_font == NULL)
if (truetype_subset->base_font == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail1;
}
/* The widths array returned must contain only widths for
* the glyphs in font_subset. The notdef glyph at index 0
* and any subglyphs appended after font_subset->num_glyphs
* are omitted. */
/* The widths array returned must contain only widths for the
* glyphs in font_subset. Any subglyphs appended after
* font_subset->num_glyphs are omitted. */
truetype_subset->widths = calloc (sizeof (double),
font->scaled_font_subset->num_glyphs);
if (truetype_subset->widths == NULL)
if (truetype_subset->widths == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail2;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
truetype_subset->widths[i] = (double)font->base.widths[i + 1]/font->base.units_per_em;
truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em;
truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em;
truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em;
@ -882,19 +932,28 @@ _cairo_truetype_subset_init (cairo_truetype_subset_t *truetype_subset,
truetype_subset->descent = (double)font->base.descent/font->base.units_per_em;
truetype_subset->data = malloc (length);
if (truetype_subset->data == NULL)
if (truetype_subset->data == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail3;
}
memcpy (truetype_subset->data, data, length);
truetype_subset->data_length = length;
offsets_length = num_strings * sizeof (unsigned long);
truetype_subset->string_offsets = malloc (offsets_length);
if (truetype_subset->string_offsets == NULL)
goto fail4;
if (num_strings) {
offsets_length = num_strings * sizeof (unsigned long);
truetype_subset->string_offsets = malloc (offsets_length);
if (truetype_subset->string_offsets == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail4;
}
memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
truetype_subset->num_string_offsets = num_strings;
memcpy (truetype_subset->string_offsets, string_offsets, offsets_length);
truetype_subset->num_string_offsets = num_strings;
} else {
truetype_subset->string_offsets = NULL;
truetype_subset->num_string_offsets = 0;
}
cairo_truetype_font_destroy (font);

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

@ -39,6 +39,11 @@
#include "cairo-path-fixed-private.h"
#include "cairo-output-stream-private.h"
typedef enum {
CAIRO_CHARSTRING_TYPE1,
CAIRO_CHARSTRING_TYPE2,
} cairo_charstring_type_t;
typedef struct _cairo_type1_font {
int *widths;
@ -90,7 +95,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
font_face = cairo_scaled_font_get_font_face (scaled_font_subset->scaled_font);
cairo_matrix_init_scale (&font_matrix, 1000, 1000);
cairo_matrix_init_scale (&font_matrix, 1000, -1000);
cairo_matrix_init_identity (&ctm);
_cairo_font_options_init_default (&font_options);
@ -101,7 +106,7 @@ cairo_type1_font_create (cairo_scaled_font_subset_t *scaled_font_subset,
&font_matrix,
&ctm,
&font_options);
if (font->type1_scaled_font == NULL)
if (font->type1_scaled_font->status)
goto fail;
_cairo_array_init (&font->contents, sizeof (unsigned char));
@ -156,7 +161,9 @@ charstring_encode_command (cairo_array_t *data, int command)
* bytes that will be used is 5.
*/
static void
charstring_encode_integer (cairo_array_t *data, int i)
charstring_encode_integer (cairo_array_t *data,
int i,
cairo_charstring_type_t type)
{
cairo_status_t status;
int orig_size;
@ -174,11 +181,19 @@ charstring_encode_integer (cairo_array_t *data, int i)
*p++ = (i >> 8)+ 251;
*p++ = i & 0xff;
} else {
*p++ = 0xff;
*p++ = i >> 24;
*p++ = (i >> 16) & 0xff;
*p++ = (i >> 8) & 0xff;
*p++ = i & 0xff;
if (type == CAIRO_CHARSTRING_TYPE1) {
*p++ = 0xff;
*p++ = i >> 24;
*p++ = (i >> 16) & 0xff;
*p++ = (i >> 8) & 0xff;
*p++ = i & 0xff;
} else {
*p++ = 0xff;
*p++ = (i >> 8) & 0xff;
*p++ = i & 0xff;
*p++ = 0;
*p++ = 0;
}
}
/* Ensure the array doesn't grow, which allows this function to
@ -193,6 +208,7 @@ charstring_encode_integer (cairo_array_t *data, int i)
typedef struct _ps_path_info {
cairo_array_t *data;
int current_x, current_y;
cairo_charstring_type_t type;
} t1_path_info_t;
static cairo_status_t
@ -209,8 +225,8 @@ _charstring_move_to (void *closure,
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
charstring_encode_integer (path_info->data, dx);
charstring_encode_integer (path_info->data, dy);
charstring_encode_integer (path_info->data, dx, path_info->type);
charstring_encode_integer (path_info->data, dy, path_info->type);
path_info->current_x += dx;
path_info->current_y += dy;
@ -233,8 +249,8 @@ _charstring_line_to (void *closure,
dx = _cairo_fixed_integer_part (point->x) - path_info->current_x;
dy = _cairo_fixed_integer_part (point->y) - path_info->current_y;
charstring_encode_integer (path_info->data, dx);
charstring_encode_integer (path_info->data, dy);
charstring_encode_integer (path_info->data, dx, path_info->type);
charstring_encode_integer (path_info->data, dy, path_info->type);
path_info->current_x += dx;
path_info->current_y += dy;
@ -263,12 +279,12 @@ _charstring_curve_to (void *closure,
dy2 = _cairo_fixed_integer_part (point2->y) - path_info->current_y - dy1;
dx3 = _cairo_fixed_integer_part (point3->x) - path_info->current_x - dx1 - dx2;
dy3 = _cairo_fixed_integer_part (point3->y) - path_info->current_y - dy1 - dy2;
charstring_encode_integer (path_info->data, dx1);
charstring_encode_integer (path_info->data, dy1);
charstring_encode_integer (path_info->data, dx2);
charstring_encode_integer (path_info->data, dy2);
charstring_encode_integer (path_info->data, dx3);
charstring_encode_integer (path_info->data, dy3);
charstring_encode_integer (path_info->data, dx1, path_info->type);
charstring_encode_integer (path_info->data, dy1, path_info->type);
charstring_encode_integer (path_info->data, dx2, path_info->type);
charstring_encode_integer (path_info->data, dy2, path_info->type);
charstring_encode_integer (path_info->data, dx3, path_info->type);
charstring_encode_integer (path_info->data, dy3, path_info->type);
path_info->current_x += dx1 + dx2 + dx3;
path_info->current_y += dy1 + dy2 + dy3;
charstring_encode_command (path_info->data, CHARSTRING_rcurveto);
@ -282,6 +298,9 @@ _charstring_close_path (void *closure)
cairo_status_t status;
t1_path_info_t *path_info = (t1_path_info_t *) closure;
if (path_info->type == CAIRO_CHARSTRING_TYPE2)
return CAIRO_STATUS_SUCCESS;
status = _cairo_array_grow_by (path_info->data, 2);
if (status)
return status;
@ -309,7 +328,7 @@ charstring_encrypt (cairo_array_t *data)
}
static cairo_int_status_t
create_notdef_charstring (cairo_array_t *data)
create_notdef_charstring (cairo_array_t *data, cairo_charstring_type_t type)
{
cairo_status_t status;
@ -320,13 +339,15 @@ create_notdef_charstring (cairo_array_t *data)
if (status)
return status;
charstring_encode_integer (data, 0);
charstring_encode_integer (data, 0);
if (type == CAIRO_CHARSTRING_TYPE1) {
charstring_encode_integer (data, 0, type);
charstring_encode_integer (data, 0, type);
/* The width and height is arbitrary. */
charstring_encode_integer (data, 500);
charstring_encode_integer (data, 500);
charstring_encode_command (data, CHARSTRING_sbw);
/* The width and height is arbitrary. */
charstring_encode_integer (data, 500, type);
charstring_encode_integer (data, 500, type);
charstring_encode_command (data, CHARSTRING_sbw);
}
charstring_encode_command (data, CHARSTRING_endchar);
@ -334,10 +355,11 @@ create_notdef_charstring (cairo_array_t *data)
}
static cairo_int_status_t
cairo_type1_font_create_charstring (cairo_type1_font_t *font,
int subset_index,
int glyph_index,
cairo_array_t *data)
cairo_type1_font_create_charstring (cairo_type1_font_t *font,
int subset_index,
int glyph_index,
cairo_charstring_type_t type,
cairo_array_t *data)
{
cairo_int_status_t status;
cairo_scaled_glyph_t *scaled_glyph;
@ -369,21 +391,29 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
if (metrics->y_bearing + metrics->height > font->y_max)
font->y_max = metrics->y_bearing + metrics->height;
}
font->widths[subset_index] = metrics->width;
font->widths[subset_index] = metrics->x_advance;
status = _cairo_array_grow_by (data, 30);
if (status)
return status;
charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing);
charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing);
charstring_encode_integer (data, (int) scaled_glyph->metrics.width);
charstring_encode_integer (data, (int) scaled_glyph->metrics.height);
charstring_encode_command (data, CHARSTRING_sbw);
if (type == CAIRO_CHARSTRING_TYPE1) {
charstring_encode_integer (data, (int) scaled_glyph->metrics.x_bearing, type);
charstring_encode_integer (data, (int) scaled_glyph->metrics.y_bearing, type);
charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
charstring_encode_integer (data, (int) scaled_glyph->metrics.height, type);
charstring_encode_command (data, CHARSTRING_sbw);
path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
} else {
charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
path_info.current_x = 0;
path_info.current_y = 0;
}
path_info.data = data;
path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
path_info.type = type;
status = _cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD,
_charstring_move_to,
@ -421,7 +451,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
"2 index /CharStrings %d dict dup begin\n",
font->scaled_font_subset->num_glyphs + 1);
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_truncate (&data, 0);
/* four "random" bytes required by encryption algorithm */
status = _cairo_array_append_multiple (&data, zeros, 4);
@ -429,6 +459,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
goto fail;
status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i],
CAIRO_CHARSTRING_TYPE1,
&data);
if (status)
goto fail;
@ -448,7 +479,7 @@ cairo_type1_font_write_charstrings (cairo_type1_font_t *font,
status = _cairo_array_append_multiple (&data, zeros, 4);
if (status)
goto fail;
status = create_notdef_charstring (&data);
status = create_notdef_charstring (&data, CAIRO_CHARSTRING_TYPE1);
if (status)
goto fail;
charstring_encrypt (&data);
@ -468,28 +499,18 @@ static void
cairo_type1_font_write_header (cairo_type1_font_t *font,
const char *name)
{
cairo_matrix_t matrix;
unsigned int i;
const char spaces[50] = " ";
matrix = font->type1_scaled_font->scale;
matrix.xy = -matrix.xy;
matrix.yy = -matrix.yy;
cairo_matrix_invert (&matrix);
_cairo_output_stream_printf (font->output,
"%%!FontType1-1.1 %s 1.0\n"
"11 dict begin\n"
"/FontName /%s def\n"
"/PaintType 0 def\n"
"/FontType 1 def\n"
"/FontMatrix [%f %f %f %f 0 0] readonly def\n",
"/FontMatrix [0.001 0 0 0.001 0 0] readonly def\n",
name,
name,
matrix.xx,
matrix.yx,
matrix.xy,
matrix.yy);
name);
/* We don't know the bbox values until after the charstrings have
* been generated. Reserve some space and fill in the bbox
@ -558,6 +579,7 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
const char *name)
{
cairo_int_status_t status;
cairo_status_t status2;
cairo_output_stream_t *encrypted_output;
font->eexec_key = CAIRO_TYPE1_PRIVATE_DICT_KEY;
@ -597,10 +619,10 @@ cairo_type1_font_write_private_dict (cairo_type1_font_t *font,
"dup /FontName get exch definefont pop\n"
"mark currentfile closefile\n");
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_output_stream_get_status (encrypted_output);
fail:
_cairo_output_stream_destroy (encrypted_output);
status2 = _cairo_output_stream_destroy (encrypted_output);
if (status == CAIRO_STATUS_SUCCESS)
status = status2;
return status;
}
@ -672,14 +694,18 @@ cairo_type1_font_generate (cairo_type1_font_t *font, const char *name)
return CAIRO_STATUS_SUCCESS;
}
static void
static cairo_status_t
cairo_type1_font_destroy (cairo_type1_font_t *font)
{
cairo_status_t status;
free (font->widths);
cairo_scaled_font_destroy (font->type1_scaled_font);
_cairo_array_fini (&font->contents);
_cairo_output_stream_destroy (font->output);
status = _cairo_output_stream_destroy (font->output);
free (font);
return status;
}
static cairo_status_t
@ -745,14 +771,14 @@ _cairo_type1_fallback_init_internal (cairo_type1_subset_t *type1_subset,
type1_subset->data_length = font->data_size;
type1_subset->trailer_length = font->trailer_size;
cairo_type1_font_destroy (font);
return CAIRO_STATUS_SUCCESS;
return cairo_type1_font_destroy (font);
fail3:
free (type1_subset->widths);
fail2:
free (type1_subset->base_font);
fail1:
/* status is already set, ignore further errors */
cairo_type1_font_destroy (font);
return status;
@ -785,3 +811,83 @@ _cairo_type1_fallback_fini (cairo_type1_subset_t *subset)
free (subset->widths);
free (subset->data);
}
cairo_status_t
_cairo_type2_charstrings_init (cairo_type2_charstrings_t *type2_subset,
cairo_scaled_font_subset_t *scaled_font_subset)
{
cairo_type1_font_t *font;
cairo_status_t status;
unsigned int i;
cairo_array_t charstring;
status = cairo_type1_font_create (scaled_font_subset, &font, FALSE);
if (status)
return status;
_cairo_array_init (&type2_subset->charstrings, sizeof (cairo_array_t));
type2_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
if (type2_subset->widths == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto fail1;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
_cairo_array_init (&charstring, sizeof (unsigned char));
status = _cairo_array_grow_by (&charstring, 32);
if (status)
goto fail2;
if (i == 0) {
status = create_notdef_charstring (&charstring, CAIRO_CHARSTRING_TYPE2);
} else {
status = cairo_type1_font_create_charstring (font, i,
font->scaled_font_subset->glyphs[i],
CAIRO_CHARSTRING_TYPE2,
&charstring);
}
if (status)
goto fail2;
status = _cairo_array_append (&type2_subset->charstrings, &charstring);
if (status)
goto fail2;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
type2_subset->widths[i] = font->widths[i];
type2_subset->x_min = (int) font->x_min;
type2_subset->y_min = (int) font->y_min;
type2_subset->x_max = (int) font->x_max;
type2_subset->y_max = (int) font->y_max;
type2_subset->ascent = (int) font->y_max;
type2_subset->descent = (int) font->y_min;
cairo_type1_font_destroy (font);
return CAIRO_STATUS_SUCCESS;
fail2:
_cairo_array_fini (&charstring);
_cairo_type2_charstrings_fini (type2_subset);
fail1:
cairo_type1_font_destroy (font);
return status;
}
void
_cairo_type2_charstrings_fini (cairo_type2_charstrings_t *type2_subset)
{
unsigned int i, num_charstrings;
cairo_array_t *charstring;
num_charstrings = _cairo_array_num_elements (&type2_subset->charstrings);
for (i = 0; i < num_charstrings; i++) {
charstring = _cairo_array_index (&type2_subset->charstrings, i);
_cairo_array_fini (charstring);
}
_cairo_array_fini (&type2_subset->charstrings);
free (type2_subset->widths);
}

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

@ -46,6 +46,8 @@
#include FT_OUTLINE_H
#include FT_TYPE1_TABLES_H
#include <ctype.h>
typedef struct _cairo_type1_font_subset {
cairo_scaled_font_subset_t *scaled_font_subset;
@ -1133,9 +1135,6 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset,
cairo_type1_font_subset_use_glyph (font, parent_glyph);
}
/* Pull in the .notdef glyph */
cairo_type1_font_subset_use_glyph (font, 0);
status = cairo_type1_font_subset_generate (font, name);
if (status)
goto fail1;
@ -1195,3 +1194,30 @@ _cairo_type1_subset_fini (cairo_type1_subset_t *subset)
free (subset->widths);
free (subset->data);
}
cairo_bool_t
_cairo_type1_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font)
{
cairo_ft_unscaled_font_t *unscaled;
FT_Face face;
PS_FontInfoRec font_info;
cairo_bool_t is_type1 = FALSE;
unscaled = (cairo_ft_unscaled_font_t *) _cairo_ft_scaled_font_get_unscaled_font (scaled_font);
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return FALSE;
if (FT_Get_PS_Font_Info(face, &font_info) == 0)
is_type1 = TRUE;
/* OpenType/CFF fonts also have a PS_FontInfoRec */
#if HAVE_FT_LOAD_SFNT_TABLE
if (FT_IS_SFNT (face))
is_type1 = FALSE;
#endif
_cairo_ft_unscaled_font_unlock_face (unscaled);
return is_type1;
}

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

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

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

@ -64,6 +64,12 @@
# ifndef UINT16_MAX
# define UINT16_MAX (65535)
# endif
# ifndef INT32_MIN
# define INT32_MIN (-2147483647-1)
# endif
# ifndef INT32_MAX
# define INT32_MAX (2147483647)
# endif
#else
#error Cannot find definitions for fixed-width integral types (uint8_t, uint32_t, etc.)
#endif

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

@ -32,9 +32,8 @@
* Contributor(s):
*/
#include <string.h>
#include <stdio.h>
#include "cairoint.h"
#include "cairo-win32-private.h"
#ifndef SPI_GETFONTSMOOTHINGTYPE
@ -227,15 +226,9 @@ _get_system_quality (void)
}
}
/* If face_hfont is non-NULL then font_matrix must be a simple scale by some
* factor S, ctm must be the identity, logfont->lfHeight must be -S,
* logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
* all be 0, and face_hfont is the result of calling CreateFontIndirectW on
* logfont.
*/
static cairo_scaled_font_t *
_win32_scaled_font_create (LOGFONTW *logfont,
HFONT face_hfont,
HFONT hfont,
cairo_font_face_t *font_face,
const cairo_matrix_t *font_matrix,
const cairo_matrix_t *ctm,
@ -245,8 +238,6 @@ _win32_scaled_font_create (LOGFONTW *logfont,
cairo_matrix_t scale;
cairo_status_t status;
_cairo_win32_initialize ();
f = malloc (sizeof(cairo_win32_scaled_font_t));
if (f == NULL)
return NULL;
@ -283,29 +274,22 @@ _win32_scaled_font_create (LOGFONTW *logfont,
}
f->em_square = 0;
f->scaled_hfont = NULL;
f->scaled_hfont = hfont;
f->unscaled_hfont = NULL;
if (f->quality == logfont->lfQuality ||
(logfont->lfQuality == DEFAULT_QUALITY &&
options->antialias == CAIRO_ANTIALIAS_DEFAULT)) {
/* If face_hfont is non-NULL, then we can use it to avoid creating our
* own --- because the constraints on face_hfont mentioned above
* guarantee it was created in exactly the same way that
* _win32_scaled_font_get_scaled_hfont would create it.
*/
f->scaled_hfont = face_hfont;
}
/* don't delete the hfont if we're using the one passed in to us */
f->delete_scaled_hfont = !f->scaled_hfont;
/* don't delete the hfont if it was passed in to us */
f->delete_scaled_hfont = !hfont;
cairo_matrix_multiply (&scale, font_matrix, ctm);
_compute_transform (f, &scale);
_cairo_scaled_font_init (&f->base, font_face,
font_matrix, ctm, options,
&cairo_win32_scaled_font_backend);
status = _cairo_scaled_font_init (&f->base, font_face,
font_matrix, ctm, options,
&cairo_win32_scaled_font_backend);
if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_win32_scaled_font_set_metrics (f);
status = _cairo_win32_scaled_font_set_metrics (f);
if (status) {
cairo_scaled_font_destroy (&f->base);
return NULL;
@ -487,8 +471,6 @@ _cairo_win32_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
int face_name_len;
cairo_status_t status;
_cairo_win32_initialize ();
status = _cairo_utf8_to_utf16 (toy_face->family, -1,
&face_name, &face_name_len);
if (status)
@ -631,8 +613,8 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
dx = NULL;
}
glyph_indices = malloc (sizeof (WCHAR) * buffer_size);
dx = malloc (sizeof (int) * buffer_size);
glyph_indices = _cairo_malloc_ab (buffer_size, sizeof (WCHAR));
dx = _cairo_malloc_ab (buffer_size, sizeof (int));
if (!glyph_indices || !dx) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL2;
@ -663,7 +645,7 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font,
}
*num_glyphs = gcp_results.nGlyphs;
*glyphs = malloc (sizeof (cairo_glyph_t) * gcp_results.nGlyphs);
*glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t));
if (!*glyphs) {
status = CAIRO_STATUS_NO_MEMORY;
goto FAIL2;
@ -1471,16 +1453,14 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font
}
free(buffer);
CLEANUP_FONT:
_cairo_scaled_glyph_set_path (scaled_glyph,
&scaled_font->base,
path);
CLEANUP_FONT:
cairo_win32_scaled_font_done_font (&scaled_font->base);
CLEANUP_PATH:
if (status != CAIRO_STATUS_SUCCESS)
_cairo_path_fixed_destroy (path);
@ -1503,11 +1483,6 @@ const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = {
typedef struct _cairo_win32_font_face cairo_win32_font_face_t;
/* If hfont is non-NULL then logfont->lfHeight must be -S for some S,
* logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must
* all be 0, and hfont is the result of calling CreateFontIndirectW on
* logfont.
*/
struct _cairo_win32_font_face {
cairo_font_face_t base;
LOGFONTW logfont;
@ -1521,14 +1496,6 @@ _cairo_win32_font_face_destroy (void *abstract_face)
{
}
static cairo_bool_t
_is_scale (const cairo_matrix_t *matrix, double scale)
{
return matrix->xx == scale && matrix->yy == scale &&
matrix->xy == 0. && matrix->yx == 0. &&
matrix->x0 == 0. && matrix->y0 == 0.;
}
static cairo_status_t
_cairo_win32_font_face_scaled_font_create (void *abstract_face,
const cairo_matrix_t *font_matrix,
@ -1536,22 +1503,10 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face,
const cairo_font_options_t *options,
cairo_scaled_font_t **font)
{
HFONT hfont = NULL;
cairo_win32_font_face_t *font_face = abstract_face;
_cairo_win32_initialize ();
if (font_face->hfont) {
/* Check whether it's OK to go ahead and use the font-face's HFONT. */
if (_is_scale (ctm, 1.) &&
_is_scale (font_matrix, -font_face->logfont.lfHeight)) {
hfont = font_face->hfont;
}
}
*font = _win32_scaled_font_create (&font_face->logfont,
hfont,
font_face->hfont,
&font_face->base,
font_matrix, ctm, options);
if (*font)
@ -1566,46 +1521,6 @@ static const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
_cairo_win32_font_face_scaled_font_create
};
/**
* cairo_win32_font_face_create_for_logfontw_hfont:
* @logfont: A #LOGFONTW structure specifying the font to use.
* If hfont is null then the lfHeight, lfWidth, lfOrientation and lfEscapement
* fields of this structure are ignored. Otherwise lfWidth, lfOrientation and
* lfEscapement must be zero.
* @font: An #HFONT that can be used when the font matrix is a scale by
* -lfHeight and the CTM is identity.
*
* Creates a new font for the Win32 font backend based on a
* #LOGFONT. This font can then be used with
* cairo_set_font_face() or cairo_scaled_font_create().
* The #cairo_scaled_font_t
* returned from cairo_scaled_font_create() is also for the Win32 backend
* and can be used with functions such as cairo_win32_scaled_font_select_font().
*
* Return value: a newly created #cairo_font_face_t. Free with
* cairo_font_face_destroy() when you are done using it.
**/
cairo_font_face_t *
cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
{
cairo_win32_font_face_t *font_face;
_cairo_win32_initialize ();
font_face = malloc (sizeof (cairo_win32_font_face_t));
if (!font_face) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
font_face->logfont = *logfont;
font_face->hfont = font;
_cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
return &font_face->base;
}
/**
* cairo_win32_font_face_create_for_logfontw:
* @logfont: A #LOGFONTW structure specifying the font to use.
@ -1625,7 +1540,20 @@ cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font)
cairo_font_face_t *
cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
{
return cairo_win32_font_face_create_for_logfontw_hfont (logfont, NULL);
cairo_win32_font_face_t *font_face;
font_face = malloc (sizeof (cairo_win32_font_face_t));
if (!font_face) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
font_face->logfont = *logfont;
font_face->hfont = NULL;
_cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
return &font_face->base;
}
/**
@ -1645,17 +1573,19 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont)
cairo_font_face_t *
cairo_win32_font_face_create_for_hfont (HFONT font)
{
LOGFONTW logfont;
GetObject (font, sizeof(logfont), &logfont);
cairo_win32_font_face_t *font_face;
if (logfont.lfEscapement != 0 || logfont.lfOrientation != 0 ||
logfont.lfWidth != 0) {
/* We can't use this font because that optimization requires that
* lfEscapement, lfOrientation and lfWidth be zero. */
font = NULL;
font_face = malloc (sizeof (cairo_win32_font_face_t));
if (!font_face) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font);
font_face->hfont = font;
_cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend);
return &font_face->base;
}
/**

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

@ -46,11 +46,7 @@
#define SB_NONE 0
#endif
#if MOZILLA_CAIRO_NOT_DEFINED
#define WIN32_FONT_LOGICAL_SCALE 32
#else
#define WIN32_FONT_LOGICAL_SCALE 1
#endif
typedef struct _cairo_win32_surface {
cairo_surface_t base;
@ -75,11 +71,11 @@ typedef struct _cairo_win32_surface {
cairo_surface_t *image;
cairo_rectangle_int16_t clip_rect;
cairo_rectangle_int_t clip_rect;
HRGN saved_clip;
cairo_rectangle_int16_t extents;
cairo_rectangle_int_t extents;
/* Surface DC flags */
uint32_t flags;
@ -109,7 +105,4 @@ _cairo_win32_print_gdi_error (const char *context);
cairo_bool_t
_cairo_surface_is_win32 (cairo_surface_t *surface);
void
_cairo_win32_initialize (void);
#endif /* CAIRO_WIN32_PRIVATE_H */

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

@ -44,13 +44,18 @@
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
# define _WIN32_WINNT 0x0500
#endif
#include <windows.h>
#include <stdio.h>
#include "cairoint.h"
#include "cairo-clip-private.h"
#include "cairo-win32-private.h"
#include <windows.h>
#if defined(__MINGW32__) && !defined(ETO_PDY)
# define ETO_PDY 0x2000
#endif
#undef DEBUG_COMPOSITE
/* for older SDKs */
@ -181,7 +186,7 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface,
}
if (num_palette > 2) {
bitmap_info = malloc (sizeof (BITMAPINFOHEADER) + num_palette * sizeof (RGBQUAD));
bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER));
if (!bitmap_info)
return CAIRO_STATUS_NO_MEMORY;
} else {
@ -327,8 +332,6 @@ _cairo_win32_surface_create_for_dc (HDC original_dc,
char *bits;
int rowstride;
_cairo_win32_initialize ();
surface = malloc (sizeof (cairo_win32_surface_t));
if (surface == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -473,12 +476,7 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
status = CAIRO_INT_STATUS_UNSUPPORTED;
/* Check for SURFACE_IS_DISPLAY here, because there are a lot
* of printer drivers that lie and say they can BitBlt, but
* just spit out black instead.
*/
if ((local->flags & CAIRO_WIN32_SURFACE_IS_DISPLAY) &&
(local->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
if ((local->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) &&
BitBlt (local->dc,
0, 0,
width, height,
@ -549,9 +547,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_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void **image_extra)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -617,9 +615,9 @@ _cairo_win32_surface_acquire_dest_image (void *abstract_surfa
static void
_cairo_win32_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -738,7 +736,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_int16_t src_extents,
cairo_rectangle_int_t src_extents,
cairo_rectangle_int32_t src_r,
cairo_rectangle_int32_t dst_r,
int alpha,
@ -846,7 +844,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
cairo_image_surface_t *src_image = NULL;
cairo_format_t src_format;
cairo_rectangle_int16_t src_extents;
cairo_rectangle_int_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 };
@ -1314,7 +1312,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_int16_t *rects,
cairo_rectangle_int_t *rects,
int num_rects)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -1376,8 +1374,8 @@ _cairo_win32_surface_fill_rectangles (void *abstract_surface,
}
static cairo_int_status_t
_cairo_win32_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
_cairo_win32_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
{
cairo_win32_surface_t *surface = abstract_surface;
cairo_status_t status;
@ -1406,9 +1404,9 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
} else {
pixman_box16_t *boxes = pixman_region_rects (region);
int num_boxes = pixman_region_num_rects (region);
pixman_box16_t *extents = pixman_region_extents (region);
cairo_rectangle_int_t extents;
cairo_box_int_t *boxes;
int num_boxes;
RGNDATA *data;
size_t data_size;
RECT *rects;
@ -1417,10 +1415,16 @@ _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)
if (!data) {
_cairo_region_boxes_fini (region, boxes);
return CAIRO_STATUS_NO_MEMORY;
}
rects = (RECT *)data->Buffer;
data->rdh.dwSize = sizeof (RGNDATAHEADER);
@ -1433,12 +1437,14 @@ _cairo_win32_surface_set_clip_region (void *abstract_surface,
data->rdh.rcBound.bottom = extents->y2;
for (i = 0; i < num_boxes; i++) {
rects[i].left = boxes[i].x1;
rects[i].top = boxes[i].y1;
rects[i].right = boxes[i].x2;
rects[i].bottom = boxes[i].y2;
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;
}
_cairo_region_boxes_fini (region, &boxes);
gdi_region = ExtCreateRegion (NULL, data_size, data);
free (data);
@ -1467,7 +1473,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_win32_surface_t *surface = abstract_surface;
@ -1548,8 +1554,8 @@ _cairo_win32_surface_show_glyphs (void *surface,
SetBkMode(dst->dc, TRANSPARENT);
if (num_glyphs > STACK_GLYPH_SIZE) {
glyph_buf = (WORD *)malloc(num_glyphs * sizeof(WORD));
dxy_buf = (int *)malloc(num_glyphs * 2 * sizeof(int));
glyph_buf = (WORD *) _cairo_malloc_ab (num_glyphs, sizeof(WORD));
dxy_buf = (int *) _cairo_malloc_abc (num_glyphs, sizeof(int), 2);
}
/* It is vital that dx values for dxy_buf are calculated from the delta of
@ -1640,8 +1646,6 @@ cairo_win32_surface_create (HDC hdc)
int depth;
cairo_format_t format;
_cairo_win32_initialize ();
/* Try to figure out the drawing bounds for the Device context
*/
if (GetClipBox (hdc, &rect) == ERROR) {
@ -1859,6 +1863,30 @@ cairo_win32_surface_get_image (cairo_surface_t *surface)
return ((cairo_win32_surface_t*)surface)->image;
}
static cairo_bool_t
_cairo_win32_surface_is_similar (void *surface_a,
void *surface_b,
cairo_content_t content)
{
cairo_win32_surface_t *a = surface_a;
cairo_win32_surface_t *b = surface_b;
return a->dc == b->dc;
}
static cairo_status_t
_cairo_win32_surface_reset (void *abstract_surface)
{
cairo_win32_surface_t *surface = abstract_surface;
cairo_status_t status;
status = _cairo_win32_surface_set_clip_region (surface, NULL);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
static const cairo_surface_backend_t cairo_win32_surface_backend = {
CAIRO_SURFACE_TYPE_WIN32,
_cairo_win32_surface_create_similar,
@ -1889,70 +1917,12 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
NULL, /* fill */
_cairo_win32_surface_show_glyphs,
NULL /* snapshot */
NULL, /* snapshot */
_cairo_win32_surface_is_similar,
_cairo_win32_surface_reset
};
/*
* Without pthread, on win32 we need to initialize all the 'mutex'es
* before use. It is guaranteed that DllMain will get called single
* threaded before any other function.
* Initializing more than finally needed should not matter much.
*/
#if !defined(HAVE_PTHREAD_H)
CRITICAL_SECTION _cairo_scaled_font_map_mutex;
#ifdef CAIRO_HAS_FT_FONT
CRITICAL_SECTION _cairo_ft_unscaled_font_map_mutex;
#endif
CRITICAL_SECTION _cairo_font_face_mutex;
static int _cairo_win32_initialized = 0;
void
_cairo_win32_initialize (void) {
if (_cairo_win32_initialized)
return;
/* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */
InitializeCriticalSection (&_cairo_scaled_font_map_mutex);
#ifdef CAIRO_HAS_FT_FONT
InitializeCriticalSection (&_cairo_ft_unscaled_font_map_mutex);
#endif
InitializeCriticalSection (&_cairo_font_face_mutex);
_cairo_win32_initialized = 1;
}
#if !defined(CAIRO_WIN32_STATIC_BUILD)
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
_cairo_win32_initialize();
break;
case DLL_PROCESS_DETACH:
DeleteCriticalSection (&_cairo_scaled_font_map_mutex);
#ifdef CAIRO_HAS_FT_FONT
DeleteCriticalSection (&_cairo_ft_unscaled_font_map_mutex);
#endif
DeleteCriticalSection (&_cairo_font_face_mutex);
break;
}
return TRUE;
}
#endif
#else
/* Need a function definition here too since it's called outside of ifdefs */
void
_cairo_win32_initialize (void)
{
}
#endif
/* Notes:
*
* Win32 alpha-understanding functions
@ -1966,3 +1936,33 @@ _cairo_win32_initialize (void)
* it will still copy over the src alpha, because the SCA value (255) will be
* multiplied by all the src components.
*/
#if !defined(CAIRO_WIN32_STATIC_BUILD)
/* declare to avoid "no previous prototype for 'DllMain'" warning */
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved);
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
CAIRO_MUTEX_INITIALIZE ();
break;
case DLL_PROCESS_DETACH:
CAIRO_MUTEX_FINALIZE ();
break;
}
return TRUE;
}
#endif

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

@ -70,9 +70,6 @@ cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont);
cairo_public cairo_font_face_t *
cairo_win32_font_face_create_for_hfont (HFONT font);
cairo_public cairo_font_face_t *
cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font);
cairo_public cairo_status_t
cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font,
HDC hdc);

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

@ -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_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect)
cairo_rectangle_int_t *image_rect)
{
cairo_image_surface_t *image;
xcb_get_image_reply_t *imagerep;
int bpp, bytes_per_line;
int x1, y1, x2, y2;
short 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 = malloc (bytes_per_line * surface->height);
data = _cairo_malloc_ab (surface->height, bytes_per_line);
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_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect_out,
cairo_rectangle_int_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_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_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_from_double (matrix->xx);
xtransform.matrix12 = _cairo_fixed_from_double (matrix->xy);
xtransform.matrix13 = _cairo_fixed_from_double (matrix->x0);
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.matrix21 = _cairo_fixed_from_double (matrix->yx);
xtransform.matrix22 = _cairo_fixed_from_double (matrix->yy);
xtransform.matrix23 = _cairo_fixed_from_double (matrix->y0);
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.matrix31 = 0;
xtransform.matrix32 = 0;
xtransform.matrix33 = _cairo_fixed_from_double (1);
xtransform.matrix33 = 1 << 16;
if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
{
@ -1246,11 +1246,14 @@ static cairo_int_status_t
_cairo_xcb_surface_fill_rectangles (void *abstract_surface,
cairo_operator_t op,
const cairo_color_t * color,
cairo_rectangle_int16_t *rects,
cairo_rectangle_int_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;
@ -1260,12 +1263,27 @@ _cairo_xcb_surface_fill_rectangles (void *abstract_surface,
render_color.blue = color->blue_short;
render_color.alpha = color->alpha_short;
/* XXX: This xcb_rectangle_t cast is evil... it needs to go away somehow. */
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;
}
_cairo_xcb_surface_ensure_dst_picture (surface);
xcb_render_fill_rectangles (surface->dpy,
_render_operator (op),
surface->dst_picture,
render_color, num_rects, (xcb_rectangle_t *) rects);
render_color, num_rects, xrects);
if (xrects != static_xrects)
free(xrects);
return CAIRO_STATUS_SUCCESS;
}
@ -1328,21 +1346,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 = malloc (sizeof (xcb_render_trapezoid_t) * num_traps);
offset_traps = _cairo_malloc_ab (num_traps, sizeof (xcb_render_trapezoid_t));
if (!offset_traps)
return XCB_NONE;
for (i = 0; i < num_traps; i++) {
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;
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;
}
xcb_render_trapezoids (dst->dpy, XCB_RENDER_PICT_OP_ADD,
@ -1470,14 +1488,41 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
dst_x, dst_y, width, height);
} else {
/* XXX: The XTrapezoid cast is evil and needs to go away somehow. */
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);
}
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, (xcb_render_trapezoid_t *) traps);
num_traps, xtraps);
if (xtraps != xtraps_stack)
free(xtraps);
}
BAIL:
@ -1487,8 +1532,8 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
}
static cairo_int_status_t
_cairo_xcb_surface_set_clip_region (void *abstract_surface,
pixman_region16_t *region)
_cairo_xcb_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -1509,28 +1554,32 @@ _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 {
pixman_box16_t *boxes;
cairo_box_int_t *boxes;
xcb_rectangle_t *rects = NULL;
int n_boxes, i;
n_boxes = pixman_region_num_rects (region);
if (_cairo_region_get_boxes (region, &n_boxes, &boxes) != CAIRO_STATUS_SUCCESS)
return CAIRO_STATUS_NO_MEMORY;
if (n_boxes > 0) {
rects = malloc (sizeof(xcb_rectangle_t) * n_boxes);
if (rects == NULL)
rects = _cairo_malloc_ab (n_boxes, sizeof(xcb_rectangle_t));
if (rects == NULL) {
_cairo_region_boxes_fini (region, boxes);
return CAIRO_STATUS_NO_MEMORY;
}
} else {
rects = NULL;
}
boxes = pixman_region_rects (region);
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;
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;
}
_cairo_region_boxes_fini (region, boxes);
surface->have_clip_rects = TRUE;
surface->clip_rects = rects;
surface->num_clip_rects = n_boxes;
@ -1547,7 +1596,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
cairo_xcb_surface_t *surface = abstract_surface;
@ -1577,6 +1626,39 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
static cairo_bool_t
_cairo_xcb_surface_is_similar (void *surface_a,
void *surface_b,
cairo_content_t content)
{
cairo_xcb_surface_t *a = surface_a;
cairo_xcb_surface_t *b = surface_b;
xcb_render_pictforminfo_t *xrender_format;
if (! _cairo_xcb_surface_same_screen (a, b))
return FALSE;
/* now check that the target is a similar format */
xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (b->dpy,
_cairo_format_from_content (content));
return a->xrender_format.id == xrender_format->id;
}
static cairo_status_t
_cairo_xcb_surface_reset (void *abstract_surface)
{
cairo_xcb_surface_t *surface = abstract_surface;
cairo_status_t status;
status = _cairo_xcb_surface_set_clip_region (surface, NULL);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
/* XXX: move this to the bottom of the file, XCB and Xlib */
static const cairo_surface_backend_t cairo_xcb_surface_backend = {
@ -1608,7 +1690,11 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
NULL, /* stroke */
NULL, /* fill */
_cairo_xcb_surface_show_glyphs,
NULL /* snapshot */
NULL, /* snapshot */
_cairo_xcb_surface_is_similar,
_cairo_xcb_surface_reset
};
/**
@ -2323,7 +2409,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 = malloc (num_glyphs * sizeof (cairo_glyph_t));
output_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
if (output_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
@ -2344,7 +2430,8 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
* so PictOpClear was never used with CompositeText before.
*/
if (op == CAIRO_OPERATOR_CLEAR) {
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE);
_cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
src_pattern = &solid_pattern.base;
op = CAIRO_OPERATOR_DEST_OUT;
}

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

@ -35,43 +35,97 @@
#include "cairoint.h"
#include "cairo-xlib.h"
#include "cairo-freelist-private.h"
typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t;
typedef struct _cairo_xlib_display cairo_xlib_display_t;
typedef struct _cairo_xlib_hook cairo_xlib_hook_t;
typedef struct _cairo_xlib_job cairo_xlib_job_t;
typedef void (*cairo_xlib_notify_func) (Display *, void *);
typedef void (*cairo_xlib_notify_resource_func) (Display *, XID);
struct _cairo_xlib_hook {
cairo_xlib_hook_t *next;
void (*func) (Display *display, void *data);
void *data;
void *key;
const void *key;
};
struct _cairo_xlib_display {
cairo_xlib_display_t *next;
unsigned int ref_count;
cairo_mutex_t mutex;
Display *display;
cairo_xlib_screen_info_t *screens;
cairo_xlib_job_t *workqueue;
cairo_freelist_t wq_freelist;
cairo_freelist_t hook_freelist;
cairo_xlib_hook_t *close_display_hooks;
unsigned int closed :1;
};
struct _cairo_xlib_screen_info {
cairo_xlib_screen_info_t *next;
unsigned int ref_count;
Display *display;
cairo_xlib_display_t *display;
Screen *screen;
cairo_bool_t has_render;
cairo_font_options_t font_options;
cairo_xlib_hook_t *close_display_hooks;
GC gc[9];
unsigned int gc_needs_clip_reset;
};
cairo_private cairo_xlib_display_t *
_cairo_xlib_display_get (Display *display);
cairo_private cairo_xlib_display_t *
_cairo_xlib_display_reference (cairo_xlib_display_t *info);
cairo_private void
_cairo_xlib_display_destroy (cairo_xlib_display_t *info);
cairo_private cairo_bool_t
_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, const void *key);
cairo_private void
_cairo_xlib_remove_close_display_hooks (Display *display, const void *key);
cairo_private cairo_status_t
_cairo_xlib_display_queue_work (cairo_xlib_display_t *display,
cairo_xlib_notify_func notify,
void *data,
void (*destroy)(void *));
cairo_private cairo_status_t
_cairo_xlib_display_queue_resource (cairo_xlib_display_t *display,
cairo_xlib_notify_resource_func notify,
XID resource);
cairo_private void
_cairo_xlib_display_notify (cairo_xlib_display_t *display);
cairo_private cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get (Display *display, Screen *screen);
cairo_private cairo_bool_t
_cairo_xlib_add_close_display_hook (Display *display, void (*func) (Display *, void *), void *data, void *key);
cairo_private cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info);
cairo_private void
_cairo_xlib_remove_close_display_hook (Display *display, void *key);
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info);
cairo_private void
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info);
cairo_private GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth);
cairo_private cairo_status_t
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip);
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
#include "cairo-xlib-xrender.h"
#ifdef MOZILLA_CAIRO_NOT_DEFINED
slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format);
#endif
#endif
#endif /* CAIRO_XLIB_PRIVATE_H */

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

@ -51,14 +51,13 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdlib.h>
#include <string.h>
#include "cairoint.h"
#include "cairo-xlib-private.h"
#include <fontconfig/fontconfig.h>
#include <X11/Xlibint.h> /* For XESetCloseDisplay */
#include <X11/extensions/Xrender.h>
static int
@ -133,7 +132,7 @@ get_integer_default (Display *dpy,
#endif
static void
_cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
_cairo_xlib_init_screen_font_options (Display *dpy, cairo_xlib_screen_info_t *info)
{
cairo_bool_t xft_hinting;
cairo_bool_t xft_antialias;
@ -143,23 +142,23 @@ _cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
cairo_subpixel_order_t subpixel_order;
cairo_hint_style_t hint_style;
if (!get_boolean_default (info->display, "antialias", &xft_antialias))
if (!get_boolean_default (dpy, "antialias", &xft_antialias))
xft_antialias = TRUE;
if (!get_boolean_default (info->display, "hinting", &xft_hinting))
if (!get_boolean_default (dpy, "hinting", &xft_hinting))
xft_hinting = TRUE;
if (!get_integer_default (info->display, "hintstyle", &xft_hintstyle))
if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
xft_hintstyle = FC_HINT_FULL;
if (!get_integer_default (info->display, "rgba", &xft_rgba))
if (!get_integer_default (dpy, "rgba", &xft_rgba))
{
xft_rgba = FC_RGBA_UNKNOWN;
#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
if (info->has_render)
{
int render_order = XRenderQuerySubpixelOrder (info->display,
int render_order = XRenderQuerySubpixelOrder (dpy,
XScreenNumberOfScreen (info->screen));
switch (render_order)
@ -237,235 +236,183 @@ _cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
antialias = CAIRO_ANTIALIAS_NONE;
}
_cairo_font_options_init_default (&info->font_options);
cairo_font_options_set_hint_style (&info->font_options, hint_style);
cairo_font_options_set_antialias (&info->font_options, antialias);
cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
}
CAIRO_MUTEX_DECLARE(_xlib_screen_mutex);
static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
static int
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
{
cairo_xlib_screen_info_t *info, **prev, *next;
/*
* Unhook from the global list
*/
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
prev = &_cairo_xlib_screen_list;
for (info = _cairo_xlib_screen_list; info; info = next) {
next = info->next;
if (info->display == dpy) {
*prev = next;
/* call all registered shutdown routines */
while (info->close_display_hooks) {
cairo_xlib_hook_t *hook = info->close_display_hooks;
info->close_display_hooks = hook->next;
hook->func (dpy, hook->data);
free (hook);
}
free (info);
} else {
prev = &info->next;
}
}
*prev = NULL;
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
/* Return value in accordance with requirements of
* XESetCloseDisplay */
return 0;
}
static void
_cairo_xlib_screen_info_reset (void)
{
cairo_xlib_screen_info_t *info, *next;
/*
* Delete everything in the list.
*/
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
for (info = _cairo_xlib_screen_list; info; info = next) {
next = info->next;
while (info->close_display_hooks) {
cairo_xlib_hook_t *hook = info->close_display_hooks;
info->close_display_hooks = hook->next;
free (hook);
}
free (info);
}
_cairo_xlib_screen_list = NULL;
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
}
static cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get_unlocked (Display *dpy, Screen *screen)
{
cairo_xlib_screen_info_t *info;
cairo_xlib_screen_info_t **prev;
int event_base, error_base;
XExtCodes *codes;
cairo_bool_t seen_display = FALSE;
for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next)
{
if (info->display == dpy) {
seen_display = TRUE;
if (info->screen == screen || screen == NULL) {
/*
* MRU the list
*/
if (prev != &_cairo_xlib_screen_list) {
*prev = info->next;
info->next = _cairo_xlib_screen_list;
_cairo_xlib_screen_list = info;
}
break;
}
}
}
if (info)
return info;
if (screen == NULL)
return NULL;
info = malloc (sizeof (cairo_xlib_screen_info_t));
if (!info)
if (info == NULL)
return NULL;
if (!seen_display) {
codes = XAddExtension (dpy);
if (!codes) {
free (info);
return NULL;
}
XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
}
info->display = dpy;
info->screen = screen;
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
info->close_display_hooks = NULL;
_cairo_xlib_init_screen_font_options (info);
info->next = _cairo_xlib_screen_list;
_cairo_xlib_screen_list = info;
assert (info->ref_count > 0);
info->ref_count++;
return info;
}
void
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
{
int i;
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
if (info->gc[i] != NULL) {
XFreeGC (info->display->display, info->gc[i]);
info->gc[i] = NULL;
}
}
}
void
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
{
cairo_xlib_screen_info_t **prev;
cairo_xlib_screen_info_t *list;
if (info == NULL)
return;
assert (info->ref_count > 0);
if (--info->ref_count)
return;
CAIRO_MUTEX_LOCK (info->display->mutex);
for (prev = &info->display->screens; (list = *prev); prev = &list->next) {
if (list == info) {
*prev = info->next;
break;
}
}
CAIRO_MUTEX_UNLOCK (info->display->mutex);
_cairo_xlib_screen_info_close_display (info);
_cairo_xlib_display_destroy (info->display);
free (info);
}
cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
{
cairo_xlib_screen_info_t *info;
cairo_xlib_display_t *display;
cairo_xlib_screen_info_t *info = NULL, **prev;
/* There is an apparent deadlock between this mutex and the
* mutex for the display, but it's actually safe. For the
* app to call XCloseDisplay() while any other thread is
* inside this function would be an error in the logic
* app, and the CloseDisplay hook is the only other place we
* acquire this mutex.
*/
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
display = _cairo_xlib_display_get (dpy);
if (display == NULL)
return NULL;
info = _cairo_xlib_screen_info_get_unlocked (dpy, screen);
CAIRO_MUTEX_LOCK (display->mutex);
if (display->closed) {
CAIRO_MUTEX_UNLOCK (display->mutex);
goto DONE;
}
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
return info;
}
cairo_bool_t
_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, void *key)
{
cairo_xlib_screen_info_t *info;
cairo_xlib_hook_t *hook;
cairo_xlib_hook_t **prev;
cairo_bool_t success = FALSE;
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
info = _cairo_xlib_screen_info_get_unlocked (dpy, NULL);
if (!info)
goto unlock;
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
{
if (hook->key == key) {
for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
if (info->screen == screen) {
/*
* MRU the list
*/
if (prev != &info->close_display_hooks) {
*prev = hook->next;
hook->next = info->close_display_hooks;
info->close_display_hooks = hook;
if (prev != &display->screens) {
*prev = info->next;
info->next = display->screens;
display->screens = info;
}
break;
}
}
CAIRO_MUTEX_UNLOCK (display->mutex);
if (!hook) {
hook = malloc (sizeof (cairo_xlib_hook_t));
if (!hook)
goto unlock;
hook->func = func;
hook->data = data;
hook->key = key;
hook->next = info->close_display_hooks;
info->close_display_hooks = hook;
}
if (info != NULL) {
info = _cairo_xlib_screen_info_reference (info);
} else {
info = malloc (sizeof (cairo_xlib_screen_info_t));
if (info != NULL) {
info->ref_count = 2; /* Add one for display cache */
info->display = _cairo_xlib_display_reference (display);
info->screen = screen;
info->has_render = FALSE;
_cairo_font_options_init_default (&info->font_options);
memset (info->gc, 0, sizeof (info->gc));
info->gc_needs_clip_reset = 0;
success = TRUE;
unlock:
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
return success;
}
if (screen) {
int event_base, error_base;
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
_cairo_xlib_init_screen_font_options (dpy, info);
}
void
_cairo_xlib_remove_close_display_hook (Display *dpy, void *key)
{
cairo_xlib_screen_info_t *info;
cairo_xlib_hook_t *hook;
cairo_xlib_hook_t **prev;
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
info = _cairo_xlib_screen_info_get_unlocked (dpy, NULL);
if (!info)
goto unlock;
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
{
if (hook->key == key) {
*prev = hook->next;
free (hook);
break;
CAIRO_MUTEX_LOCK (display->mutex);
info->next = display->screens;
display->screens = info;
CAIRO_MUTEX_UNLOCK (display->mutex);
}
}
unlock:
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
DONE:
_cairo_xlib_display_destroy (display);
return info;
}
void
_cairo_xlib_screen_reset_static_data (void)
static int
depth_to_index (int depth)
{
_cairo_xlib_screen_info_reset ();
switch(depth){
case 1: return 1;
case 8: return 2;
case 12: return 3;
case 15: return 4;
case 16: return 5;
case 24: return 6;
case 30: return 7;
case 32: return 8;
}
return 0;
}
GC
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
{
GC gc;
depth = depth_to_index (depth);
gc = info->gc[depth];
info->gc[depth] = NULL;
if (info->gc_needs_clip_reset & (1 << depth)) {
XSetClipMask(info->display->display, gc, None);
info->gc_needs_clip_reset &= ~(1 << depth);
}
return gc;
}
cairo_status_t
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
{
cairo_status_t status = CAIRO_STATUS_SUCCESS;
depth = depth_to_index (depth);
if (info->gc[depth] != NULL) {
status = _cairo_xlib_display_queue_work (info->display,
(cairo_xlib_notify_func) XFreeGC,
info->gc[depth],
NULL);
}
info->gc[depth] = gc;
if (reset_clip)
info->gc_needs_clip_reset |= 1 << depth;
else
info->gc_needs_clip_reset &= ~(1 << depth);
return status;
}

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

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

@ -1,54 +0,0 @@
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#ifndef CAIRO_XLIB_TEST_H
#define CAIRO_XLIB_TEST_H
#include <cairo.h>
#if CAIRO_HAS_XLIB_SURFACE
#include <cairo-xlib.h>
CAIRO_BEGIN_DECLS
cairo_public void
_cairo_xlib_test_disable_render (void);
CAIRO_END_DECLS
#endif /* CAIRO_HAS_XLIB_SURFACE */
#endif /* CAIRO_XLIB_H */

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

@ -41,6 +41,7 @@
#if CAIRO_HAS_XLIB_SURFACE
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
CAIRO_BEGIN_DECLS

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

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

@ -895,7 +895,7 @@ typedef enum _cairo_subpixel_order {
/**
* cairo_hint_style_t:
* @CAIRO_HINT_STYLE_DEFAULT: Use the default hint style for
* for font backend and target device
* font backend and target device
* @CAIRO_HINT_STYLE_NONE: Do not hint outlines
* @CAIRO_HINT_STYLE_SLIGHT: Hint outlines slightly to improve
* contrast while retaining good fidelity to the original

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

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

@ -51,10 +51,10 @@
* there.
*/
#include "test-fallback-surface.h"
#include "cairoint.h"
#include "test-fallback-surface.h"
typedef struct _test_fallback_surface {
cairo_surface_t base;
@ -80,6 +80,7 @@ _cairo_test_fallback_surface_create (cairo_content_t content,
surface = malloc (sizeof (test_fallback_surface_t));
if (surface == NULL) {
cairo_surface_destroy (backing);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
@ -139,9 +140,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_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t **image_out,
cairo_rectangle_int16_t *image_rect_out,
cairo_rectangle_int_t *image_rect_out,
void **image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
@ -155,9 +156,9 @@ _test_fallback_surface_acquire_dest_image (void *abstract_surface,
static void
_test_fallback_surface_release_dest_image (void *abstract_surface,
cairo_rectangle_int16_t *interest_rect,
cairo_rectangle_int_t *interest_rect,
cairo_image_surface_t *image,
cairo_rectangle_int16_t *image_rect,
cairo_rectangle_int_t *image_rect,
void *image_extra)
{
test_fallback_surface_t *surface = abstract_surface;
@ -169,9 +170,29 @@ _test_fallback_surface_release_dest_image (void *abstract_surface,
image_extra);
}
static cairo_status_t
_test_fallback_surface_clone_similar (void *abstract_surface,
cairo_surface_t *src,
int src_x,
int src_y,
int width,
int height,
cairo_surface_t **clone_out)
{
test_fallback_surface_t *surface = abstract_surface;
if (src->backend == surface->base.backend) {
*clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
}
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_int_status_t
_test_fallback_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *rectangle)
_test_fallback_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
{
test_fallback_surface_t *surface = abstract_surface;
@ -186,7 +207,7 @@ const cairo_surface_backend_t test_fallback_surface_backend = {
_test_fallback_surface_release_source_image,
_test_fallback_surface_acquire_dest_image,
_test_fallback_surface_release_dest_image,
NULL, /* clone_similar */
_test_fallback_surface_clone_similar,
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */

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

@ -45,9 +45,10 @@
* backend.
*/
#include "cairoint.h"
#include "test-meta-surface.h"
#include "cairoint.h"
#include "cairo-meta-surface-private.h"
typedef struct _test_meta_surface {
@ -143,11 +144,14 @@ static cairo_int_status_t
_test_meta_surface_show_page (void *abstract_surface)
{
test_meta_surface_t *surface = abstract_surface;
cairo_status_t status;
if (surface->image_reflects_meta)
return CAIRO_STATUS_SUCCESS;
_cairo_meta_surface_replay (surface->meta, surface->image);
status = _cairo_meta_surface_replay (surface->meta, surface->image);
if (status)
return status;
surface->image_reflects_meta = TRUE;
@ -170,7 +174,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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
test_meta_surface_t *surface = abstract_surface;
@ -279,6 +283,7 @@ static cairo_surface_t *
_test_meta_surface_snapshot (void *abstract_other)
{
test_meta_surface_t *other = abstract_other;
cairo_status_t status;
/* XXX: Just making a snapshot of other->meta is what we really
* want. But this currently triggers a bug somewhere (the "mask"
@ -295,17 +300,23 @@ _test_meta_surface_snapshot (void *abstract_other)
#if 0
return _cairo_surface_snapshot (other->meta);
#else
cairo_rectangle_int16_t extents;
cairo_rectangle_int_t extents;
cairo_surface_t *surface;
_cairo_surface_get_extents (other->image, &extents);
status = _cairo_surface_get_extents (other->image, &extents);
if (status)
return (cairo_surface_t*) &_cairo_surface_nil;
surface = cairo_surface_create_similar (other->image,
CAIRO_CONTENT_COLOR_ALPHA,
extents.width,
extents.height);
_cairo_meta_surface_replay (other->meta, surface);
status = _cairo_meta_surface_replay (other->meta, surface);
if (status) {
cairo_surface_destroy (surface);
surface = (cairo_surface_t*) &_cairo_surface_nil;
}
return surface;
#endif

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

@ -45,11 +45,11 @@
* backend.
*/
#include "test-paginated-surface.h"
#include "cairoint.h"
#include "cairo-paginated-surface-private.h"
#include "test-paginated-surface.h"
#include "cairo-paginated-private.h"
typedef struct _test_paginated_surface {
cairo_surface_t base;
@ -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,
pixman_region16_t *region)
cairo_region_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_int16_t *rectangle)
cairo_rectangle_int_t *rectangle)
{
test_paginated_surface_t *surface = abstract_surface;