зеркало из https://github.com/mozilla/gecko-dev.git
b=383960, Cairo 1.5.x: Cairo
This commit is contained in:
Родитель
837921103c
Коммит
24adcacb7a
|
@ -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,
|
||||
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,7 +1102,7 @@ _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,
|
||||
_cairo_traps_add_trap_from_points (bo_traps->traps,
|
||||
fixed_top,
|
||||
fixed_bot,
|
||||
left_top, left_bot,
|
||||
|
@ -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 (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,6 +1519,7 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
|
|||
xmin, ymin, xmax, ymax,
|
||||
&intersections);
|
||||
|
||||
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,24 +170,19 @@ _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);
|
||||
|
||||
_cairo_region_fini (&intersection);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
@ -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,25 +207,20 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
|
|||
/* Intersect clip path into region. */
|
||||
}
|
||||
|
||||
if (clip->region)
|
||||
pixman_region_intersect (region, clip->region, region);
|
||||
if (clip->has_region) {
|
||||
status = _cairo_region_intersect (region, &clip->region, region);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (clip->surface) {
|
||||
pixman_region16_t *clip_rect;
|
||||
pixman_region_status_t pixman_status;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_region_t clip_rect;
|
||||
|
||||
clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
|
||||
if (clip_rect == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
_cairo_region_init_rect (&clip_rect, &clip->surface_rect);
|
||||
|
||||
pixman_status = pixman_region_intersect (region,
|
||||
clip_rect,
|
||||
region);
|
||||
if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
status = _cairo_region_intersect (region, &clip_rect, region);
|
||||
|
||||
pixman_region_destroy (clip_rect);
|
||||
_cairo_region_fini (&clip_rect);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
@ -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, ®ion);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (region == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
if (clip->region == NULL) {
|
||||
clip->region = region;
|
||||
} else {
|
||||
pixman_region16_t *intersection = pixman_region_create();
|
||||
|
||||
if (pixman_region_intersect (intersection,
|
||||
clip->region, region)
|
||||
== PIXMAN_REGION_STATUS_SUCCESS) {
|
||||
pixman_region_destroy (clip->region);
|
||||
clip->region = intersection;
|
||||
if (!clip->has_region) {
|
||||
status = _cairo_region_copy (&clip->region, ®ion);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
clip->has_region = TRUE;
|
||||
} else {
|
||||
status = CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
pixman_region_destroy (region);
|
||||
cairo_region_t intersection;
|
||||
_cairo_region_init (&intersection);
|
||||
|
||||
status = _cairo_region_intersect (&intersection,
|
||||
&clip->region,
|
||||
®ion);
|
||||
|
||||
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 (®ion);
|
||||
|
||||
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,41 +622,50 @@ 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;
|
||||
|
||||
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])) {
|
||||
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;
|
||||
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)) {
|
||||
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;
|
||||
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -160,3 +160,13 @@ _cairo_color_get_rgba_premultiplied (cairo_color_t *color,
|
|||
*blue = color->blue * color->alpha;
|
||||
*alpha = color->alpha;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_color_equal (const cairo_color_t *color_a,
|
||||
const cairo_color_t *color_b)
|
||||
{
|
||||
return color_a->red_short == color_b->red_short &&
|
||||
color_a->green_short == color_b->green_short &&
|
||||
color_a->blue_short == color_b->blue_short &&
|
||||
color_a->alpha_short == color_b->alpha_short;
|
||||
}
|
||||
|
|
|
@ -59,13 +59,11 @@
|
|||
void
|
||||
cairo_debug_reset_static_data (void)
|
||||
{
|
||||
#if CAIRO_HAS_XLIB_SURFACE
|
||||
_cairo_xlib_screen_reset_static_data ();
|
||||
#endif
|
||||
|
||||
_cairo_font_reset_static_data ();
|
||||
|
||||
#if CAIRO_HAS_FT_FONT
|
||||
_cairo_ft_font_reset_static_data ();
|
||||
#endif
|
||||
|
||||
_cairo_pattern_reset_static_data ();
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output)
|
|||
|
||||
stream = malloc (sizeof (cairo_deflate_stream_t));
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
|
||||
_cairo_output_stream_init (&stream->base,
|
||||
_cairo_deflate_stream_write,
|
||||
|
@ -130,8 +130,10 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output)
|
|||
stream->zlib_stream.zfree = Z_NULL;
|
||||
stream->zlib_stream.opaque = Z_NULL;
|
||||
|
||||
if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK) {
|
||||
free (stream);
|
||||
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
|
||||
}
|
||||
|
||||
stream->zlib_stream.next_in = stream->input_buf;
|
||||
stream->zlib_stream.avail_in = 0;
|
||||
|
|
|
@ -35,10 +35,9 @@
|
|||
* Claudio Ciccani <klan@users.sf.net>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-directfb.h"
|
||||
|
||||
#include <directfb.h>
|
||||
|
||||
|
@ -47,9 +46,6 @@
|
|||
#include <direct/memcpy.h>
|
||||
#include <direct/util.h>
|
||||
|
||||
#include "cairo-directfb.h"
|
||||
#include "cairoint.h"
|
||||
|
||||
|
||||
/*
|
||||
* Rectangle causes problems (see bugs 361377, 359553, 359243 in Gnome BTS).
|
||||
|
@ -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;
|
||||
|
@ -1100,7 +1096,7 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
|
|||
|
||||
static cairo_int_status_t
|
||||
_cairo_directfb_surface_set_clip_region (void *abstract_surface,
|
||||
pixman_region16_t *region)
|
||||
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,10 +692,15 @@ _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
|
||||
* Packard and libXft. */
|
||||
static const int filters[3][3] = {
|
||||
|
@ -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,17 +1185,21 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
|
|||
|
||||
/* Initialize it to empty
|
||||
*/
|
||||
_cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
|
||||
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,
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||
&pattern.base, NULL, image,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
width,
|
||||
|
@ -1196,6 +1207,11 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
|
|||
|
||||
_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,
|
||||
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;
|
||||
}
|
||||
|
||||
_cairo_ft_unscaled_font_set_scale (unscaled,
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
if (_cairo_path_fixed_curve_to (path,
|
||||
x1, y1,
|
||||
x2, y2,
|
||||
x3, y3);
|
||||
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,
|
||||
if (_cairo_path_fixed_curve_to (path,
|
||||
x0, y0,
|
||||
x1, y1,
|
||||
x2, y2);
|
||||
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,
|
||||
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,11 +2242,13 @@ _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 = {
|
||||
CAIRO_FONT_TYPE_FT,
|
||||
|
@ -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))
|
||||
{
|
||||
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,11 +2443,9 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_ft_font_face_create_for_ft_face:
|
||||
|
@ -2429,13 +2494,11 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_ft_scaled_font_lock_face:
|
||||
|
@ -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,
|
||||
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)
|
||||
{
|
||||
if (surface->has_clip) {
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
|
||||
pixman_region_destroy (surface->clip);
|
||||
_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,31 +292,97 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
|
|||
glitz_buffer_destroy (buffer);
|
||||
|
||||
/* restore the clip, if any */
|
||||
if (surface->clip) {
|
||||
if (surface->has_clip) {
|
||||
glitz_box_t *box;
|
||||
int n;
|
||||
|
||||
box = (glitz_box_t *) pixman_region_rects (surface->clip);
|
||||
n = pixman_region_num_rects (surface->clip);
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
|
||||
}
|
||||
|
||||
image = (cairo_image_surface_t *)
|
||||
_cairo_image_surface_create_with_masks (pixels,
|
||||
&format,
|
||||
width, height,
|
||||
pf.bytes_per_line);
|
||||
if (image->base.status)
|
||||
{
|
||||
box = _cairo_glitz_get_boxes_from_region (&surface->clip, &n);
|
||||
if (box == NULL && n != 0) {
|
||||
free (pixels);
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
|
||||
|
||||
free (box);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prefer to use a standard pixman format instead of the
|
||||
* general masks case.
|
||||
*/
|
||||
if (_CAIRO_MASK_FORMAT (&masks, &format)) {
|
||||
image = (cairo_image_surface_t *)
|
||||
cairo_image_surface_create_for_data (pixels,
|
||||
format,
|
||||
x2 - x1,
|
||||
y2 - y1,
|
||||
pf.bytes_per_line);
|
||||
if (image->base.status)
|
||||
goto FAIL;
|
||||
} else {
|
||||
/*
|
||||
* XXX This can't work. We must convert the data to one of the
|
||||
* supported pixman formats. Pixman needs another function
|
||||
* which takes data in an arbitrary format and converts it
|
||||
* to something supported by that library.
|
||||
*/
|
||||
image = (cairo_image_surface_t *)
|
||||
_cairo_image_surface_create_with_masks (pixels,
|
||||
&masks,
|
||||
x2 - x1,
|
||||
y2 - y1,
|
||||
pf.bytes_per_line);
|
||||
if (image->base.status)
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
_cairo_image_surface_assume_ownership_of_data (image);
|
||||
|
||||
*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)
|
||||
if (!surface->has_clip) {
|
||||
_cairo_region_init (&surface->clip);
|
||||
surface->has_clip = TRUE;
|
||||
}
|
||||
|
||||
if (_cairo_region_copy (&surface->clip, region) != CAIRO_STATUS_SUCCESS)
|
||||
{
|
||||
surface->clip = pixman_region_create ();
|
||||
if (!surface->clip)
|
||||
_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;
|
||||
}
|
||||
pixman_region_copy (surface->clip, region);
|
||||
|
||||
box = (glitz_box_t *) pixman_region_rects (surface->clip);
|
||||
n = pixman_region_num_rects (surface->clip);
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
|
||||
|
||||
free (box);
|
||||
}
|
||||
else
|
||||
{
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
|
||||
|
||||
if (surface->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 *
|
||||
|
@ -2242,7 +2453,7 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
|
|||
|
||||
crsurface->surface = surface;
|
||||
crsurface->format = format;
|
||||
crsurface->clip = NULL;
|
||||
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,23 +787,24 @@ _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,
|
||||
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,
|
||||
return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
|
||||
mask,
|
||||
&gstate->ctm_inverse);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
else
|
||||
|
||||
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,
|
||||
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,
|
||||
return _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
|
||||
utf8, glyphs, num_glyphs);
|
||||
|
||||
if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs))
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
@ -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;
|
||||
return cairo_image_surface_create_for_data (data,
|
||||
format,
|
||||
width,
|
||||
height,
|
||||
stride);
|
||||
}
|
||||
|
||||
surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
|
||||
cairo_format);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -291,7 +230,7 @@ cairo_image_surface_create (cairo_format_t format,
|
|||
int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
pixman_format_t *pixman_format;
|
||||
pixman_format_code_t pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
|
||||
if (! CAIRO_FORMAT_VALID (format)) {
|
||||
|
@ -299,22 +238,19 @@ cairo_image_surface_create (cairo_format_t 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;
|
||||
}
|
||||
|
@ -370,24 +306,16 @@ cairo_image_surface_create_for_data (unsigned char *data,
|
|||
int stride)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
pixman_format_t *pixman_format;
|
||||
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,7 +779,7 @@ _cairo_image_surface_composite (cairo_operator_t op,
|
|||
if (status)
|
||||
goto CLEANUP_SURFACES;
|
||||
|
||||
pixman_composite (_pixman_operator (op),
|
||||
pixman_image_composite (_pixman_operator (op),
|
||||
src->pixman_image,
|
||||
mask->pixman_image,
|
||||
dst->pixman_image,
|
||||
|
@ -860,7 +792,7 @@ _cairo_image_surface_composite (cairo_operator_t op,
|
|||
}
|
||||
else
|
||||
{
|
||||
pixman_composite (_pixman_operator (op),
|
||||
pixman_image_composite (_pixman_operator (op),
|
||||
src->pixman_image,
|
||||
NULL,
|
||||
dst->pixman_image,
|
||||
|
@ -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);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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,46 +961,42 @@ _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),
|
||||
pixman_image_composite (_pixman_operator (op),
|
||||
src->pixman_image,
|
||||
mask,
|
||||
dst->pixman_image,
|
||||
|
@ -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, ®ion->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,8 +215,7 @@ _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;
|
||||
|
@ -258,8 +258,6 @@ _cairo_dtostr (char *buffer, size_t size, double d)
|
|||
p--;
|
||||
}
|
||||
}
|
||||
|
||||
return p + 1 - buffer;
|
||||
}
|
||||
|
||||
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,20 +306,30 @@ _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') {
|
||||
length_modifier = LENGTH_MODIFIER_LONG;
|
||||
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':
|
||||
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:
|
||||
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,12 +218,15 @@ _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) {
|
||||
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,
|
||||
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,
|
||||
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,7 +144,7 @@ _cairo_path_count (cairo_path_t *path,
|
|||
cpc.current_point.x = 0;
|
||||
cpc.current_point.y = 0;
|
||||
|
||||
_cairo_path_fixed_interpret (path_fixed,
|
||||
status = _cairo_path_fixed_interpret (path_fixed,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cpc_move_to,
|
||||
_cpc_line_to,
|
||||
|
@ -151,6 +153,8 @@ _cairo_path_count (cairo_path_t *path,
|
|||
_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,7 +324,7 @@ _cairo_path_populate (cairo_path_t *path,
|
|||
cpp.current_point.x = 0;
|
||||
cpp.current_point.y = 0;
|
||||
|
||||
_cairo_path_fixed_interpret (path_fixed,
|
||||
status = _cairo_path_fixed_interpret (path_fixed,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cpp_move_to,
|
||||
_cpp_line_to,
|
||||
|
@ -327,9 +333,13 @@ _cairo_path_populate (cairo_path_t *path,
|
|||
_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,17 +374,20 @@ _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,
|
||||
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,9 +227,14 @@ 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)
|
||||
while (size) {
|
||||
size_t ret = fwrite (data, 1, size, fp);
|
||||
size -= ret;
|
||||
data += ret;
|
||||
if (size && ferror (fp))
|
||||
png_error(png, "Write Error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_write_to_png:
|
||||
|
@ -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,9 +472,14 @@ 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)
|
||||
while (size) {
|
||||
size_t ret = fread (data, 1, size, fp);
|
||||
size -= ret;
|
||||
data += ret;
|
||||
if (size && ferror (fp))
|
||||
png_error(png, "Read Error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_image_surface_create_from_png:
|
||||
|
|
|
@ -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,
|
||||
_cairo_polygon_add_edge (polygon,
|
||||
&polygon->current_point,
|
||||
&polygon->first_point);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
polygon->has_current_point = FALSE;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -39,9 +39,9 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-ps.h"
|
||||
#include "cairo-ps-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,
|
||||
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,12 +1543,17 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
|||
|
||||
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
|
||||
|
||||
_cairo_surface_fill_rectangle (opaque,
|
||||
status = _cairo_surface_fill_rectangle (opaque,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
CAIRO_COLOR_WHITE,
|
||||
0, 0, image->width, image->height);
|
||||
0, 0,
|
||||
image->width, image->height);
|
||||
if (status) {
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
goto bail0;
|
||||
}
|
||||
|
||||
_cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||
&pattern.base,
|
||||
NULL,
|
||||
opaque,
|
||||
|
@ -1602,6 +1562,10 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
|||
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;
|
||||
|
||||
// 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,6 +632,7 @@ typedef enum {
|
|||
DO_SOLID,
|
||||
DO_SHADING,
|
||||
DO_PATTERN,
|
||||
DO_IMAGE,
|
||||
DO_UNSUPPORTED
|
||||
} cairo_quartz_action_t;
|
||||
|
||||
|
@ -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,11 +885,20 @@ _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_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_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
|
@ -891,9 +920,9 @@ _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_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_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
|
@ -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++) {
|
||||
cg_glyphs[i] = glyphs[i].index;
|
||||
float xf = glyphs[i].x;
|
||||
float yf = glyphs[i].y;
|
||||
cg_glyphs[i] = glyphs[i].index;
|
||||
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 (®ion->rgn);
|
||||
}
|
||||
|
||||
return region;
|
||||
void
|
||||
_cairo_region_init_rect (cairo_region_t *region,
|
||||
cairo_rectangle_int_t *rect)
|
||||
{
|
||||
pixman_region_init_rect (®ion->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;
|
||||
}
|
||||
|
||||
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 (®ion->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 (®ion->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 (®ion->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 (®ion->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 (®ion->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 (®ion->rgn);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_region_translate (cairo_region_t *region,
|
||||
int x, int y)
|
||||
{
|
||||
pixman_region_translate (®ion->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;
|
||||
}
|
||||
|
||||
|
@ -247,8 +267,7 @@ _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_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++;
|
||||
}
|
||||
}
|
||||
|
||||
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,8 +366,15 @@ _cairo_sub_font_collect (void *entry, void *closure)
|
|||
for (i = 0; i <= sub_font->current_subset; i++) {
|
||||
collection->subset_id = i;
|
||||
|
||||
if (sub_font->parent->type == CAIRO_SUBSETS_SCALED) {
|
||||
collection->num_glyphs = 0;
|
||||
collection->max_glyph = 0;
|
||||
} else {
|
||||
/* Assign .notdef glyph to the first glyph in the subset */
|
||||
collection->glyphs[0] = 0;
|
||||
collection->num_glyphs = 1;
|
||||
collection->max_glyph = 0;
|
||||
}
|
||||
|
||||
_cairo_hash_table_foreach (sub_font->sub_font_glyphs,
|
||||
_cairo_sub_font_glyph_collect, collection);
|
||||
|
@ -334,13 +383,14 @@ _cairo_sub_font_collect (void *entry, void *closure)
|
|||
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,45 +468,45 @@ 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;
|
||||
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
|
||||
* bitmap and add to the appropriate subset */
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,21 +517,31 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
|||
memmove (&font_map->holdovers[i],
|
||||
&font_map->holdovers[i+1],
|
||||
(font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
|
||||
|
||||
/* reset any error status */
|
||||
scaled_font->status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (scaled_font->status == CAIRO_STATUS_SUCCESS) {
|
||||
/* We increment the reference count manually here, (rather
|
||||
* than calling into cairo_scaled_font_reference), since we
|
||||
* must modify the reference count while our lock is still
|
||||
* held. */
|
||||
scaled_font->ref_count++;
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
} else {
|
||||
return scaled_font;
|
||||
}
|
||||
|
||||
/* the font has been put into an error status - abandon the cache */
|
||||
_cairo_hash_table_remove (font_map->hash_table, &key.hash_entry);
|
||||
}
|
||||
|
||||
/* Otherwise create it and insert it into the hash table. */
|
||||
status = font_face->backend->scaled_font_create (font_face, font_matrix,
|
||||
ctm, options, &scaled_font);
|
||||
if (status) {
|
||||
_cairo_scaled_font_map_unlock ();
|
||||
return NULL;
|
||||
return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;
|
||||
}
|
||||
|
||||
status = _cairo_hash_table_insert (font_map->hash_table,
|
||||
|
@ -528,8 +554,7 @@ cairo_scaled_font_create (cairo_font_face_t *font_face,
|
|||
* hash table. */
|
||||
_cairo_scaled_font_fini (scaled_font);
|
||||
free (scaled_font);
|
||||
return NULL;
|
||||
}
|
||||
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,31 +519,41 @@ _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;
|
||||
|
||||
status = _cairo_surface_get_extents (dst, &extents);
|
||||
|
||||
if (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 (CAIRO_INT_STATUS_UNSUPPORTED == status) {
|
||||
has_trap_region = FALSE;
|
||||
} else if (status) {
|
||||
return status;
|
||||
} else {
|
||||
has_trap_region = TRUE;
|
||||
}
|
||||
|
||||
if (_cairo_operator_bounded_by_mask (op)) {
|
||||
cairo_rectangle_int_t trap_extents;
|
||||
|
||||
if (has_trap_region) {
|
||||
status = _cairo_clip_intersect_to_region (clip, &trap_region);
|
||||
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
_cairo_region_extents_rectangle (trap_region, &trap_extents);
|
||||
_cairo_region_get_extents (&trap_region, &trap_extents);
|
||||
} else {
|
||||
cairo_box_t trap_box;
|
||||
_cairo_traps_extents (traps, &trap_box);
|
||||
|
@ -544,72 +562,69 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
|
|||
|
||||
_cairo_rectangle_intersect (&extents, &trap_extents);
|
||||
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
|
||||
|
||||
if (status)
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
|
||||
|
||||
if (trap_region && !clip_surface) {
|
||||
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.
|
||||
*/
|
||||
clear_region = _cairo_region_create_from_rectangle (&extents);
|
||||
if (clear_region == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
_cairo_region_init_rect (&clear_region, &extents);
|
||||
|
||||
has_clear_region = TRUE;
|
||||
status = _cairo_clip_intersect_to_region (clip, &clear_region);
|
||||
|
||||
status = _cairo_clip_intersect_to_region (clip, clear_region);
|
||||
if (status)
|
||||
return status;
|
||||
goto out;
|
||||
|
||||
_cairo_region_extents_rectangle (clear_region, &extents);
|
||||
_cairo_region_get_extents (&clear_region, &extents);
|
||||
|
||||
if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
status = _cairo_region_subtract (&clear_region, &clear_region, &trap_region);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
if (!pixman_region_not_empty (clear_region)) {
|
||||
pixman_region_destroy (clear_region);
|
||||
clear_region = NULL;
|
||||
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)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
if (trap_region)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if ((src->type == CAIRO_PATTERN_TYPE_SOLID ||
|
||||
op == CAIRO_OPERATOR_CLEAR) && !clip_surface) {
|
||||
const cairo_color_t *color;
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR)
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
color = CAIRO_COLOR_TRANSPARENT;
|
||||
else
|
||||
} 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, op, color, &trap_region);
|
||||
|
||||
if (!status && has_clear_region)
|
||||
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
clear_region);
|
||||
&clear_region);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) ||
|
||||
!clip_surface)
|
||||
{
|
||||
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
|
||||
|
@ -626,13 +641,13 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
|
|||
* 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)
|
||||
&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);
|
||||
&clear_region);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -642,14 +657,14 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
|
|||
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);
|
||||
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,7 +705,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
_clip_and_composite_trapezoids (source,
|
||||
status = _clip_and_composite_trapezoids (source,
|
||||
op,
|
||||
surface,
|
||||
&traps,
|
||||
|
@ -699,7 +714,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
|
|||
|
||||
_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,7 +839,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
_clip_and_composite_trapezoids (source,
|
||||
status = _clip_and_composite_trapezoids (source,
|
||||
op,
|
||||
surface,
|
||||
&traps,
|
||||
|
@ -807,7 +848,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
|
|||
|
||||
_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,7 +1053,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
|
||||
_cairo_pattern_init_for_surface (&pattern.surface, &image->base);
|
||||
|
||||
_cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base,
|
||||
NULL,
|
||||
snapshot,
|
||||
|
@ -990,6 +1064,10 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
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,
|
||||
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);
|
||||
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,18 +313,22 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other,
|
|||
return (cairo_surface_t*) &_cairo_surface_nil;
|
||||
}
|
||||
|
||||
source = _cairo_pattern_create_solid (color);
|
||||
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);
|
||||
|
||||
if (source != pattern)
|
||||
cairo_pattern_destroy (source);
|
||||
|
||||
if (status) {
|
||||
|
@ -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,33 +1230,46 @@ 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)
|
||||
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);
|
||||
|
||||
_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,
|
||||
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.
|
||||
|
@ -1887,27 +1981,28 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
|
|||
|
||||
/* 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) {
|
||||
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);
|
||||
&clear_region);
|
||||
|
||||
CLEANUP_REGIONS:
|
||||
if (drawn_region)
|
||||
pixman_region_destroy (drawn_region);
|
||||
if (clear_region)
|
||||
pixman_region_destroy (clear_region);
|
||||
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_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
|
||||
|
@ -89,9 +101,7 @@ _cairo_traps_init_box (cairo_traps_t *traps,
|
|||
{
|
||||
_cairo_traps_init (traps);
|
||||
|
||||
traps->status = _cairo_traps_grow (traps);
|
||||
if (traps->status)
|
||||
return traps->status;
|
||||
assert (traps->traps_size >= 1);
|
||||
|
||||
traps->num_traps = 1;
|
||||
|
||||
|
@ -109,23 +119,84 @@ _cairo_traps_init_box (cairo_traps_t *traps,
|
|||
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_int_status_t
|
||||
_cairo_traps_extract_region (cairo_traps_t *traps,
|
||||
pixman_region16_t **region)
|
||||
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;
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
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,
|
||||
|
||||
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,
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
|
||||
tag, 0, buffer, &size);
|
||||
return 0;
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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);
|
||||
maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs);
|
||||
if (font->status)
|
||||
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;
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs);
|
||||
|
||||
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;
|
||||
|
||||
if (num_strings) {
|
||||
offsets_length = num_strings * sizeof (unsigned long);
|
||||
truetype_subset->string_offsets = malloc (offsets_length);
|
||||
if (truetype_subset->string_offsets == NULL)
|
||||
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;
|
||||
} 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 {
|
||||
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_integer (data, 500, type);
|
||||
charstring_encode_integer (data, 500, type);
|
||||
charstring_encode_command (data, CHARSTRING_sbw);
|
||||
}
|
||||
|
||||
charstring_encode_command (data, CHARSTRING_endchar);
|
||||
|
||||
|
@ -337,6 +358,7 @@ static cairo_int_status_t
|
|||
cairo_type1_font_create_charstring (cairo_type1_font_t *font,
|
||||
int subset_index,
|
||||
int glyph_index,
|
||||
cairo_charstring_type_t type,
|
||||
cairo_array_t *data)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
|
@ -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);
|
||||
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.data = data;
|
||||
path_info.current_x = (int) scaled_glyph->metrics.x_bearing;
|
||||
path_info.current_y = (int) scaled_glyph->metrics.y_bearing;
|
||||
} else {
|
||||
charstring_encode_integer (data, (int) scaled_glyph->metrics.width, type);
|
||||
|
||||
path_info.current_x = 0;
|
||||
path_info.current_y = 0;
|
||||
}
|
||||
path_info.data = data;
|
||||
path_info.type = type;
|
||||
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,
|
||||
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);
|
||||
|
||||
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;
|
||||
|
@ -1377,7 +1375,7 @@ _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_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:
|
||||
|
@ -1488,7 +1533,7 @@ _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_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 (n_boxes > 0) {
|
||||
rects = malloc (sizeof(xcb_rectangle_t) * n_boxes);
|
||||
if (rects == NULL)
|
||||
if (_cairo_region_get_boxes (region, &n_boxes, &boxes) != CAIRO_STATUS_SUCCESS)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (n_boxes > 0) {
|
||||
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;
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Unhook from the global list
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
assert (info->ref_count > 0);
|
||||
info->ref_count++;
|
||||
|
||||
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;
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xlib_screen_info_reset (void)
|
||||
void
|
||||
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info, *next;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
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)
|
||||
void
|
||||
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
|
||||
{
|
||||
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;
|
||||
cairo_xlib_screen_info_t *list;
|
||||
|
||||
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) {
|
||||
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;
|
||||
info->next = _cairo_xlib_screen_list;
|
||||
_cairo_xlib_screen_list = info;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (info->display->mutex);
|
||||
|
||||
if (info)
|
||||
return info;
|
||||
_cairo_xlib_screen_info_close_display (info);
|
||||
|
||||
if (screen == NULL)
|
||||
return NULL;
|
||||
_cairo_xlib_display_destroy (info->display);
|
||||
|
||||
info = malloc (sizeof (cairo_xlib_screen_info_t));
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
if (!seen_display) {
|
||||
codes = XAddExtension (dpy);
|
||||
if (!codes) {
|
||||
free (info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
|
||||
}
|
||||
|
||||
info->display = dpy;
|
||||
info->screen = screen;
|
||||
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
|
||||
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
|
||||
|
||||
info->close_display_hooks = NULL;
|
||||
|
||||
_cairo_xlib_init_screen_font_options (info);
|
||||
|
||||
info->next = _cairo_xlib_screen_list;
|
||||
_cairo_xlib_screen_list = info;
|
||||
|
||||
return info;
|
||||
}
|
||||
cairo_xlib_screen_info_t *
|
||||
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
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.
|
||||
display = _cairo_xlib_display_get (dpy);
|
||||
if (display == NULL)
|
||||
return NULL;
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
if (display->closed) {
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
|
||||
if (info->screen == screen) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
if (prev != &display->screens) {
|
||||
*prev = info->next;
|
||||
info->next = display->screens;
|
||||
display->screens = info;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
|
||||
info = _cairo_xlib_screen_info_get_unlocked (dpy, screen);
|
||||
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;
|
||||
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
if (screen) {
|
||||
int event_base, error_base;
|
||||
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
|
||||
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
|
||||
_cairo_xlib_init_screen_font_options (dpy, info);
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_LOCK (display->mutex);
|
||||
info->next = display->screens;
|
||||
display->screens = info;
|
||||
CAIRO_MUTEX_UNLOCK (display->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
DONE:
|
||||
_cairo_xlib_display_destroy (display);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, void *key)
|
||||
static int
|
||||
depth_to_index (int depth)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_xlib_hook_t **prev;
|
||||
cairo_bool_t success = FALSE;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
GC
|
||||
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
|
||||
{
|
||||
if (hook->key == key) {
|
||||
/*
|
||||
* MRU the list
|
||||
*/
|
||||
if (prev != &info->close_display_hooks) {
|
||||
*prev = hook->next;
|
||||
hook->next = info->close_display_hooks;
|
||||
info->close_display_hooks = hook;
|
||||
}
|
||||
break;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
return gc;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
unlock:
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_xlib_remove_close_display_hook (Display *dpy, void *key)
|
||||
cairo_status_t
|
||||
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
|
||||
{
|
||||
cairo_xlib_screen_info_t *info;
|
||||
cairo_xlib_hook_t *hook;
|
||||
cairo_xlib_hook_t **prev;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
|
||||
depth = depth_to_index (depth);
|
||||
|
||||
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;
|
||||
}
|
||||
if (info->gc[depth] != NULL) {
|
||||
status = _cairo_xlib_display_queue_work (info->display,
|
||||
(cairo_xlib_notify_func) XFreeGC,
|
||||
info->gc[depth],
|
||||
NULL);
|
||||
}
|
||||
|
||||
unlock:
|
||||
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
|
||||
}
|
||||
info->gc[depth] = gc;
|
||||
if (reset_clip)
|
||||
info->gc_needs_clip_reset |= 1 << depth;
|
||||
else
|
||||
info->gc_needs_clip_reset &= ~(1 << depth);
|
||||
|
||||
void
|
||||
_cairo_xlib_screen_reset_static_data (void)
|
||||
{
|
||||
_cairo_xlib_screen_info_reset ();
|
||||
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)
|
||||
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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче