--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -19,21 +19,13 @@ VC6 is not supported. Please upgrade to
All patches in the cairo tree are surrounded by "MOZILLA_CAIRO_NOT_DEFINED" (which should NOT be defined).
Some specific things:
max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues
fbcompose-bandaid.patch: Disable "optimized" code in non-MMX case due to bugs
+quartz-glyph-rounding.patch: Round glyph positions, not advances, to float
+
win32-scaled-font-size.patch: Add cairo_win32_font_face_create_for_logfontw_hfont,
allow win32 scaled_fonts to rescale themselves properly to the required CTM
and only use the font_face's hfont if we're sure it's appropriate
-
-win32-no-printer-bitblt.patch: If we need to BitBlt from a DC (to do
-fallback), only bother trying if the IS_DISPLAY flag is set -- many
-printers lie about their support for BitBlt, and we end up getting
-black instead of what we want.
-
-avoid-region-extract.patch: Bail from _cairo_traps_extract_region early
-if we have over 200 traps (arbitrary); this avoids an O(N*N) perf hit
-when the region is built up, because we call union_rect with each rect
-individually instead of building the region up in one go.
\ No newline at end of file
deleted file mode 100644
--- a/gfx/cairo/avoid-region-extract.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-diff -r 0e7cd985a7f0 gfx/cairo/cairo/src/cairo-traps.c
---- a/gfx/cairo/cairo/src/cairo-traps.c Fri Jun 08 18:09:53 2007 -0700
-+++ b/gfx/cairo/cairo/src/cairo-traps.c Fri Jun 08 18:10:48 2007 -0700
-@@ -599,6 +599,12 @@ _cairo_traps_extract_region (cairo_traps
- {
- 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)
-+ return CAIRO_INT_STATUS_UNSUPPORTED;
-+
- for (i = 0; i < traps->num_traps; i++)
- if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
- && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -65,27 +65,26 @@ CSRCS = \
cairo-array.c \
cairo-bentley-ottmann.c \
cairo-cache.c \
cairo-clip.c \
cairo-color.c \
cairo-debug.c \
cairo-deflate-stream.c \
cairo-fixed.c \
- cairo-font-face.c \
+ cairo-font.c \
cairo-font-options.c \
cairo-freelist.c \
cairo-gstate.c \
cairo-hash.c \
cairo-hull.c \
cairo-image-surface.c \
cairo-lzw.c \
cairo-matrix.c \
cairo-meta-surface.c \
- cairo-mutex.c \
cairo-operator.c \
cairo-output-stream.c \
cairo-paginated-surface.c \
cairo-path.c \
cairo-path-bounds.c \
cairo-path-fill.c \
cairo-path-fixed.c \
cairo-path-stroke.c \
@@ -150,18 +149,17 @@ endif
ifdef BUILD_CAIRO_SVG
CSRCS += cairo-svg-surface.c
EXPORTS += cairo-svg.h
endif
ifdef MOZ_X11
CSRCS += cairo-xlib-surface.c \
- cairo-xlib-screen.c \
- cairo-xlib-display.c
+ cairo-xlib-screen.c
EXPORTS += cairo-xlib.h cairo-xlib-xrender.h
endif
ifdef MOZ_ENABLE_CAIRO_FT
CSRCS += cairo-ft-font.c
EXPORTS += cairo-ft.h
OS_INCLUDES += $(CAIRO_FT_CFLAGS)
endif
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -30,17 +30,17 @@
*
* Contributor(s):
* Keith Packard <keithp@keithp.com>
*/
#include "cairoint.h"
#include "cairo-analysis-surface-private.h"
-#include "cairo-paginated-private.h"
+#include "cairo-paginated-surface-private.h"
typedef struct {
cairo_surface_t base;
int width;
int height;
cairo_surface_t *target;
--- a/gfx/cairo/cairo/src/cairo-arc.c
+++ b/gfx/cairo/cairo/src/cairo-arc.c
@@ -29,18 +29,16 @@
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* 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:
error = sqrt (x**2 + y**2) - 1
A simpler error function to work with is:
@@ -82,17 +80,17 @@ static double
{ M_PI / 5.0, 1.11281001494389081528e-06 },
{ M_PI / 6.0, 3.72662000942734705475e-07 },
{ M_PI / 7.0, 1.47783685574284411325e-07 },
{ M_PI / 8.0, 6.63240432022601149057e-08 },
{ M_PI / 9.0, 3.2715520137536980553e-08 },
{ M_PI / 10.0, 1.73863223499021216974e-08 },
{ M_PI / 11.0, 9.81410988043554039085e-09 },
};
- int table_size = ARRAY_LENGTH (table);
+ int table_size = (sizeof (table) / sizeof (table[0]));
for (i = 0; i < table_size; i++)
if (table[i].error < tolerance)
return table[i].angle;
++i;
do {
angle = M_PI / i++;
--- a/gfx/cairo/cairo/src/cairo-atsui-font.c
+++ b/gfx/cairo/cairo/src/cairo-atsui-font.c
@@ -29,20 +29,21 @@
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Calum Robinson
*
* Contributor(s):
* 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"
/*
* FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions
* here so we can use older SDKs.
*/
#ifndef FixedToFloat
#define fixed1 ((Fixed) 0x00010000L)
@@ -111,17 +112,18 @@ static cairo_status_t
cairo_atsui_font_face_t *font_face = abstract_face;
OSStatus err;
ATSUAttributeTag styleTags[] = { kATSUFontTag };
ATSUAttributeValuePtr styleValues[] = { &font_face->font_id };
ByteCount styleSizes[] = { sizeof(ATSUFontID) };
ATSUStyle style;
err = ATSUCreateStyle (&style);
- err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
+ err = ATSUSetAttributes(style,
+ sizeof(styleTags) / sizeof(styleTags[0]),
styleTags, styleSizes, styleValues);
return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
font_matrix, ctm, options, font);
}
static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
CAIRO_FONT_TYPE_ATSUI,
@@ -142,16 +144,24 @@ cairo_atsui_font_face_create_for_atsu_fo
font_face->font_id = font_id;
_cairo_font_face_init (&font_face->base, &_cairo_atsui_font_face_backend);
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,
const CGAffineTransform *theTransform)
{
ATSUStyle style;
OSStatus err;
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag,
@@ -217,23 +227,18 @@ static cairo_status_t
cairo_status_t status;
double xscale = 1.0;
double yscale = 1.0;
font = malloc(sizeof(cairo_atsui_font_t));
if (font == NULL)
return CAIRO_STATUS_NO_MEMORY;
- status = _cairo_scaled_font_init (&font->base,
- font_face, font_matrix, ctm, options,
- &cairo_atsui_scaled_font_backend);
- if (status) {
- free (font);
- return status;
- }
+ _cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
+ &cairo_atsui_scaled_font_backend);
_cairo_matrix_compute_scale_factors (&font->base.scale,
&xscale, &yscale, 1);
font->font_matrix = CGAffineTransformMake (1., 0.,
0., yscale/xscale,
0., 0.);
font->size = FloatToFixed (xscale);
@@ -364,17 +369,18 @@ static cairo_status_t
{
ATSUAttributeTag styleTags[] =
{ kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag };
ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID };
ByteCount styleSizes[] =
{ sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
- err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
+ err = ATSUSetAttributes(style,
+ sizeof(styleTags) / sizeof(styleTags[0]),
styleTags, styleSizes, styleValues);
}
return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
font_matrix, ctm, options, font_out);
}
static void
@@ -386,33 +392,83 @@ static void
return;
if (font->style)
ATSUDisposeStyle(font->style);
if (font->unscaled_style)
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);
if (index > 0xffff)
return kATSDeletedGlyphcode;
return index;
}
static cairo_status_t
_cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
- OSStatus err;
+ OSStatus err, callback_err;
ATSGlyphScreenMetrics metricsH;
+ static ATSCubicMoveToUPP moveProc = NULL;
+ static ATSCubicLineToUPP lineProc = NULL;
+ static ATSCubicCurveToUPP curveProc = NULL;
+ static ATSCubicClosePathUPP closePathProc = NULL;
+ CGMutablePathRef path;
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
double xscale, yscale;
+ CGRect rect;
if (theGlyph == kATSDeletedGlyphcode) {
_cairo_scaled_glyph_set_metrics (scaled_glyph,
&scaled_font->base,
&extents);
return CAIRO_STATUS_SUCCESS;
}
@@ -428,25 +484,51 @@ static cairo_status_t
/* Scale down to font units.*/
_cairo_matrix_compute_scale_factors (&scaled_font->base.scale,
&xscale, &yscale, 1);
xscale = 1.0/xscale;
yscale = 1.0/yscale;
extents.x_advance = metricsH.deviceAdvance.x * xscale;
extents.y_advance = 0;
-
- extents.x_bearing = metricsH.topLeft.x * xscale;
- extents.y_bearing = -metricsH.topLeft.y * yscale;
- extents.width = metricsH.width * xscale;
- extents.height = metricsH.height * yscale;
+
+ if (moveProc == NULL) {
+ moveProc = NewATSCubicMoveToUPP (_move_to_for_metrics);
+ lineProc = NewATSCubicLineToUPP (_line_to_for_metrics);
+ curveProc = NewATSCubicCurveToUPP (_curve_to_for_metrics);
+ closePathProc = NewATSCubicClosePathUPP (_close_path_for_metrics);
+ }
+
+ path = CGPathCreateMutable ();
+
+ /* The callback error contains any error our functions returned.
+ * Its only meaningful if err != noErr, and we don't currently
+ * use it for anything.
+ */
+ err = ATSUGlyphGetCubicPaths (scaled_font->style, theGlyph,
+ moveProc, lineProc, curveProc, closePathProc,
+ (void *)path, &callback_err);
+
+ if (err != noErr) {
+ CGPathRelease (path);
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
+ rect = CGPathGetBoundingBox (path);
+
+ extents.x_bearing = rect.origin.x * xscale;
+ extents.y_bearing = rect.origin.y * yscale;
+ extents.width = rect.size.width * xscale;
+ extents.height = rect.size.height * yscale;
_cairo_scaled_glyph_set_metrics (scaled_glyph,
&scaled_font->base,
&extents);
+ CGPathRelease (path);
+
return CAIRO_STATUS_SUCCESS;
}
static OSStatus
_move_to (const Float32Point *point,
void *callback_data)
{
cairo_atsui_scaled_path_t *scaled_path = callback_data;
@@ -580,63 +662,54 @@ static cairo_status_t
static cairo_status_t
_cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
OSStatus err;
CGContextRef drawingContext;
cairo_image_surface_t *surface;
cairo_format_t format;
- cairo_status_t status;
ATSFontRef atsFont;
CGFontRef cgFont;
cairo_scaled_font_t base = scaled_font->base;
cairo_font_extents_t extents = base.extents;
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
ATSGlyphScreenMetrics metricsH;
double left, bottom, width, height;
double xscale, yscale;
CGRect bbox;
CGAffineTransform transform;
if (theGlyph == kATSDeletedGlyphcode) {
surface = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
- status = cairo_surface_status ((cairo_surface_t *)surface);
- if (status)
- return status;
-
+ if (!surface)
+ return CAIRO_STATUS_NO_MEMORY;
_cairo_scaled_glyph_set_surface (scaled_glyph,
&base,
surface);
return CAIRO_STATUS_SUCCESS;
}
/* Compute a box to contain the glyph mask. The vertical
- * sizes come from the font extents; extra pixels are
+ * sizes come from the font extents; extra pixels are
* added to account for fractional sizes.
*/
height = extents.ascent + extents.descent + 2.0;
bottom = -extents.descent - 1.0;
- _cairo_matrix_compute_scale_factors (&base.scale,
- &xscale, &yscale, 1);
- bbox = CGRectApplyAffineTransform (CGRectMake (1.0, bottom, 1.0, height), CGAffineTransformMakeScale(xscale, yscale));
- bottom = CGRectGetMinY (bbox);
- height = bbox.size.height;
-
/* Horizontal sizes come from the glyph typographic metrics.
* It is possible that this might result in clipped text
* in fonts where the typographic bounds don't cover the ink.
* The width is recalculated, since metricsH.width is rounded.
*/
err = ATSUGlyphGetScreenMetrics (scaled_font->style,
- 1, &theGlyph, 0, false,
+ 1, &theGlyph, 0, false,
false, &metricsH);
left = metricsH.sideBearing.x - 1.0;
width = metricsH.deviceAdvance.x
- metricsH.sideBearing.x
+ metricsH.otherSideBearing.x + 2.0;
/* The xy and yx components are negated because the y-axis
* is flipped into the cairo system then flipped back, ie:
@@ -665,19 +738,18 @@ static cairo_status_t
left = CGRectGetMinX (bbox);
bottom = CGRectGetMinY (bbox);
/* XXX should we select format based on antialiasing flags, as ft does? */
format = CAIRO_FORMAT_A8;
/* create the glyph mask surface */
surface = (cairo_image_surface_t *)cairo_image_surface_create (format, bbox.size.width, bbox.size.height);
- status = cairo_surface_status ((cairo_surface_t *)surface);
- if (status)
- return status;
+ if (!surface)
+ return CAIRO_STATUS_NO_MEMORY;
/* Create a CGBitmapContext for the dest surface for drawing into */
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray ();
drawingContext = CGBitmapContextCreate (surface->data,
surface->width,
surface->height,
--- a/gfx/cairo/cairo/src/cairo-base85-stream.c
+++ b/gfx/cairo/cairo/src/cairo-base85-stream.c
@@ -110,17 +110,17 @@ static cairo_status_t
cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output)
{
cairo_base85_stream_t *stream;
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,
_cairo_base85_stream_close);
stream->output = output;
stream->pending = 0;
return &stream->base;
--- a/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
+++ b/gfx/cairo/cairo/src/cairo-bentley-ottmann.c
@@ -132,17 +132,16 @@ typedef struct _cairo_bo_event_queue {
/* This structure extends cairo_skip_list_t, which must come first. */
typedef struct _cairo_bo_sweep_line {
cairo_skip_list_t active_edges;
cairo_bo_edge_t *head;
cairo_bo_edge_t *tail;
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)
{
int cmp = a->y - b->y;
if (cmp) return cmp;
return a->x - b->x;
}
@@ -688,26 +687,23 @@ static void
cairo_bo_point32_t point)
{
event->type = type;
event->e1 = e1;
event->e2 = e2;
event->point = point;
}
-static cairo_status_t
+static void
_cairo_bo_event_queue_insert (cairo_bo_event_queue_t *queue,
cairo_bo_event_t *event)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
/* Don't insert if there's already an equivalent intersection event in the queue. */
- if (_cairo_skip_list_insert (&queue->intersection_queue, event,
- event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION) == NULL)
- status = CAIRO_STATUS_NO_MEMORY;
- return status;
+ _cairo_skip_list_insert (&queue->intersection_queue, event,
+ event->type == CAIRO_BO_EVENT_TYPE_INTERSECTION);
}
static void
_cairo_bo_event_queue_delete (cairo_bo_event_queue_t *queue,
cairo_bo_event_t *event)
{
if (CAIRO_BO_EVENT_TYPE_INTERSECTION == event->type)
_cairo_skip_list_delete_given ( &queue->intersection_queue, &event->elt );
@@ -749,24 +745,26 @@ static cairo_status_t
sizeof (cairo_bo_event_t));
if (0 == num_edges)
return CAIRO_STATUS_SUCCESS;
/* The skip_elt_t field of a cairo_bo_event_t isn't used for start
* 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) + sizeof(cairo_bo_event_t*)));
- if (events == NULL)
+ events = malloc (num_events * sizeof(cairo_bo_event_t));
+ sorted_event_ptrs = malloc (num_events * sizeof(cairo_bo_event_t*));
+ if (!events || !sorted_event_ptrs) {
+ if (events) free(events);
+ if (sorted_event_ptrs) free(sorted_event_ptrs);
return CAIRO_STATUS_NO_MEMORY;
-
- sorted_event_ptrs = (cairo_bo_event_t **) (events + num_events);
+ }
event_queue->startstop_events = events;
event_queue->sorted_startstop_event_ptrs = sorted_event_ptrs;
- event_queue->num_startstop_events = num_events;
+ event_queue->num_startstop_events = (unsigned)(num_events);
event_queue->next_startstop_event_index = 0;
for (i = 0; i < num_edges; i++) {
sorted_event_ptrs[2*i] = &events[2*i];
sorted_event_ptrs[2*i+1] = &events[2*i+1];
/* Initialize "middle" to top */
edges[i].middle = edges[i].top;
@@ -789,51 +787,53 @@ static cairo_status_t
}
static void
_cairo_bo_event_queue_fini (cairo_bo_event_queue_t *event_queue)
{
_cairo_skip_list_fini (&event_queue->intersection_queue);
if (event_queue->startstop_events)
free (event_queue->startstop_events);
+ if (event_queue->sorted_startstop_event_ptrs)
+ free (event_queue->sorted_startstop_event_ptrs);
}
-static cairo_status_t
+static void
_cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_t *event_queue,
cairo_bo_edge_t *left,
cairo_bo_edge_t *right)
{
cairo_bo_status_t status;
cairo_bo_point32_t intersection;
cairo_bo_event_t event;
if (left == NULL || right == NULL)
- return CAIRO_STATUS_SUCCESS;
+ return;
/* The names "left" and "right" here are correct descriptions of
* the order of the two edges within the active edge list. So if a
* slope comparison also puts left less than right, then we know
* that the intersection of these two segments has oalready
* occurred before the current sweep line position. */
if (_slope_compare (left, right) < 0)
- return CAIRO_STATUS_SUCCESS;
+ return;
status = _cairo_bo_edge_intersect (left, right, &intersection);
if (status == CAIRO_BO_STATUS_PARALLEL ||
status == CAIRO_BO_STATUS_NO_INTERSECTION)
{
- return CAIRO_STATUS_SUCCESS;
+ return;
}
_cairo_bo_event_init (&event,
CAIRO_BO_EVENT_TYPE_INTERSECTION,
left, right,
intersection);
- return _cairo_bo_event_queue_insert (event_queue, &event);
+ _cairo_bo_event_queue_insert (event_queue, &event);
}
static void
_cairo_bo_sweep_line_init (cairo_bo_sweep_line_t *sweep_line)
{
_cairo_skip_list_init (&sweep_line->active_edges,
_sweep_line_elt_compare,
sizeof (sweep_line_elt_t));
@@ -843,28 +843,26 @@ static void
}
static void
_cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
{
_cairo_skip_list_fini (&sweep_line->active_edges);
}
-static cairo_status_t
+static void
_cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
cairo_bo_edge_t *edge)
{
skip_elt_t *next_elt;
sweep_line_elt_t *sweep_line_elt;
cairo_bo_edge_t **prev_of_next, **next_of_prev;
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)
prev_of_next = & (SKIP_ELT_TO_EDGE (next_elt)->prev);
else
prev_of_next = &sweep_line->tail;
if (*prev_of_next)
@@ -873,18 +871,16 @@ static cairo_status_t
next_of_prev = &sweep_line->head;
edge->prev = *prev_of_next;
edge->next = *next_of_prev;
*prev_of_next = edge;
*next_of_prev = edge;
edge->sweep_line_elt = sweep_line_elt;
-
- return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_bo_sweep_line_delete (cairo_bo_sweep_line_t *sweep_line,
cairo_bo_edge_t *edge)
{
cairo_bo_edge_t **left_next, **right_prev;
@@ -1056,16 +1052,17 @@ print_state (const char *msg,
/* Adds the trapezoid, if any, of the left edge to the cairo_traps_t
* of bo_traps. */
static cairo_status_t
_cairo_bo_edge_end_trap (cairo_bo_edge_t *left,
int32_t bot,
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;
if (!trap)
return CAIRO_STATUS_SUCCESS;
/* If the right edge of the trapezoid stopped earlier than the
* left edge, then cut the trapezoid bottom early. */
@@ -1097,36 +1094,35 @@ static cairo_status_t
* TODO: need a real collinearity test here for the cases
* where the trapezoid is degenerate, yet the top and bottom
* coordinates aren't equal. */
if (left_top.x != right_top.x ||
left_top.y != right_top.y ||
left_bot.x != right_bot.x ||
left_bot.y != right_bot.y)
{
- _cairo_traps_add_trap_from_points (bo_traps->traps,
- fixed_top,
- fixed_bot,
- left_top, left_bot,
- right_top, right_bot);
+ status = _cairo_traps_add_trap_from_points (bo_traps->traps,
+ fixed_top,
+ fixed_bot,
+ left_top, left_bot,
+ right_top, right_bot);
#if DEBUG_PRINT_STATE
printf ("Deferred trap: left=(%08x, %08x)-(%08x,%08x) "
"right=(%08x,%08x)-(%08x,%08x) top=%08x, bot=%08x\n",
left->top.x, left->top.y, left->bottom.x, left->bottom.y,
right->top.x, right->top.y, right->bottom.x, right->bottom.y,
trap->top, bot);
#endif
}
}
_cairo_freelist_free (&bo_traps->freelist, trap);
left->deferred_trap = NULL;
-
- return _cairo_traps_status (bo_traps->traps);
+ return status;
}
/* Start a new trapezoid at the given top y coordinate, whose edges
* are `edge' and `edge->next'. If `edge' already has a trapezoid,
* then either add it to the traps in `bo_traps', if the trapezoid's
* right edge differs from `edge->next', or do nothing if the new
* trapezoid would be a continuation of the existing one. */
static cairo_status_t
@@ -1253,30 +1249,27 @@ static cairo_status_t
cairo_fill_rule_t fill_rule,
cairo_traps_t *traps,
cairo_fixed_t xmin,
cairo_fixed_t ymin,
cairo_fixed_t xmax,
cairo_fixed_t ymax,
int *num_intersections)
{
- cairo_status_t status;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
int intersection_count = 0;
cairo_bo_event_queue_t event_queue;
cairo_bo_sweep_line_t sweep_line;
cairo_bo_traps_t bo_traps;
cairo_bo_event_t *event, event_saved;
cairo_bo_edge_t *edge;
cairo_bo_edge_t *left, *right;
cairo_bo_edge_t *edge1, *edge2;
- status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
- if (status)
- return status;
-
+ _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
_cairo_bo_sweep_line_init (&sweep_line);
_cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
#if DEBUG_PRINT_STATE
print_state ("After initializing", &event_queue, &sweep_line);
#endif
while (1)
@@ -1298,33 +1291,27 @@ static cairo_status_t
event_saved = *event;
_cairo_bo_event_queue_delete (&event_queue, event);
event = &event_saved;
switch (event->type) {
case CAIRO_BO_EVENT_TYPE_START:
edge = event->e1;
- status = _cairo_bo_sweep_line_insert (&sweep_line, edge);
- if (status)
- goto unwind;
+ _cairo_bo_sweep_line_insert (&sweep_line, edge);
/* Cache the insert position for use in pass 2.
event->e2 = Sortlist::prev (sweep_line, edge);
*/
left = edge->prev;
right = edge->next;
- status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge);
- if (status)
- goto unwind;
+ _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, edge);
- status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
- if (status)
- goto unwind;
+ _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, edge, right);
#if DEBUG_PRINT_STATE
print_state ("After processing start", &event_queue, &sweep_line);
#endif
_cairo_bo_sweep_line_validate (&sweep_line);
break;
case CAIRO_BO_EVENT_TYPE_STOP:
@@ -1334,19 +1321,17 @@ static cairo_status_t
right = edge->next;
_cairo_bo_sweep_line_delete (&sweep_line, edge);
status = _cairo_bo_edge_end_trap (edge, edge->bottom.y, &bo_traps);
if (status)
goto unwind;
- status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
- if (status)
- goto unwind;
+ _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue, left, right);
#if DEBUG_PRINT_STATE
print_state ("After processing stop", &event_queue, &sweep_line);
#endif
_cairo_bo_sweep_line_validate (&sweep_line);
break;
case CAIRO_BO_EVENT_TYPE_INTERSECTION:
@@ -1364,25 +1349,21 @@ static cairo_status_t
left = edge1->prev;
right = edge2->next;
_cairo_bo_sweep_line_swap (&sweep_line, edge1, edge2);
/* after the swap e2 is left of e1 */
- status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
+ _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
left, edge2);
- if (status)
- goto unwind;
- status = _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
+ _cairo_bo_event_queue_insert_if_intersect_below_current_y (&event_queue,
edge1, right);
- if (status)
- goto unwind;
#if DEBUG_PRINT_STATE
print_state ("After processing intersection", &event_queue, &sweep_line);
#endif
_cairo_bo_sweep_line_validate (&sweep_line);
break;
}
@@ -1416,35 +1397,30 @@ update_minmax(cairo_fixed_t *inout_min,
cairo_status_t
_cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
cairo_polygon_t *polygon,
cairo_fill_rule_t fill_rule)
{
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;
cairo_fixed_t xmax = -0x80000000;
cairo_fixed_t ymax = -0x80000000;
int num_bo_edges;
int i;
if (0 == polygon->num_edges)
return CAIRO_STATUS_SUCCESS;
- if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
- edges = stack_edges;
- } else {
- edges = malloc (polygon->num_edges * sizeof (cairo_bo_edge_t));
- if (edges == NULL)
- return CAIRO_STATUS_NO_MEMORY;
- }
+ edges = malloc (polygon->num_edges * sizeof (cairo_bo_edge_t));
+ if (edges == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
/* Figure out the bounding box of the input coordinates and
* validate that we're not given invalid polygon edges. */
for (i = 0; i < polygon->num_edges; i++) {
update_minmax (&xmin, &xmax, polygon->edges[i].edge.p1.x);
update_minmax (&ymin, &ymax, polygon->edges[i].edge.p1.y);
update_minmax (&xmin, &xmax, polygon->edges[i].edge.p2.x);
update_minmax (&ymin, &ymax, polygon->edges[i].edge.p2.y);
@@ -1514,18 +1490,17 @@ cairo_status_t
* passes of the Bentley-Ottmann algorithm. It would merely
* require storing the results of each pass into a temporary
* cairo_traps_t. */
status = _cairo_bentley_ottmann_tessellate_bo_edges (edges, num_bo_edges,
fill_rule, traps,
xmin, ymin, xmax, ymax,
&intersections);
- if (edges != stack_edges)
- free (edges);
+ free (edges);
return status;
}
#if 0
static cairo_bool_t
edges_have_an_intersection_quadratic (cairo_bo_edge_t *edges,
int num_edges)
@@ -1791,17 +1766,17 @@ run_test (const char *test_name,
int
main (void)
{
char random_name[] = "random-XX";
cairo_bo_edge_t random_edges[MAX_RANDOM], *edge;
unsigned int i, num_random;
test_t *test;
- for (i = 0; i < ARRAY_LENGTH (tests); i++) {
+ for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i++) {
test = &tests[i];
run_test (test->name, test->edges, test->num_edges);
}
for (num_random = 0; num_random < MAX_RANDOM; num_random++) {
srand (0);
for (i = 0; i < num_random; i++) {
do {
--- a/gfx/cairo/cairo/src/cairo-cache-private.h
+++ b/gfx/cairo/cairo/src/cairo-cache-private.h
@@ -34,17 +34,17 @@
* Keith Packard <keithp@keithp.com>
* Graydon Hoare <graydon@redhat.com>
* Carl Worth <cworth@cworth.org>
*/
#ifndef CAIRO_CACHE_PRIVATE_H
#define CAIRO_CACHE_PRIVATE_H
-#include "cairo-types-private.h"
+typedef struct _cairo_cache cairo_cache_t;
/**
* cairo_cache_entry_t:
*
* A #cairo_cache_entry_t contains both a key and a value for
* cairo_cache_t. User-derived types for cairo_cache_entry_t must
* have a cairo_cache_entry_t as their first field. For example:
*
--- a/gfx/cairo/cairo/src/cairo-cache.c
+++ b/gfx/cairo/cairo/src/cairo-cache.c
@@ -33,16 +33,27 @@
* Contributor(s):
* Keith Packard <keithp@keithp.com>
* Graydon Hoare <graydon@redhat.com>
* Carl Worth <cworth@cworth.org>
*/
#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);
static void
_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
unsigned long additional);
--- a/gfx/cairo/cairo/src/cairo-cff-subset.c
+++ b/gfx/cairo/cairo/src/cairo-cff-subset.c
@@ -32,44 +32,39 @@
* Contributor(s):
* Adrian Johnson <ajohnson@redneon.com>
* Eugeniy Meshcheryakov <eugen@debian.org>
*/
#include "cairoint.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-truetype-subset-private.h"
-#include <string.h>
/* CFF Dict Operators. If the high byte is 0 the command is encoded
* with a single byte. */
#define BASEFONTNAME_OP 0x0c16
-#define CIDCOUNT_OP 0x0c22
#define CHARSET_OP 0x000f
#define CHARSTRINGS_OP 0x0011
#define COPYRIGHT_OP 0x0c00
#define ENCODING_OP 0x0010
#define FAMILYNAME_OP 0x0003
-#define FDARRAY_OP 0x0c24
-#define FDSELECT_OP 0x0c25
-#define FONTBBOX_OP 0x0005
#define FONTNAME_OP 0x0c26
#define FULLNAME_OP 0x0002
#define LOCAL_SUB_OP 0x0013
#define NOTICE_OP 0x0001
#define POSTSCRIPT_OP 0x0c15
#define PRIVATE_OP 0x0012
#define ROS_OP 0x0c1e
-#define UNIQUEID_OP 0x000d
#define VERSION_OP 0x0000
#define WEIGHT_OP 0x0004
-#define XUID_OP 0x000e
#define NUM_STD_STRINGS 391
+#define ARRAY_LENGTH(a) ( (sizeof (a)) / (sizeof ((a)[0])) )
+
typedef struct _cff_header {
uint8_t major;
uint8_t minor;
uint8_t header_size;
uint8_t offset_size;
} cff_header_t;
typedef struct _cff_index_element {
@@ -82,16 +77,23 @@ typedef struct _cff_dict_operator {
cairo_hash_entry_t base;
unsigned short operator;
unsigned char *operand;
int operand_length;
int operand_offset;
} cff_dict_operator_t;
+typedef struct _cff_charset {
+ cairo_bool_t is_builtin;
+ const uint16_t *sids;
+ const unsigned char *data;
+ int length;
+} cff_charset_t;
+
typedef struct _cairo_cff_font {
cairo_scaled_font_subset_t *scaled_font_subset;
const cairo_scaled_font_backend_t *backend;
/* Font Data */
unsigned char *data;
unsigned long data_length;
@@ -101,33 +103,24 @@ typedef struct _cairo_cff_font {
char *font_name;
cairo_hash_table_t *top_dict;
cairo_hash_table_t *private_dict;
cairo_array_t strings_index;
cairo_array_t charstrings_index;
cairo_array_t global_sub_index;
cairo_array_t local_sub_index;
int num_glyphs;
- cairo_bool_t is_cid;
-
- /* CID Font Data */
- int *fdselect;
- unsigned int num_fontdicts;
- cairo_hash_table_t **fd_dict;
- cairo_hash_table_t **fd_private_dict;
- cairo_array_t *fd_local_sub_index;
+ cff_charset_t charset;
+ int charset_offset;
/* Subsetted Font Data */
char *subset_font_name;
cairo_array_t charstrings_subset_index;
cairo_array_t strings_subset_index;
- int *fdselect_subset;
- unsigned int num_subset_fontdicts;
- int *fd_subset_map;
- int *private_dict_offset;
+ cairo_array_t charset_subset;
cairo_array_t output;
/* Subset Metrics */
int *widths;
int x_min, y_min, x_max, y_max;
int ascent, descent;
} cairo_cff_font_t;
@@ -349,16 +342,17 @@ cff_index_write (cairo_array_t *index, c
for (i = 0; i < num_elem; i++) {
element = _cairo_array_index (index, i);
offset += element->length;
encode_index_offset (buf, offset_size, offset);
status = _cairo_array_append_multiple (output, buf, offset_size);
if (status)
return status;
+
}
for (i = 0; i < num_elem; i++) {
element = _cairo_array_index (index, i);
status = _cairo_array_append_multiple (output,
element->data,
element->length);
if (status)
@@ -375,19 +369,17 @@ cff_index_append (cairo_array_t *index,
element.length = length;
element.is_copy = FALSE;
element.data = object;
return _cairo_array_append (index, &element);
}
static cairo_status_t
-cff_index_append_copy (cairo_array_t *index,
- const unsigned char *object,
- unsigned int length)
+cff_index_append_copy (cairo_array_t *index, unsigned char *object , int length)
{
cff_index_element_t element;
element.length = length;
element.is_copy = TRUE;
element.data = malloc (element.length);
if (element.data == NULL)
return CAIRO_STATUS_NO_MEMORY;
@@ -491,31 +483,16 @@ cff_dict_read (cairo_hash_table_t *dict,
}
fail:
_cairo_array_fini (&operands);
return status;
}
-static void
-cff_dict_remove (cairo_hash_table_t *dict, unsigned short operator)
-{
- cff_dict_operator_t key, *op;
-
- _cairo_dict_init_key (&key, operator);
- if (_cairo_hash_table_lookup (dict, &key.base,
- (cairo_hash_entry_t **) &op))
- {
- free (op->operand);
- _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) op);
- free (op);
- }
-}
-
static unsigned char *
cff_dict_get_operands (cairo_hash_table_t *dict,
unsigned short operator,
int *size)
{
cff_dict_operator_t key, *op;
_cairo_dict_init_key (&key, operator);
@@ -581,65 +558,49 @@ cff_dict_get_location (cairo_hash_table_
}
typedef struct _dict_write_info {
cairo_array_t *output;
cairo_status_t status;
} dict_write_info_t;
static void
-cairo_dict_write_operator (cff_dict_operator_t *op, dict_write_info_t *write_info)
+_cairo_dict_collect (void *entry, void *closure)
{
+ dict_write_info_t *write_info = closure;
+ cff_dict_operator_t *op = entry;
unsigned char data;
+ if (write_info->status)
+ return;
+
op->operand_offset = _cairo_array_num_elements (write_info->output);
- write_info->status = _cairo_array_append_multiple (write_info->output, op->operand, op->operand_length);
+ write_info->status = _cairo_array_append_multiple (write_info->output,
+ op->operand,
+ op->operand_length);
if (write_info->status)
return;
if (op->operator & 0xff00) {
data = op->operator >> 8;
write_info->status = _cairo_array_append (write_info->output, &data);
if (write_info->status)
return;
}
data = op->operator & 0xff;
write_info->status = _cairo_array_append (write_info->output, &data);
}
-static void
-_cairo_dict_collect (void *entry, void *closure)
-{
- dict_write_info_t *write_info = closure;
- cff_dict_operator_t *op = entry;
-
- if (write_info->status)
- return;
-
- /* The ROS operator is handled separately in cff_dict_write() */
- if (op->operator != ROS_OP)
- cairo_dict_write_operator (op, write_info);
-}
-
static cairo_status_t
cff_dict_write (cairo_hash_table_t *dict, cairo_array_t *output)
{
dict_write_info_t write_info;
- cff_dict_operator_t key, *op;
write_info.output = output;
write_info.status = CAIRO_STATUS_SUCCESS;
-
- /* The CFF specification requires that the Top Dict of CID fonts
- * begin with the ROS operator. */
- _cairo_dict_init_key (&key, ROS_OP);
- if (_cairo_hash_table_lookup (dict, &key.base,
- (cairo_hash_entry_t **) &op))
- cairo_dict_write_operator (op, &write_info);
-
_cairo_hash_table_foreach (dict, _cairo_dict_collect, &write_info);
return write_info.status;
}
static void
cff_dict_fini (cairo_hash_table_t *dict)
{
@@ -680,163 +641,42 @@ cairo_cff_font_read_name (cairo_cff_font
status = cff_index_read (&index, &font->current_ptr, font->data_end);
cff_index_fini (&index);
return status;
}
static cairo_int_status_t
cairo_cff_font_read_private_dict (cairo_cff_font_t *font,
- cairo_hash_table_t *private_dict,
- cairo_array_t *local_sub_index,
unsigned char *ptr,
int size)
{
unsigned char buf[10];
unsigned char *end_buf;
int offset;
int i;
unsigned char *operand;
unsigned char *p;
- cff_dict_read (private_dict, ptr, size);
- operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
+ cff_dict_read (font->private_dict, ptr, size);
+ operand = cff_dict_get_operands (font->private_dict, LOCAL_SUB_OP, &i);
if (operand) {
decode_integer (operand, &offset);
p = ptr + offset;
- cff_index_read (local_sub_index, &p, font->data_end);
+ cff_index_read (&font->local_sub_index, &p, font->data_end);
/* Use maximum sized encoding to reserve space for later modification. */
end_buf = encode_integer_max (buf, 0);
- cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p)
-{
- int type, num_ranges, first, last, fd, i, j;
-
- font->fdselect = calloc (font->num_glyphs, sizeof (int));
- if (font->fdselect == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- type = *p++;
- if (type == 0)
- {
- for (i = 0; i < font->num_glyphs; i++)
- font->fdselect[i] = *p++;
- } else if (type == 3) {
- num_ranges = be16_to_cpu( *((uint16_t *)p) );
- p += 2;
- for (i = 0; i < num_ranges; i++)
- {
- first = be16_to_cpu( *((uint16_t *)p) );
- p += 2;
- fd = *p++;
- last = be16_to_cpu( *((uint16_t *)p) );
- for (j = first; j < last; j++)
- font->fdselect[j] = fd;
- }
- } else {
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ cff_dict_set_operands (font->private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
-cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
-{
- cairo_array_t index;
- cff_index_element_t *element;
- unsigned int i;
- int size;
- unsigned char *operand;
- int offset;
- cairo_int_status_t status;
- unsigned char buf[100];
- unsigned char *end_buf;
-
- cff_index_init (&index);
- status = cff_index_read (&index, &ptr, font->data_end);
- if (status)
- goto fail;
-
- font->num_fontdicts = _cairo_array_num_elements (&index);
-
- font->fd_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
- if (font->fd_dict == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto fail;
- }
-
- font->fd_private_dict = calloc (sizeof (cairo_hash_table_t *), font->num_fontdicts);
- if (font->fd_private_dict == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto fail;
- }
-
- font->fd_local_sub_index = calloc (sizeof (cairo_array_t), font->num_fontdicts);
- if (font->fd_local_sub_index == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto fail;
- }
-
- for (i = 0; i < font->num_fontdicts; i++) {
- cff_dict_init (&font->fd_dict[i]);
- if (font->fd_dict[i] == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto fail;
- }
- element = _cairo_array_index (&index, i);
- status = cff_dict_read (font->fd_dict[i], element->data, element->length);
- if (status)
- goto fail;
-
- operand = cff_dict_get_operands (font->fd_dict[i], PRIVATE_OP, &size);
- if (operand == NULL) {
- status = CAIRO_INT_STATUS_UNSUPPORTED;
- goto fail;
- }
- operand = decode_integer (operand, &size);
- decode_integer (operand, &offset);
- cff_dict_init (&font->fd_private_dict[i]);
- if (font->fd_private_dict[i] == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto fail;
- }
- cff_index_init (&font->fd_local_sub_index[i]);
- status = cairo_cff_font_read_private_dict (font,
- font->fd_private_dict[i],
- &font->fd_local_sub_index[i],
- font->data + offset,
- size);
- if (status)
- goto fail;
- /* Set integer operand to max value to use max size encoding to reserve
- * space for any value later */
- end_buf = encode_integer_max (buf, 0);
- end_buf = encode_integer_max (end_buf, 0);
- status = cff_dict_set_operands (font->fd_dict[i], PRIVATE_OP, buf, end_buf - buf);
- if (status)
- goto fail;
- }
-
- return CAIRO_STATUS_SUCCESS;
-
-fail:
- cff_index_fini (&index);
-
- return status;
-}
-
-static cairo_int_status_t
cairo_cff_font_read_top_dict (cairo_cff_font_t *font)
{
cairo_array_t index;
cff_index_element_t *element;
unsigned char buf[20];
unsigned char *end_buf;
unsigned char *operand;
cairo_int_status_t status;
@@ -845,66 +685,53 @@ cairo_cff_font_read_top_dict (cairo_cff_
int offset;
cff_index_init (&index);
status = cff_index_read (&index, &font->current_ptr, font->data_end);
if (status)
goto fail;
element = _cairo_array_index (&index, 0);
- status = cff_dict_read (font->top_dict, element->data, element->length);
- if (status)
- goto fail;
+ cff_dict_read (font->top_dict, element->data, element->length);
- if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL)
- font->is_cid = TRUE;
- else
- font->is_cid = FALSE;
+ /* CID fonts are NYI */
+ if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL) {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto fail;
+ }
operand = cff_dict_get_operands (font->top_dict, CHARSTRINGS_OP, &size);
decode_integer (operand, &offset);
p = font->data + offset;
status = cff_index_read (&font->charstrings_index, &p, font->data_end);
if (status)
goto fail;
font->num_glyphs = _cairo_array_num_elements (&font->charstrings_index);
- if (font->is_cid) {
- operand = cff_dict_get_operands (font->top_dict, FDSELECT_OP, &size);
- decode_integer (operand, &offset);
- cairo_cff_font_read_fdselect (font, font->data + offset);
+ operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
+ operand = decode_integer (operand, &size);
+ decode_integer (operand, &offset);
+ cairo_cff_font_read_private_dict (font, font->data + offset, size);
- operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
- decode_integer (operand, &offset);
- cairo_cff_font_read_cid_fontdict (font, font->data + offset);
- } else {
- operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
- operand = decode_integer (operand, &size);
- decode_integer (operand, &offset);
- cairo_cff_font_read_private_dict (font,
- font->private_dict,
- &font->local_sub_index,
- font->data + offset,
- size);
+ operand = cff_dict_get_operands (font->top_dict, CHARSET_OP, &size);
+ if (!operand)
+ font->charset_offset = 0;
+ else {
+ decode_integer (operand, &offset);
+ font->charset_offset = offset;
}
/* Use maximum sized encoding to reserve space for later modification. */
end_buf = encode_integer_max (buf, 0);
cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
- cff_dict_set_operands (font->top_dict, FDSELECT_OP, buf, end_buf - buf);
- cff_dict_set_operands (font->top_dict, FDARRAY_OP, buf, end_buf - buf);
+ cff_dict_set_operands (font->top_dict, ENCODING_OP, buf, end_buf - buf);
cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
-
- cff_dict_remove (font->top_dict, ENCODING_OP);
- cff_dict_remove (font->top_dict, PRIVATE_OP);
-
- /* Remove the unique identifier operators as the subsetted font is
- * not the same is the original font. */
- cff_dict_remove (font->top_dict, UNIQUEID_OP);
- cff_dict_remove (font->top_dict, XUID_OP);
+ /* Private has two operands - size and offset */
+ end_buf = encode_integer_max (end_buf, 0);
+ cff_dict_set_operands (font->top_dict, PRIVATE_OP, buf, end_buf - buf);
fail:
cff_index_fini (&index);
return status;
}
static cairo_int_status_t
@@ -914,25 +741,159 @@ cairo_cff_font_read_strings (cairo_cff_f
}
static cairo_int_status_t
cairo_cff_font_read_global_subroutines (cairo_cff_font_t *font)
{
return cff_index_read (&font->global_sub_index, &font->current_ptr, font->data_end);
}
+static cairo_int_status_t
+cff_charset_read_data (cff_charset_t *charset, const unsigned char *data,
+ const unsigned char *data_end, int num_glyphs)
+{
+ const unsigned char *p = data;
+
+ num_glyphs -= 1; /* do not count .notdef */
+
+ if (p + 1 > data_end)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ switch (*p++) {
+ case 0:
+ if (p + num_glyphs*2 > data_end)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ charset->is_builtin = FALSE;
+ charset->data = data;
+ charset->length = num_glyphs * 2 + 1;
+ break;
+ case 1:
+ while (num_glyphs > 0) {
+ if (p + 3 > data_end)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ num_glyphs -= p[2] + 1;
+ p += 3;
+ }
+ if (num_glyphs < 0)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ charset->is_builtin = FALSE;
+ charset->data = data;
+ charset->length = p - data;
+ break;
+ case 2:
+ while (num_glyphs > 0) {
+ if (p + 4 > data_end)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ num_glyphs -= be16_to_cpu(*(uint16_t *)(p + 2)) + 1;
+ p += 4;
+ }
+ if (num_glyphs < 0)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ charset->is_builtin = FALSE;
+ charset->data = data;
+ charset->length = p - data;
+ break;
+ default:
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static const uint16_t ISOAdobe_charset[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
+ 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
+ 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+ 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
+ 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+ 222, 223, 224, 225, 226, 227, 228,
+};
+
+static const uint16_t Expert_charset[] = {
+ 1, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 13,
+ 14, 15, 99, 239, 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 27, 28, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+ 258, 259, 260, 261, 262, 263, 264, 265, 266, 109, 110,
+ 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+ 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
+ 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
+ 311, 312, 313, 314, 315, 316, 317, 318, 158, 155, 163,
+ 319, 320, 321, 322, 323, 324, 325, 326, 150, 164, 169,
+ 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337,
+ 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
+ 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
+ 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370,
+ 371, 372, 373, 374, 375, 376, 377, 378,
+};
+
+static const uint16_t ExpertSubset_charset[] = {
+ 1, 231, 232, 235, 236, 237, 238, 13, 14, 15, 99, 239, 240,
+ 241, 242, 243, 244, 245, 246, 247, 248, 27, 28, 249, 250,
+ 251, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262,
+ 263, 264, 265, 266, 109, 110, 267, 268, 269, 270, 272,
+ 300, 301, 302, 305, 314, 315, 158, 155, 163, 320, 321,
+ 322, 323, 324, 325, 326, 150, 164, 169, 327, 328, 329,
+ 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340,
+ 341, 342, 343, 344, 345, 346,
+};
+
+static cairo_int_status_t
+cairo_cff_font_read_charset (cairo_cff_font_t *font)
+{
+ switch (font->charset_offset) {
+ case 0:
+ /* ISOAdobe charset */
+ font->charset.is_builtin = TRUE;
+ font->charset.sids = ISOAdobe_charset;
+ font->charset.length = sizeof (ISOAdobe_charset);
+ return CAIRO_STATUS_SUCCESS;
+ case 1:
+ /* Expert charset */
+ font->charset.is_builtin = TRUE;
+ font->charset.sids = Expert_charset;
+ font->charset.length = sizeof (Expert_charset);
+ return CAIRO_STATUS_SUCCESS;
+ case 2:
+ /* ExpertSubset charset */;
+ font->charset.is_builtin = TRUE;
+ font->charset.sids = ExpertSubset_charset;
+ font->charset.length = sizeof (ExpertSubset_charset);
+ return CAIRO_STATUS_SUCCESS;
+ default:
+ break;
+ }
+ return cff_charset_read_data (&font->charset, font->data + (unsigned)font->charset_offset,
+ font->data_end, font->num_glyphs);
+}
+
typedef cairo_int_status_t
(*font_read_t) (cairo_cff_font_t *font);
static const font_read_t font_read_funcs[] = {
cairo_cff_font_read_header,
cairo_cff_font_read_name,
cairo_cff_font_read_top_dict,
cairo_cff_font_read_strings,
cairo_cff_font_read_global_subroutines,
+ /* non-contiguous */
+ cairo_cff_font_read_charset,
};
static cairo_int_status_t
cairo_cff_font_read_font (cairo_cff_font_t *font)
{
cairo_int_status_t status;
unsigned int i;
@@ -940,44 +901,16 @@ cairo_cff_font_read_font (cairo_cff_font
status = font_read_funcs[i] (font);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}
-static void
-cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
-{
- unsigned char buf[30];
- unsigned char *p;
- int sid1, sid2;
- const char *registry = "Adobe";
- const char *ordering = "Identity";
-
- sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
- cff_index_append_copy (&font->strings_subset_index,
- (unsigned char *)registry,
- strlen(registry));
-
- sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
- cff_index_append_copy (&font->strings_subset_index,
- (unsigned char *)ordering,
- strlen(ordering));
-
- p = encode_integer (buf, sid1);
- p = encode_integer (p, sid2);
- p = encode_integer (p, 0);
- cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
-
- p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
- cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
-}
-
static cairo_status_t
cairo_cff_font_subset_dict_string(cairo_cff_font_t *font,
cairo_hash_table_t *dict,
int operator)
{
int size;
unsigned char *p;
int sid;
@@ -1029,156 +962,148 @@ cairo_cff_font_subset_dict_strings (cair
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
+cairo_cff_font_subset_strings (cairo_cff_font_t *font)
+{
+ cairo_status_t status;
+
+ status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
+ if (status)
+ return status;
+
+ status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
+
+ return status;
+}
+
+static cairo_status_t
cairo_cff_font_subset_charstrings (cairo_cff_font_t *font)
{
cff_index_element_t *element;
unsigned int i;
cairo_status_t status;
+ /* add .notdef */
+ element = _cairo_array_index (&font->charstrings_index, 0);
+ status = cff_index_append (&font->charstrings_subset_index,
+ element->data,
+ element->length);
+ if (status)
+ return status;
+
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
element = _cairo_array_index (&font->charstrings_index,
font->scaled_font_subset->glyphs[i]);
status = cff_index_append (&font->charstrings_subset_index,
element->data,
element->length);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
-cairo_cff_font_subset_fontdict (cairo_cff_font_t *font)
+static uint16_t
+cff_sid_from_gid (const cff_charset_t *charset, int gid)
{
- unsigned int i;
- int fd;
- int *reverse_map;
-
- font->fdselect_subset = calloc (font->scaled_font_subset->num_glyphs,
- sizeof (int));
- if (font->fdselect_subset == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int));
- if (font->fd_subset_map == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int));
- if (font->private_dict_offset == NULL)
- return CAIRO_STATUS_NO_MEMORY;
+ const uint16_t *sids;
+ const unsigned char *p;
+ int prev_glyph;
- reverse_map = calloc (font->num_fontdicts, sizeof (int));
- if (reverse_map == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- for (i = 0; i < font->num_fontdicts; i++)
- reverse_map[i] = -1;
-
- font->num_subset_fontdicts = 0;
- for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
- fd = font->fdselect[font->scaled_font_subset->glyphs[i]];
- if (reverse_map[fd] < 0) {
- font->fd_subset_map[font->num_subset_fontdicts] = fd;
- reverse_map[fd] = font->num_subset_fontdicts++;
- }
- font->fdselect_subset[i] = reverse_map[fd];
+ if (charset->is_builtin) {
+ if (gid - 1 < charset->length / 2)
+ return charset->sids[gid - 1];
}
-
- free (reverse_map);
-
- return CAIRO_STATUS_SUCCESS;
+ else {
+ /* no need to check sizes here, this was done during reading */
+ switch (charset->data[0]) {
+ case 0:
+ sids = (const uint16_t *)(charset->data + 1);
+ return be16_to_cpu(sids[gid - 1]);
+ case 1:
+ prev_glyph = 1;
+ for (p = charset->data + 1; p < charset->data + charset->length; p += 3) {
+ if (gid <= prev_glyph + p[2]) {
+ uint16_t sid = be16_to_cpu(*(const uint16_t *)p);
+ return sid + gid - prev_glyph;
+ }
+ prev_glyph += p[2] + 1;
+ }
+ break;
+ case 2:
+ prev_glyph = 1;
+ for (p = charset->data + 1; p < charset->data + charset->length; p += 4) {
+ uint16_t nLeft = be16_to_cpu(*(const uint16_t *)(p + 2));
+ if (gid <= prev_glyph + nLeft) {
+ uint16_t sid = be16_to_cpu(*(const uint16_t *)p);
+ return sid + gid - prev_glyph;
+ }
+ prev_glyph += nLeft + 1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return 0;
}
static cairo_status_t
-cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
+cairo_cff_font_subset_charset (cairo_cff_font_t *font)
{
- unsigned char buf[100];
- unsigned char *end_buf;
-
- font->num_fontdicts = 1;
- font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
- if (font->fd_dict == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- cff_dict_init (&font->fd_dict[0]);
-
- font->fd_subset_map = malloc (sizeof (int));
- if (font->fd_subset_map == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- font->private_dict_offset = malloc (sizeof (int));
- if (font->private_dict_offset == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- font->fd_subset_map[0] = 0;
- font->num_subset_fontdicts = 1;
-
- /* Set integer operand to max value to use max size encoding to reserve
- * space for any value later */
- end_buf = encode_integer_max (buf, 0);
- end_buf = encode_integer_max (end_buf, 0);
- cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-cairo_cff_font_subset_strings (cairo_cff_font_t *font)
-{
- cairo_status_t status;
unsigned int i;
- status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
- if (status)
- return status;
- if (font->is_cid) {
- for (i = 0; i < font->num_subset_fontdicts; i++) {
- status = cairo_cff_font_subset_dict_strings (font, font->fd_dict[font->fd_subset_map[i]]);
- if (status)
- return status;
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
+ int gid = font->scaled_font_subset->glyphs[i];
+ uint16_t original_sid = cff_sid_from_gid(&font->charset, gid);
+ uint16_t new_sid;
+ cff_index_element_t *element;
+ cairo_status_t status;
- status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]);
- if (status)
- return status;
- }
- } else {
- status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
+ if (original_sid >= NUM_STD_STRINGS) {
+ element = _cairo_array_index (&font->strings_index, original_sid - NUM_STD_STRINGS);
+ new_sid = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
+ status = cff_index_append (&font->strings_subset_index, element->data, element->length);
+ if (status)
+ return status;
+ }
+ else
+ new_sid = original_sid;
+
+ status = _cairo_array_append(&font->charset_subset, &new_sid);
+ if (status)
+ return status;
}
-
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_subset_font (cairo_cff_font_t *font)
{
cairo_status_t status;
- cairo_cff_font_set_ros_strings (font);
-
- status = cairo_cff_font_subset_charstrings (font);
- if (status)
- return status;
-
- if (font->is_cid)
- cairo_cff_font_subset_fontdict (font);
- else
- cairo_cff_font_create_cid_fontdict (font);
+ /* TODO: subset subroutines */
status = cairo_cff_font_subset_strings (font);
if (status)
return status;
+ status = cairo_cff_font_subset_charstrings (font);
+ if (status)
+ return status;
+
+ status = cairo_cff_font_subset_charset (font);
+
return status;
}
/* Set the operand of the specified operator in the (already written)
* top dict to point to the current position in the output
* array. Operands updated with this function must have previously
* been encoded with the 5-byte (max) integer encoding. */
static void
@@ -1282,255 +1207,114 @@ cairo_cff_font_write_strings (cairo_cff_
static cairo_status_t
cairo_cff_font_write_global_subrs (cairo_cff_font_t *font)
{
return cff_index_write (&font->global_sub_index, &font->output);
}
static cairo_status_t
-cairo_cff_font_write_fdselect (cairo_cff_font_t *font)
+cairo_cff_font_write_encoding (cairo_cff_font_t *font)
{
- unsigned char data;
- unsigned int i;
- cairo_int_status_t status;
-
- cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDSELECT_OP);
-
- if (font->is_cid) {
- data = 0;
- status = _cairo_array_append (&font->output, &data);
- if (status)
- return status;
-
- for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
- data = font->fdselect_subset[i];
- status = _cairo_array_append (&font->output, &data);
- if (status)
- return status;
- }
- } else {
- unsigned char byte;
- uint16_t word;
+ unsigned char buf[10];
- status = _cairo_array_grow_by (&font->output, 9);
- if (status)
- return status;
-
- byte = 3;
- status = _cairo_array_append (&font->output, &byte);
- assert (status == CAIRO_STATUS_SUCCESS);
-
- word = cpu_to_be16 (1);
- status = _cairo_array_append_multiple (&font->output, &word, 2);
- assert (status == CAIRO_STATUS_SUCCESS);
+ cairo_cff_font_set_topdict_operator_to_cur_pos (font, ENCODING_OP);
+ buf[0] = 1; /* Format 1 */
+ buf[1] = 1; /* Number of ranges */
+ buf[2] = 0; /* First code in range */
+ /* Codes left in range excluding first */
+ buf[3] = font->scaled_font_subset->num_glyphs - 1;
- word = cpu_to_be16 (0);
- status = _cairo_array_append_multiple (&font->output, &word, 2);
- assert (status == CAIRO_STATUS_SUCCESS);
-
- byte = 0;
- status = _cairo_array_append (&font->output, &byte);
- assert (status == CAIRO_STATUS_SUCCESS);
-
- word = cpu_to_be16 (font->scaled_font_subset->num_glyphs);
- status = _cairo_array_append_multiple (&font->output, &word, 2);
- assert (status == CAIRO_STATUS_SUCCESS);
- }
-
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_array_append_multiple (&font->output, buf, 4);
}
static cairo_status_t
cairo_cff_font_write_charset (cairo_cff_font_t *font)
{
- unsigned char byte;
- uint16_t word;
+ unsigned char format = 0;
+ unsigned int i;
cairo_status_t status;
cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
- status = _cairo_array_grow_by (&font->output, 5);
+ status = _cairo_array_append (&font->output, &format);
if (status)
- return status;
-
- byte = 2;
- status = _cairo_array_append (&font->output, &byte);
- assert (status == CAIRO_STATUS_SUCCESS);
+ return status;
- word = cpu_to_be16 (1);
- status = _cairo_array_append_multiple (&font->output, &word, 2);
- assert (status == CAIRO_STATUS_SUCCESS);
-
- word = cpu_to_be16 (font->scaled_font_subset->num_glyphs - 2);
- status = _cairo_array_append_multiple (&font->output, &word, 2);
- assert (status == CAIRO_STATUS_SUCCESS);
-
+ for (i = 0; i < (unsigned)_cairo_array_num_elements(&font->charset_subset); i++) {
+ uint16_t sid = cpu_to_be16(*(uint16_t *)_cairo_array_index(&font->charset_subset, i));
+ status = _cairo_array_append_multiple (&font->output, &sid, sizeof(sid));
+ if (status)
+ return status;
+ }
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_write_charstrings (cairo_cff_font_t *font)
{
cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSTRINGS_OP);
return cff_index_write (&font->charstrings_subset_index, &font->output);
}
static cairo_status_t
-cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
+cairo_cff_font_write_private_dict_and_local_sub (cairo_cff_font_t *font)
{
- unsigned int i;
- cairo_int_status_t status;
- uint32_t *offset_array;
- int offset_base;
- uint16_t count;
- uint8_t offset_size = 4;
-
- cairo_cff_font_set_topdict_operator_to_cur_pos (font, FDARRAY_OP);
- count = cpu_to_be16 (font->num_subset_fontdicts);
- status = _cairo_array_append_multiple (&font->output, &count, sizeof (uint16_t));
- if (status)
- return status;
- status = _cairo_array_append (&font->output, &offset_size);
- if (status)
- return status;
- status = _cairo_array_allocate (&font->output,
- (font->num_subset_fontdicts + 1)*offset_size,
- (void **) &offset_array);
- if (status)
- return status;
- offset_base = _cairo_array_num_elements (&font->output) - 1;
- *offset_array++ = cpu_to_be32(1);
- for (i = 0; i < font->num_subset_fontdicts; i++) {
- status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
- &font->output);
- if (status)
- return status;
- *offset_array++ = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-cairo_cff_font_write_private_dict (cairo_cff_font_t *font,
- int dict_num,
- cairo_hash_table_t *parent_dict,
- cairo_hash_table_t *private_dict)
-{
- int offset;
+ int offset, private_dict_offset;
int size;
unsigned char buf[10];
unsigned char *buf_end;
unsigned char *p;
cairo_status_t status;
/* Write private dict and update offset and size in top dict */
- font->private_dict_offset[dict_num] = _cairo_array_num_elements (&font->output);
- status = cff_dict_write (private_dict, &font->output);
+ private_dict_offset = _cairo_array_num_elements (&font->output);
+ status = cff_dict_write (font->private_dict, &font->output);
if (status)
return status;
- size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
+ size = _cairo_array_num_elements (&font->output) - private_dict_offset;
/* private entry has two operands - size and offset */
buf_end = encode_integer_max (buf, size);
- buf_end = encode_integer_max (buf_end, font->private_dict_offset[dict_num]);
- offset = cff_dict_get_location (parent_dict, PRIVATE_OP, &size);
+ buf_end = encode_integer_max (buf_end, private_dict_offset);
+ offset = cff_dict_get_location (font->top_dict, PRIVATE_OP, &size);
assert (offset > 0);
p = _cairo_array_index (&font->output, offset);
memcpy (p, buf, buf_end - buf);
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-cairo_cff_font_write_local_sub (cairo_cff_font_t *font,
- int dict_num,
- cairo_hash_table_t *private_dict,
- cairo_array_t *local_sub_index)
-{
- int offset;
- int size;
- unsigned char buf[10];
- unsigned char *buf_end;
- unsigned char *p;
- cairo_status_t status;
-
- if (_cairo_array_num_elements (local_sub_index) > 0) {
+ if (_cairo_array_num_elements (&font->local_sub_index) > 0) {
/* Write local subroutines and update offset in private
* dict. Local subroutines offset is relative to start of
* private dict */
- offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
+ offset = _cairo_array_num_elements (&font->output) - private_dict_offset;
buf_end = encode_integer_max (buf, offset);
- offset = cff_dict_get_location (private_dict, LOCAL_SUB_OP, &size);
+ offset = cff_dict_get_location (font->private_dict, LOCAL_SUB_OP, &size);
assert (offset > 0);
p = _cairo_array_index (&font->output, offset);
memcpy (p, buf, buf_end - buf);
- status = cff_index_write (local_sub_index, &font->output);
+ status = cff_index_write (&font->local_sub_index, &font->output);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}
-
-static cairo_status_t
-cairo_cff_font_write_cid_private_dict_and_local_sub (cairo_cff_font_t *font)
-{
- unsigned int i;
- cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
-
- if (font->is_cid) {
- for (i = 0; i < font->num_subset_fontdicts; i++) {
- status = cairo_cff_font_write_private_dict (
- font,
- i,
- font->fd_dict[font->fd_subset_map[i]],
- font->fd_private_dict[font->fd_subset_map[i]]);
- if (status)
- return status;
- }
-
- for (i = 0; i < font->num_subset_fontdicts; i++) {
- status = cairo_cff_font_write_local_sub (
- font,
- i,
- font->fd_private_dict[font->fd_subset_map[i]],
- &font->fd_local_sub_index[font->fd_subset_map[i]]);
- if (status)
- return status;
- }
- } else {
- status = cairo_cff_font_write_private_dict (font,
- 0,
- font->fd_dict[0],
- font->private_dict);
- status = cairo_cff_font_write_local_sub (font,
- 0,
- font->private_dict,
- &font->local_sub_index);
- }
-
- return status;
-}
-
typedef cairo_status_t
(*font_write_t) (cairo_cff_font_t *font);
static const font_write_t font_write_funcs[] = {
cairo_cff_font_write_header,
cairo_cff_font_write_name,
cairo_cff_font_write_top_dict,
cairo_cff_font_write_strings,
cairo_cff_font_write_global_subrs,
- cairo_cff_font_write_fdselect,
+ cairo_cff_font_write_encoding,
cairo_cff_font_write_charset,
cairo_cff_font_write_charstrings,
- cairo_cff_font_write_cid_fontdict,
- cairo_cff_font_write_cid_private_dict_and_local_sub,
+ cairo_cff_font_write_private_dict_and_local_sub,
};
static cairo_status_t
cairo_cff_font_write_subset (cairo_cff_font_t *font)
{
cairo_int_status_t status;
unsigned int i;
@@ -1584,17 +1368,17 @@ cairo_cff_font_create_set_widths (cairo_
size = sizeof (tt_hhea_t);
status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hhea, 0,
(unsigned char*) &hhea, &size);
if (status)
return status;
num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
- for (i = 1; i < font->scaled_font_subset->num_glyphs; i++) {
+ for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
glyph_index = font->scaled_font_subset->glyphs[i];
long_entry_size = 2 * sizeof (int16_t);
short_entry_size = sizeof (int16_t);
if (glyph_index < num_hmetrics) {
status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
glyph_index * long_entry_size,
buf, &short_entry_size);
@@ -1766,23 +1550,17 @@ static cairo_int_status_t
cff_dict_init (&font->top_dict);
cff_dict_init (&font->private_dict);
cff_index_init (&font->strings_index);
cff_index_init (&font->charstrings_index);
cff_index_init (&font->global_sub_index);
cff_index_init (&font->local_sub_index);
cff_index_init (&font->charstrings_subset_index);
cff_index_init (&font->strings_subset_index);
- font->fdselect = NULL;
- font->fd_dict = NULL;
- font->fd_private_dict = NULL;
- font->fd_local_sub_index = NULL;
- font->fdselect_subset = NULL;
- font->fd_subset_map = NULL;
- font->private_dict_offset = NULL;
+ _cairo_array_init (&font->charset_subset, sizeof(uint16_t));
free (name);
*font_return = font;
return CAIRO_STATUS_SUCCESS;
fail7:
free (font->data);
@@ -1799,67 +1577,29 @@ fail2:
fail1:
free (name);
return status;
}
static void
cairo_cff_font_destroy (cairo_cff_font_t *font)
{
- unsigned int i;
-
free (font->widths);
free (font->font_name);
free (font->subset_font_name);
_cairo_array_fini (&font->output);
cff_dict_fini (font->top_dict);
cff_dict_fini (font->private_dict);
cff_index_fini (&font->strings_index);
cff_index_fini (&font->charstrings_index);
cff_index_fini (&font->global_sub_index);
cff_index_fini (&font->local_sub_index);
cff_index_fini (&font->charstrings_subset_index);
cff_index_fini (&font->strings_subset_index);
-
- /* If we bailed out early as a result of an error some of the
- * following cairo_cff_font_t members may still be NULL */
- if (font->fd_dict) {
- for (i = 0; i < font->num_fontdicts; i++) {
- if (font->fd_dict[i])
- cff_dict_fini (font->fd_dict[i]);
- }
- free (font->fd_dict);
- }
- if (font->fd_subset_map)
- free (font->fd_subset_map);
- if (font->private_dict_offset)
- free (font->private_dict_offset);
-
- if (font->is_cid) {
- if (font->fdselect)
- free (font->fdselect);
- if (font->fdselect_subset)
- free (font->fdselect_subset);
- if (font->fd_private_dict) {
- for (i = 0; i < font->num_fontdicts; i++) {
- if (font->fd_private_dict[i])
- cff_dict_fini (font->fd_private_dict[i]);
- }
- free (font->fd_private_dict);
- }
- if (font->fd_local_sub_index) {
- for (i = 0; i < font->num_fontdicts; i++)
- cff_index_fini (&font->fd_local_sub_index[i]);
- free (font->fd_local_sub_index);
- }
- }
-
- if (font->data)
- free (font->data);
-
+ _cairo_array_fini (&font->charset_subset);
free (font);
}
cairo_status_t
_cairo_cff_subset_init (cairo_cff_subset_t *cff_subset,
const char *subset_name,
cairo_scaled_font_subset_t *font_subset)
{
@@ -1917,220 +1657,8 @@ cairo_status_t
void
_cairo_cff_subset_fini (cairo_cff_subset_t *subset)
{
free (subset->base_font);
free (subset->widths);
free (subset->data);
}
-
-static cairo_int_status_t
-_cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset,
- cairo_cff_font_t **font_return,
- const char *subset_name)
-{
- cairo_status_t status;
- cairo_cff_font_t *font;
-
- font = malloc (sizeof (cairo_cff_font_t));
- if (font == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- font->backend = NULL;
- font->scaled_font_subset = scaled_font_subset;
-
- _cairo_array_init (&font->output, sizeof (char));
- status = _cairo_array_grow_by (&font->output, 4096);
- if (status)
- goto fail1;
-
- font->subset_font_name = strdup (subset_name);
- if (font->subset_font_name == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto fail2;
- }
-
- font->font_name = strdup (subset_name);
- if (font->subset_font_name == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto fail3;
- }
-
- font->x_min = 0;
- font->y_min = 0;
- font->x_max = 0;
- font->y_max = 0;
- font->ascent = 0;
- font->descent = 0;
-
- font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
- if (font->widths == NULL) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto fail4;
- }
-
- font->data_length = 0;
- font->data = NULL;
- font->data_end = 0;
-
- cff_dict_init (&font->top_dict);
- cff_dict_init (&font->private_dict);
- cff_index_init (&font->strings_index);
- cff_index_init (&font->charstrings_index);
- cff_index_init (&font->global_sub_index);
- cff_index_init (&font->local_sub_index);
- cff_index_init (&font->charstrings_subset_index);
- cff_index_init (&font->strings_subset_index);
- font->fdselect = NULL;
- font->fd_dict = NULL;
- font->fd_private_dict = NULL;
- font->fd_local_sub_index = NULL;
- font->fdselect_subset = NULL;
- font->fd_subset_map = NULL;
- font->private_dict_offset = NULL;
-
- *font_return = font;
-
- return CAIRO_STATUS_SUCCESS;
-
-fail4:
- free (font->font_name);
-fail3:
- free (font->subset_font_name);
-fail2:
- _cairo_array_fini (&font->output);
-fail1:
- free (font);
- return status;
-}
-
-static cairo_int_status_t
-cairo_cff_font_fallback_generate (cairo_cff_font_t *font,
- cairo_type2_charstrings_t *type2_subset,
- const char **data,
- unsigned long *length)
-{
- cairo_int_status_t status;
- cff_header_t header;
- cairo_array_t *charstring;
- unsigned char buf[40];
- unsigned char *end_buf;
- unsigned int i;
-
- /* Create header */
- header.major = 1;
- header.minor = 0;
- header.header_size = 4;
- header.offset_size = 4;
- font->header = &header;
-
- /* Create Top Dict */
- font->is_cid = FALSE;
- end_buf = encode_integer (buf, type2_subset->x_min);
- end_buf = encode_integer (end_buf, type2_subset->y_min);
- end_buf = encode_integer (end_buf, type2_subset->x_max);
- end_buf = encode_integer (end_buf, type2_subset->y_max);
- cff_dict_set_operands (font->top_dict, FONTBBOX_OP, buf, end_buf - buf);
- end_buf = encode_integer_max (buf, 0);
- cff_dict_set_operands (font->top_dict, CHARSTRINGS_OP, buf, end_buf - buf);
- cff_dict_set_operands (font->top_dict, FDSELECT_OP, buf, end_buf - buf);
- cff_dict_set_operands (font->top_dict, FDARRAY_OP, buf, end_buf - buf);
- cff_dict_set_operands (font->top_dict, CHARSET_OP, buf, end_buf - buf);
- cairo_cff_font_set_ros_strings (font);
-
- /* Create CID FD dictionary */
- cairo_cff_font_create_cid_fontdict (font);
-
- /* Create charstrings */
- for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) {
- charstring = _cairo_array_index(&type2_subset->charstrings, i);
-
- status = cff_index_append (&font->charstrings_subset_index,
- _cairo_array_index (charstring, 0),
- _cairo_array_num_elements (charstring));
-
- if (status)
- return status;
- }
-
- status = cairo_cff_font_write_subset (font);
- if (status)
- return status;
-
- *data = _cairo_array_index (&font->output, 0);
- *length = _cairo_array_num_elements (&font->output);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset,
- const char *subset_name,
- cairo_scaled_font_subset_t *font_subset)
-{
- cairo_cff_font_t *font = NULL; /* squelch bogus compiler warning */
- cairo_status_t status;
- const char *data = NULL; /* squelch bogus compiler warning */
- unsigned long length = 0; /* squelch bogus compiler warning */
- unsigned int i;
- cairo_type2_charstrings_t type2_subset;
-
- status = _cairo_cff_font_fallback_create (font_subset, &font, subset_name);
- if (status)
- return status;
-
- status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
- if (status)
- goto fail1;
-
- status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
- if (status)
- goto fail1;
-
- cff_subset->base_font = strdup (font->font_name);
- if (cff_subset->base_font == NULL)
- goto fail1;
-
- cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
- if (cff_subset->widths == NULL)
- goto fail2;
- for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
- cff_subset->widths[i] = type2_subset.widths[i];
-
- cff_subset->x_min = type2_subset.x_min;
- cff_subset->y_min = type2_subset.y_min;
- cff_subset->x_max = type2_subset.x_max;
- cff_subset->y_max = type2_subset.y_max;
- cff_subset->ascent = type2_subset.y_max;
- cff_subset->descent = type2_subset.y_min;
-
- _cairo_type2_charstrings_fini (&type2_subset);
-
- cff_subset->data = malloc (length);
- if (cff_subset->data == NULL)
- goto fail3;
-
- memcpy (cff_subset->data, data, length);
- cff_subset->data_length = length;
- cff_subset->data_length = length;
-
- cairo_cff_font_destroy (font);
-
- return CAIRO_STATUS_SUCCESS;
-
- fail3:
- free (cff_subset->widths);
- fail2:
- free (cff_subset->base_font);
- fail1:
- cairo_cff_font_destroy (font);
-
- return status;
-}
-
-void
-_cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
-{
- free (subset->base_font);
- free (subset->widths);
- free (subset->data);
-}
--- a/gfx/cairo/cairo/src/cairo-clip-private.h
+++ b/gfx/cairo/cairo/src/cairo-clip-private.h
@@ -33,17 +33,17 @@
* Kristian Høgsberg <krh@redhat.com>
*/
#ifndef CAIRO_CLIP_PRIVATE_H
#define CAIRO_CLIP_PRIVATE_H
#include "cairo-path-fixed-private.h"
-extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
+extern cairo_private const cairo_rectangle_list_t _cairo_rectangles_nil;
struct _cairo_clip_path {
unsigned int ref_count;
cairo_path_fixed_t path;
cairo_fill_rule_t fill_rule;
double tolerance;
cairo_antialias_t antialias;
cairo_clip_path_t *prev;
@@ -67,37 +67,39 @@ struct _cairo_clip {
/*
* Surface clip serial number to store
* in the surface when this clip is set
*/
unsigned int serial;
/*
* A clip region that can be placed in the surface
*/
- pixman_region16_t region;
- cairo_bool_t has_region;
+ pixman_region16_t *region;
/*
* If the surface supports path clipping, we store the list of
* clipping paths that has been set here as a linked list.
*/
cairo_clip_path_t *path;
};
cairo_private void
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target);
-cairo_private cairo_status_t
+cairo_private void
+_cairo_clip_fini (cairo_clip_t *clip);
+
+cairo_private void
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
-cairo_private cairo_status_t
+cairo_private void
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
cairo_clip_t *other,
cairo_surface_t *target);
-cairo_private void
+cairo_private cairo_status_t
_cairo_clip_reset (cairo_clip_t *clip);
cairo_private cairo_status_t
_cairo_clip_clip (cairo_clip_t *clip,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias,
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -56,72 +56,74 @@ void
clip->surface = NULL;
clip->surface_rect.x = 0;
clip->surface_rect.y = 0;
clip->surface_rect.width = 0;
clip->surface_rect.height = 0;
clip->serial = 0;
- pixman_region_init (&clip->region);
- clip->has_region = FALSE;
+ clip->region = NULL;
clip->path = NULL;
}
-cairo_status_t
+void
+_cairo_clip_fini (cairo_clip_t *clip)
+{
+ cairo_surface_destroy (clip->surface);
+ clip->surface = NULL;
+
+ clip->serial = 0;
+
+ if (clip->region)
+ pixman_region_destroy (clip->region);
+ clip->region = NULL;
+
+ _cairo_clip_path_destroy (clip->path);
+ clip->path = NULL;
+}
+
+void
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
{
clip->mode = other->mode;
clip->surface = cairo_surface_reference (other->surface);
clip->surface_rect = other->surface_rect;
clip->serial = other->serial;
- pixman_region_init (&clip->region);
-
- if (other->has_region) {
- if (pixman_region_copy (&clip->region, &other->region) !=
- PIXMAN_REGION_STATUS_SUCCESS) {
- pixman_region_fini (&clip->region);
- cairo_surface_destroy (clip->surface);
- return CAIRO_STATUS_NO_MEMORY;
- }
- clip->has_region = TRUE;
+ if (other->region == NULL) {
+ clip->region = other->region;
} else {
- clip->has_region = FALSE;
+ clip->region = pixman_region_create ();
+ pixman_region_copy (clip->region, other->region);
}
clip->path = _cairo_clip_path_reference (other->path);
-
- return CAIRO_STATUS_SUCCESS;
}
-void
+cairo_status_t
_cairo_clip_reset (cairo_clip_t *clip)
{
/* destroy any existing clip-region artifacts */
cairo_surface_destroy (clip->surface);
clip->surface = NULL;
clip->serial = 0;
- if (clip->has_region) {
- /* pixman_region_fini just releases the resources used but
- * doesn't bother with leaving the region in a valid state.
- * So pixman_region_init has to be called afterwards. */
- pixman_region_fini (&clip->region);
- pixman_region_init (&clip->region);
-
- clip->has_region = FALSE;
- }
+ if (clip->region)
+ pixman_region_destroy (clip->region);
+ clip->region = NULL;
_cairo_clip_path_destroy (clip->path);
clip->path = NULL;
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
cairo_rectangle_int16_t *rectangle)
{
while (clip_path) {
cairo_status_t status;
@@ -163,79 +165,78 @@ cairo_status_t
cairo_status_t status;
status = _cairo_clip_path_intersect_to_rectangle (clip->path,
rectangle);
if (status)
return status;
}
- if (clip->has_region) {
+ if (clip->region) {
+ pixman_region16_t *intersection;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- pixman_region16_t intersection;
+ pixman_region_status_t pixman_status;
- pixman_region_init_rect (&intersection,
- rectangle->x, rectangle->y,
- rectangle->width, rectangle->height);
+ intersection = _cairo_region_create_from_rectangle (rectangle);
+ if (intersection == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
- if (PIXMAN_REGION_STATUS_SUCCESS !=
- pixman_region_intersect (&intersection, &clip->region,
- &intersection)) {
+ pixman_status = pixman_region_intersect (intersection,
+ clip->region,
+ intersection);
+ if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS)
+ _cairo_region_extents_rectangle (intersection, rectangle);
+ else
status = CAIRO_STATUS_NO_MEMORY;
- } else {
- _cairo_region_extents_rectangle (&intersection, rectangle);
- }
+
+ pixman_region_destroy (intersection);
- pixman_region_fini (&intersection);
-
- if (status)
- return status;
+ if (status)
+ return status;
}
if (clip->surface)
_cairo_rectangle_intersect (rectangle, &clip->surface_rect);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
pixman_region16_t *region)
{
- pixman_region_status_t pixman_status;
-
if (!clip)
return CAIRO_STATUS_SUCCESS;
if (clip->path) {
/* Intersect clip path into region. */
}
- if (clip->has_region) {
- pixman_status = pixman_region_intersect (region, &clip->region, region);
- if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
- return CAIRO_STATUS_NO_MEMORY;
- }
+ if (clip->region)
+ pixman_region_intersect (region, clip->region, region);
if (clip->surface) {
+ pixman_region16_t *clip_rect;
+ pixman_region_status_t pixman_status;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- pixman_region16_t clip_rect;
- pixman_region_init_rect (&clip_rect,
- clip->surface_rect.x, clip->surface_rect.y,
- clip->surface_rect.width, clip->surface_rect.height);
+ clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
+ if (clip_rect == NULL)
+ return CAIRO_STATUS_NO_MEMORY;
- if (PIXMAN_REGION_STATUS_SUCCESS !=
- pixman_region_intersect (region, &clip_rect, region))
+ pixman_status = pixman_region_intersect (region,
+ clip_rect,
+ region);
+ if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
status = CAIRO_STATUS_NO_MEMORY;
- pixman_region_fini (&clip_rect);
+ pixman_region_destroy (clip_rect);
- if (status)
- return status;
+ if (status)
+ return status;
}
return CAIRO_STATUS_SUCCESS;
}
/* Combines the region of clip->surface given by extents in
* device backend coordinates into the given temporary surface,
* which has its origin at dst_x, dst_y in backend coordinates
@@ -323,57 +324,52 @@ static void
if (clip_path->ref_count)
return;
_cairo_path_fixed_fini (&clip_path->path);
_cairo_clip_path_destroy (clip_path->prev);
free (clip_path);
}
-static cairo_int_status_t
+static cairo_status_t
_cairo_clip_intersect_region (cairo_clip_t *clip,
cairo_traps_t *traps,
cairo_surface_t *target)
{
- pixman_region16_t region;
- cairo_int_status_t status;
+ pixman_region16_t *region;
+ cairo_status_t status;
if (clip->mode != CAIRO_CLIP_MODE_REGION)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_traps_extract_region (traps, ®ion);
-
if (status)
return status;
- status = CAIRO_STATUS_SUCCESS;
+ if (region == NULL)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
- if (!clip->has_region) {
- if (pixman_region_copy (&clip->region, ®ion) ==
- PIXMAN_REGION_STATUS_SUCCESS)
- clip->has_region = TRUE;
- else
- status = CAIRO_STATUS_NO_MEMORY;
+ status = CAIRO_STATUS_SUCCESS;
+ if (clip->region == NULL) {
+ clip->region = region;
} else {
- pixman_region16_t intersection;
- pixman_region_init (&intersection);
+ pixman_region16_t *intersection = pixman_region_create();
- if (PIXMAN_REGION_STATUS_SUCCESS !=
- pixman_region_intersect (&intersection,
- &clip->region,
- ®ion) ||
- PIXMAN_REGION_STATUS_SUCCESS !=
- pixman_region_copy (&clip->region, &intersection))
+ if (pixman_region_intersect (intersection,
+ clip->region, region)
+ == PIXMAN_REGION_STATUS_SUCCESS) {
+ pixman_region_destroy (clip->region);
+ clip->region = intersection;
+ } else {
status = CAIRO_STATUS_NO_MEMORY;
-
- pixman_region_fini (&intersection);
+ }
+ pixman_region_destroy (region);
}
clip->serial = _cairo_surface_allocate_clip_serial (target);
- pixman_region_fini (®ion);
return status;
}
static cairo_status_t
_cairo_clip_intersect_mask (cairo_clip_t *clip,
cairo_traps_t *traps,
cairo_antialias_t antialias,
@@ -401,26 +397,24 @@ static cairo_status_t
status = _cairo_surface_get_extents (target, &target_rect);
if (!status)
_cairo_rectangle_intersect (&surface_rect, &target_rect);
surface = _cairo_surface_create_similar_solid (target,
CAIRO_CONTENT_ALPHA,
surface_rect.width,
surface_rect.height,
- CAIRO_COLOR_WHITE,
- NULL);
+ CAIRO_COLOR_WHITE);
if (surface->status)
return CAIRO_STATUS_NO_MEMORY;
/* Render the new clipping path into the new mask surface. */
_cairo_traps_translate (traps, -surface_rect.x, -surface_rect.y);
- _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
- CAIRO_CONTENT_COLOR);
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE);
status = _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_IN,
&pattern.base,
surface,
antialias,
0, 0,
0, 0,
surface_rect.width,
@@ -510,18 +504,18 @@ cairo_status_t
return status;
}
void
_cairo_clip_translate (cairo_clip_t *clip,
cairo_fixed_t tx,
cairo_fixed_t ty)
{
- if (clip->has_region) {
- pixman_region_translate (&clip->region,
+ if (clip->region) {
+ pixman_region_translate (clip->region,
_cairo_fixed_integer_part (tx),
_cairo_fixed_integer_part (ty));
}
if (clip->surface) {
clip->surface_rect.x += _cairo_fixed_integer_part (tx);
clip->surface_rect.y += _cairo_fixed_integer_part (ty);
}
@@ -550,60 +544,46 @@ static void
_cairo_clip_intersect_path (clip,
&clip_path->path,
clip_path->fill_rule,
clip_path->tolerance,
clip_path->antialias);
}
-cairo_status_t
+void
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
cairo_clip_t *other,
cairo_surface_t *target)
{
_cairo_clip_init (clip, target);
if (other->mode != clip->mode) {
/* We should reapply the original clip path in this case, and let
* whatever the right handling is happen */
} else {
- if (other->has_region) {
- if (pixman_region_copy (&clip->region, &other->region) !=
- PIXMAN_REGION_STATUS_SUCCESS)
- goto BAIL;
- clip->has_region = TRUE;
+ if (other->region) {
+ clip->region = pixman_region_create ();
+ pixman_region_copy (clip->region, other->region);
}
if (other->surface) {
- if (_cairo_surface_clone_similar (target, other->surface,
+ _cairo_surface_clone_similar (target, other->surface,
other->surface_rect.x,
other->surface_rect.y,
other->surface_rect.width,
other->surface_rect.height,
- &clip->surface) !=
- CAIRO_STATUS_SUCCESS)
- goto BAIL;
+ &clip->surface);
clip->surface_rect = other->surface_rect;
}
if (other->path) {
_cairo_clip_path_reapply_clip_path (clip, other->path);
}
}
-
- return CAIRO_STATUS_SUCCESS;
-
-BAIL:
- if (clip->has_region)
- pixman_region_fini (&clip->region);
- if (clip->surface)
- cairo_surface_destroy (clip->surface);
-
- return CAIRO_STATUS_NO_MEMORY;
}
const cairo_rectangle_list_t _cairo_rectangles_nil =
{ CAIRO_STATUS_NO_MEMORY, NULL, 0 };
static const cairo_rectangle_list_t _cairo_rectangles_not_representable =
{ CAIRO_STATUS_CLIP_NOT_REPRESENTABLE, NULL, 0 };
static cairo_bool_t
@@ -628,46 +608,42 @@ cairo_private cairo_rectangle_list_t*
{
cairo_rectangle_list_t *list;
cairo_rectangle_t *rectangles;
int n_boxes;
if (clip->path || clip->surface)
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
- n_boxes = clip->has_region ? pixman_region_num_rects (&clip->region) : 1;
+ 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->has_region) {
+ if (clip->region) {
pixman_box16_t *boxes;
int i;
- boxes = pixman_region_rects (&clip->region);
+ boxes = pixman_region_rects (clip->region);
for (i = 0; i < n_boxes; ++i) {
if (!_cairo_clip_rect_to_user(gstate, boxes[i].x1, boxes[i].y1,
boxes[i].x2 - boxes[i].x1,
boxes[i].y2 - boxes[i].y1,
&rectangles[i])) {
free (rectangles);
return (cairo_rectangle_list_t*)
&_cairo_rectangles_not_representable;
}
}
} else {
cairo_rectangle_int16_t extents;
- if (_cairo_surface_get_extents (_cairo_gstate_get_target (gstate),
- &extents) != CAIRO_STATUS_SUCCESS) {
- free (rectangles);
- return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
- }
- if (! _cairo_clip_rect_to_user(gstate, extents.x, extents.y,
- extents.width, extents.height,
- rectangles)) {
+ _cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents);
+ if (!_cairo_clip_rect_to_user(gstate, extents.x, extents.y,
+ extents.width, extents.height,
+ rectangles)) {
free (rectangles);
return (cairo_rectangle_list_t*)
&_cairo_rectangles_not_representable;
}
}
list = malloc (sizeof (cairo_rectangle_list_t));
if (list == NULL) {
--- a/gfx/cairo/cairo/src/cairo-color.c
+++ b/gfx/cairo/cairo/src/cairo-color.c
@@ -155,18 +155,8 @@ void
double *blue,
double *alpha)
{
*red = color->red * color->alpha;
*green = color->green * color->alpha;
*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;
-}
--- a/gfx/cairo/cairo/src/cairo-debug.c
+++ b/gfx/cairo/cairo/src/cairo-debug.c
@@ -54,16 +54,18 @@
* active cairo objects remaining, (ie. the appropriate destroy
* functions have been called as necessary). If there are active cairo
* objects, this call is likely to cause a crash, (eg. an assertion
* failure due to a hash table being destroyed when non-empty).
**/
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 ();
}
--- a/gfx/cairo/cairo/src/cairo-deflate-stream.c
+++ b/gfx/cairo/cairo/src/cairo-deflate-stream.c
@@ -114,31 +114,29 @@ static cairo_status_t
cairo_output_stream_t *
_cairo_deflate_stream_create (cairo_output_stream_t *output)
{
cairo_deflate_stream_t *stream;
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,
_cairo_deflate_stream_close);
stream->output = output;
stream->zlib_stream.zalloc = Z_NULL;
stream->zlib_stream.zfree = Z_NULL;
stream->zlib_stream.opaque = Z_NULL;
- if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK) {
- free (stream);
- return (cairo_output_stream_t *) &_cairo_output_stream_nil;
- }
+ if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
+ return (cairo_output_stream_t *) &cairo_output_stream_nil;
stream->zlib_stream.next_in = stream->input_buf;
stream->zlib_stream.avail_in = 0;
stream->zlib_stream.next_out = stream->output_buf;
stream->zlib_stream.avail_out = BUFFER_SIZE;
return &stream->base;
}
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -30,27 +30,31 @@
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Michael Emmel <mike.emmel@gmail.com>
* Claudio Ciccani <klan@users.sf.net>
*/
-#include "cairoint.h"
-
-#include "cairo-directfb.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <assert.h>
#include <directfb.h>
#include <direct/types.h>
#include <direct/debug.h>
#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).
*/
#define DFB_RECTANGLES 0
/*
* Composite works fine.
@@ -328,17 +332,17 @@ static cairo_status_t
{
void *data;
int pitch;
IDirectFBSurface *buffer;
DFBRectangle source_rect;
cairo_format_t cairo_format;
cairo_format = surface->format;
- if (surface->format == (cairo_format_t) -1) {
+ if (surface->format == -1) {
if( intrest_rec ) {
source_rect.x = intrest_rec->x;
source_rect.y = intrest_rec->y;
source_rect.w = intrest_rec->width;
source_rect.h = intrest_rec->height;
}else {
source_rect.x=0;
source_rect.y=0;
@@ -1506,27 +1510,16 @@ static cairo_int_status_t
dst->dfbsurface->BatchBlit (dst->dfbsurface,
cache->dfbsurface, rects, points, num));
return CAIRO_STATUS_SUCCESS;
}
#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*/
_cairo_directfb_surface_finish, /*finish*/
_cairo_directfb_surface_acquire_source_image,/*acquire_source_image*/
_cairo_directfb_surface_release_source_image,/*release_source_image*/
_cairo_directfb_surface_acquire_dest_image,/*acquire_dest_image*/
_cairo_directfb_surface_release_dest_image,/*release_dest_image*/
@@ -1566,19 +1559,17 @@ static cairo_surface_backend_t cairo_dir
NULL, /* mask */
NULL, /* stroke */
NULL, /* fill */
#if DFB_SHOW_GLYPHS
_cairo_directfb_surface_show_glyphs,/*show_glyphs*/
#else
NULL, /* show_glyphs */
#endif
- NULL, /* snapshot */
- _cairo_directfb_is_similar,
- NULL /* reset */
+ NULL /* snapshot */
};
static void
cairo_directfb_surface_backend_init (IDirectFB *dfb)
{
DFBGraphicsDeviceDescription dsc;
static int done = 0;
--- a/gfx/cairo/cairo/src/cairo-directfb.h
+++ b/gfx/cairo/cairo/src/cairo-directfb.h
@@ -36,18 +36,16 @@
#ifndef CAIRO_DIRECTFB_H
#define CAIRO_DIRECTFB_H
#include <cairo.h>
#ifdef CAIRO_HAS_DIRECTFB_SURFACE
-#include <directfb.h>
-
CAIRO_BEGIN_DECLS
cairo_public cairo_surface_t *
cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface);
CAIRO_END_DECLS
#else /*CAIRO_HAS_DIRECTFB_SURFACE*/
--- a/gfx/cairo/cairo/src/cairo-features.h.in
+++ b/gfx/cairo/cairo/src/cairo-features.h.in
@@ -48,30 +48,28 @@
#endif
#ifndef cairo_public
# define cairo_public
#endif
#define CAIRO_VERSION_MAJOR 1
#define CAIRO_VERSION_MINOR 4
-#define CAIRO_VERSION_MICRO 8
+#define CAIRO_VERSION_MICRO 2
-#define CAIRO_VERSION_STRING "1.4.8"
+#define CAIRO_VERSION_STRING "1.4.2"
@PS_SURFACE_FEATURE@
@PDF_SURFACE_FEATURE@
@SVG_SURFACE_FEATURE@
@XLIB_SURFACE_FEATURE@
-@XLIB_XRENDER_SURFACE_FEATURE@
-
@QUARTZ_SURFACE_FEATURE@
@XCB_SURFACE_FEATURE@
@WIN32_SURFACE_FEATURE@
@OS2_SURFACE_FEATURE@
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-font-face.c
+++ /dev/null
@@ -1,519 +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)
-{
- CAIRO_MUTEX_INITIALIZE ();
-
- font_face->status = CAIRO_STATUS_SUCCESS;
- font_face->ref_count = 1;
- font_face->backend = backend;
-
- _cairo_user_data_array_init (&font_face->user_data);
-}
-
-/**
- * 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;
- cairo_status_t status;
-
- status = cairo_font_options_status ((cairo_font_options_t *) options);
- if (status)
- return status;
-
- return backend->create_toy (font_face,
- font_matrix, ctm, options, scaled_font);
-}
-
-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);
-}
--- a/gfx/cairo/cairo/src/cairo-font-options.c
+++ b/gfx/cairo/cairo/src/cairo-font-options.c
@@ -31,33 +31,33 @@
* California.
*
* Contributor(s):
* Owen Taylor <otaylor@redhat.com>
*/
#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,
CAIRO_HINT_METRICS_DEFAULT
};
/**
* _cairo_font_options_init_default:
* @options: a #cairo_font_options_t
*
* Initializes all fields of the font options object to default values.
**/
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;
options->subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
options->hint_style = CAIRO_HINT_STYLE_DEFAULT;
options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT;
}
@@ -84,17 +84,17 @@ void
* You can check for this with cairo_font_options_status().
**/
cairo_font_options_t *
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);
return options;
}
slim_hidden_def (cairo_font_options_create);
/**
@@ -108,41 +108,37 @@ slim_hidden_def (cairo_font_options_crea
* cairo_font_options_destroy(). This function always returns a
* valid pointer; if memory cannot be allocated, then a special
* error object is returned where all operations on the object do nothing.
* You can check for this with cairo_font_options_status().
**/
cairo_font_options_t *
cairo_font_options_copy (const cairo_font_options_t *original)
{
- cairo_font_options_t *options;
+ cairo_font_options_t *options = malloc (sizeof (cairo_font_options_t));
- if (original == &_cairo_font_options_nil)
- return (cairo_font_options_t *)&_cairo_font_options_nil;
-
- options = malloc (sizeof (cairo_font_options_t));
if (!options)
- return (cairo_font_options_t *)&_cairo_font_options_nil;
+ return (cairo_font_options_t *)&cairo_font_options_nil;
_cairo_font_options_init_copy (options, original);
return options;
}
/**
* cairo_font_options_destroy:
* @options: a #cairo_font_options_t
*
* Destroys a #cairo_font_options_t object created with with
* cairo_font_options_create() or cairo_font_options_copy().
**/
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);
}
slim_hidden_def (cairo_font_options_destroy);
/**
* cairo_font_options_status:
@@ -151,38 +147,37 @@ slim_hidden_def (cairo_font_options_dest
* Checks whether an error has previously occurred for this
* font options object
*
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
**/
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:
* @options: a #cairo_font_options_t
* @other: another #cairo_font_options_t
*
* Merges non-default options from @other into @options, replacing
* existing values. This operation can be thought of as somewhat
* similar to compositing @other onto @options with the operation
* of %CAIRO_OPERATION_OVER.
**/
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)
options->antialias = other->antialias;
if (other->subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
options->subpixel_order = other->subpixel_order;
if (other->hint_style != CAIRO_HINT_STYLE_DEFAULT)
options->hint_style = other->hint_style;
@@ -240,17 +235,17 @@ slim_hidden_def (cairo_font_options_hash
*
* Sets the antialiasing mode for the font options object. This
* specifies the type of antialiasing to do when rendering text.
**/
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;
}
slim_hidden_def (cairo_font_options_set_antialias);
/**
* cairo_font_options_get_antialias:
@@ -276,17 +271,17 @@ cairo_font_options_get_antialias (const
* the display device when rendering with an antialiasing mode of
* %CAIRO_ANTIALIAS_SUBPIXEL. See the documentation for
* #cairo_subpixel_order_t for full details.
**/
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;
}
slim_hidden_def (cairo_font_options_set_subpixel_order);
/**
* cairo_font_options_get_subpixel_order:
@@ -312,17 +307,17 @@ cairo_font_options_get_subpixel_order (c
* This controls whether to fit font outlines to the pixel grid,
* and if so, whether to optimize for fidelity or contrast.
* See the documentation for #cairo_hint_style_t for full details.
**/
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;
}
slim_hidden_def (cairo_font_options_set_hint_style);
/**
* cairo_font_options_get_hint_style:
@@ -348,17 +343,17 @@ cairo_font_options_get_hint_style (const
* controls whether metrics are quantized to integer values in
* device units.
* See the documentation for #cairo_hint_metrics_t for full details.
**/
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;
}
slim_hidden_def (cairo_font_options_set_hint_metrics);
/**
* cairo_font_options_get_hint_metrics:
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-font.c
@@ -0,0 +1,516 @@
+/* -*- 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);
+}
--- a/gfx/cairo/cairo/src/cairo-freelist-private.h
+++ b/gfx/cairo/cairo/src/cairo-freelist-private.h
@@ -21,16 +21,18 @@
*/
#ifndef CAIRO_FREELIST_H
#define CAIRO_FREELIST_H
#include "cairoint.h"
#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;
struct _cairo_freelist_node {
cairo_freelist_node_t *next;
};
struct _cairo_freelist {
--- a/gfx/cairo/cairo/src/cairo-freelist.c
+++ b/gfx/cairo/cairo/src/cairo-freelist.c
@@ -14,19 +14,18 @@
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
-
-#include "cairoint.h"
-
+#include <stdlib.h>
+#include <string.h>
#include "cairo-freelist-private.h"
void
_cairo_freelist_init (cairo_freelist_t *freelist, unsigned nodesize)
{
memset (freelist, 0, sizeof(cairo_freelist_t));
freelist->nodesize = nodesize;
}
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -32,22 +32,20 @@
*
* Contributor(s):
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
* Keith Packard <keithp@keithp.com>
* Carl Worth <cworth@cworth.org>
*/
-#include "cairoint.h"
+#include <float.h>
#include "cairo-ft-private.h"
-#include <float.h>
-
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_IMAGE_H
#include FT_TRUETYPE_TABLES_H
@@ -59,19 +57,21 @@
#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
/* This is the max number of FT_face objects we keep open at once
*/
#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
*/
typedef struct _cairo_ft_font_transform {
double x_scale, y_scale;
@@ -151,16 +151,18 @@ static const cairo_unscaled_font_backend
typedef struct _cairo_ft_unscaled_font_map {
cairo_hash_table_t *hash_table;
FT_Library ft_library;
int num_open_faces;
} cairo_ft_unscaled_font_map_t;
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)
{
if (unscaled->face) {
FT_Done_Face (unscaled->face);
unscaled->face = NULL;
unscaled->have_scale = FALSE;
@@ -254,17 +256,16 @@ static cairo_ft_unscaled_font_map_t *
CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
if (cairo_ft_unscaled_font_map == NULL)
{
_cairo_ft_unscaled_font_map_create ();
if (cairo_ft_unscaled_font_map == NULL) {
CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
}
return cairo_ft_unscaled_font_map;
}
static void
@@ -327,26 +328,24 @@ static cairo_status_t
unscaled->id = 0;
} else {
char *filename_copy;
unscaled->from_face = FALSE;
unscaled->face = NULL;
filename_copy = strdup (filename);
- if (filename_copy == NULL) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (filename_copy == NULL)
return CAIRO_STATUS_NO_MEMORY;
- }
_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);
}
unscaled->have_scale = FALSE;
- CAIRO_MUTEX_INIT (unscaled->mutex);
+ CAIRO_MUTEX_INIT (&unscaled->mutex);
unscaled->lock_count = 0;
unscaled->faces = NULL;
return CAIRO_STATUS_SUCCESS;
}
cairo_bool_t
@@ -371,17 +370,17 @@ static void
{
assert (unscaled->face == NULL);
if (unscaled->filename) {
free (unscaled->filename);
unscaled->filename = NULL;
}
- CAIRO_MUTEX_FINI (unscaled->mutex);
+ CAIRO_MUTEX_FINI (&unscaled->mutex);
}
static int
_cairo_ft_unscaled_font_keys_equal (const void *key_a,
const void *key_b)
{
const cairo_ft_unscaled_font_t *unscaled_a = key_a;
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
@@ -415,18 +414,18 @@ static cairo_ft_unscaled_font_t *
goto UNWIND;
_cairo_ft_unscaled_font_init_key (&key, filename, id);
/* Return existing unscaled font if it exists in the hash table. */
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;
}
/* Otherwise create it and insert into hash table. */
unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
if (unscaled == NULL)
goto UNWIND_FONT_MAP_LOCK;
@@ -552,17 +551,16 @@ FT_Face
_cairo_ft_unscaled_font_map_unlock ();
if (FT_New_Face (font_map->ft_library,
unscaled->filename,
unscaled->id,
&face) != FT_Err_Ok)
{
CAIRO_MUTEX_UNLOCK (unscaled->mutex);
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
unscaled->face = face;
font_map->num_open_faces++;
return face;
@@ -611,32 +609,32 @@ static void
sf->shape[0][0] = sf->shape[1][1] = 1.0;
sf->shape[0][1] = sf->shape[1][0] = 0.0;
}
}
/* Temporarily scales an unscaled font to the give scale. We catch
* scaling to the same size, since changing a FT_Face is expensive.
*/
-static cairo_status_t
+static void
_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
cairo_matrix_t *scale)
{
cairo_ft_font_transform_t sf;
FT_Matrix mat;
FT_Error error;
assert (unscaled->face != NULL);
if (unscaled->have_scale &&
scale->xx == unscaled->current_scale.xx &&
scale->yx == unscaled->current_scale.yx &&
scale->xy == unscaled->current_scale.xy &&
scale->yy == unscaled->current_scale.yy)
- return CAIRO_STATUS_SUCCESS;
+ return;
unscaled->have_scale = TRUE;
unscaled->current_scale = *scale;
_compute_transform (&sf, scale);
unscaled->x_scale = sf.x_scale;
unscaled->y_scale = sf.y_scale;
@@ -655,33 +653,37 @@ static cairo_status_t
cairo_matrix_init (&unscaled->current_shape,
sf.shape[0][0], sf.shape[0][1],
sf.shape[1][0], sf.shape[1][1],
0.0, 0.0);
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);
- if (error) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
+#endif /* MOZCAIRO */
+ assert (error == 0);
} else {
double min_distance = DBL_MAX;
int i;
int best_i = 0;
for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
#if HAVE_FT_BITMAP_SIZE_Y_PPEM
double size = unscaled->face->available_sizes[i].y_ppem / 64.;
@@ -700,23 +702,18 @@ static cairo_status_t
unscaled->face->available_sizes[best_i].x_ppem,
unscaled->face->available_sizes[best_i].y_ppem,
0, 0);
if (error)
#endif
error = FT_Set_Pixel_Sizes (unscaled->face,
unscaled->face->available_sizes[best_i].width,
unscaled->face->available_sizes[best_i].height);
- if (error) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
+ assert (error == 0);
}
-
- return CAIRO_STATUS_SUCCESS;
}
/* Empirically-derived subpixel filtering values thanks to Keith
* Packard and libXft. */
static const int filters[3][3] = {
/* red */
#if 0
{ 65538*4/7,65538*2/7,65538*1/7 },
@@ -751,20 +748,18 @@ static cairo_status_t
switch (bitmap->pixel_mode) {
case FT_PIXEL_MODE_MONO:
stride = (((width + 31) & ~31) >> 3);
if (own_buffer) {
data = bitmap->buffer;
assert (stride == bitmap->pitch);
} else {
data = malloc (stride * height);
- if (!data) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (!data)
return CAIRO_STATUS_NO_MEMORY;
- }
if (stride == bitmap->pitch) {
memcpy (data, bitmap->buffer, stride * height);
} else {
int i;
unsigned char *source, *dest;
source = bitmap->buffer;
@@ -801,20 +796,18 @@ static cairo_status_t
case CAIRO_ANTIALIAS_GRAY:
case CAIRO_ANTIALIAS_NONE:
default:
stride = bitmap->pitch;
if (own_buffer) {
data = bitmap->buffer;
} else {
data = malloc (stride * height);
- if (!data) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (!data)
return CAIRO_STATUS_NO_MEMORY;
- }
memcpy (data, bitmap->buffer, stride * height);
}
format = CAIRO_FORMAT_A8;
break;
case CAIRO_ANTIALIAS_SUBPIXEL: {
int x, y;
unsigned char *in_line, *out_line, *in;
unsigned int *out;
@@ -843,22 +836,16 @@ static cairo_status_t
}
/*
* Filter the glyph to soften the color fringes
*/
width_rgba = width;
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) {
case CAIRO_SUBPIXEL_ORDER_VRGB:
os = stride;
case CAIRO_SUBPIXEL_ORDER_DEFAULT:
case CAIRO_SUBPIXEL_ORDER_RGB:
default:
@@ -913,19 +900,16 @@ static cairo_status_t
break;
}
}
break;
case FT_PIXEL_MODE_GRAY2:
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;
}
*surface = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (data,
format,
width, height, stride);
if ((*surface)->base.status) {
@@ -1046,25 +1030,23 @@ static cairo_status_t
}
bitmap.pitch = stride;
bitmap.width = width * hmul;
bitmap.rows = height * vmul;
bitmap.buffer = calloc (1, stride * bitmap.rows);
if (bitmap.buffer == NULL) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
free (bitmap.buffer);
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
if (status)
return status;
}
@@ -1092,20 +1074,18 @@ static cairo_status_t
/* According to the FreeType docs, glyphslot->format could be
* something other than FT_GLYPH_FORMAT_OUTLINE or
* FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
* the opportunity to convert such to
* bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
* we avoid the FT_LOAD_NO_RECURSE flag.
*/
error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
- if (error) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (error)
return CAIRO_STATUS_NO_MEMORY;
- }
status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
if (status)
return status;
/*
* Note: the font's coordinate system is upside down from ours, so the
* Y coordinate of the control box needs to be negated.
@@ -1193,43 +1173,34 @@ static cairo_status_t
/* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
width = (width + 3) & ~3;
image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
if (image->status)
return CAIRO_STATUS_NO_MEMORY;
/* Initialize it to empty
*/
- status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
- CAIRO_COLOR_TRANSPARENT,
- 0, 0,
- width, height);
- if (status) {
- cairo_surface_destroy (image);
- return status;
- }
+ _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
+ CAIRO_COLOR_TRANSPARENT,
+ 0, 0,
+ width, height);
/* Draw the original bitmap transformed into the new bitmap
*/
_cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
- status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
- &pattern.base, NULL, image,
- 0, 0, 0, 0, 0, 0,
- width,
- height);
+ _cairo_surface_composite (CAIRO_OPERATOR_OVER,
+ &pattern.base, NULL, image,
+ 0, 0, 0, 0, 0, 0,
+ width,
+ height);
_cairo_pattern_fini (&pattern.base);
- if (status) {
- cairo_surface_destroy (image);
- return status;
- }
-
/* Now update the cache entry for the new bitmap, recomputing
* the origin based on the final transform.
*/
origin_x = - origin_x;
origin_y = - origin_y;
cairo_matrix_transform_point (&original_to_transformed,
&origin_x, &origin_y);
@@ -1469,58 +1440,43 @@ static cairo_scaled_font_t *
const cairo_matrix_t *ctm,
const cairo_font_options_t *options,
cairo_ft_options_t ft_options)
{
cairo_ft_scaled_font_t *scaled_font = NULL;
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)
return NULL;
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;
}
_cairo_unscaled_font_reference (&unscaled->base);
scaled_font->unscaled = unscaled;
if (options->hint_metrics != CAIRO_HINT_METRICS_OFF)
ft_options.extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS;
_cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
_cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
- status = _cairo_scaled_font_init (&scaled_font->base,
- font_face,
- font_matrix, ctm, options,
- &cairo_ft_scaled_font_backend);
- if (status) {
- free (scaled_font);
- _cairo_unscaled_font_destroy (&unscaled->base);
- _cairo_ft_unscaled_font_unlock_face (unscaled);
- return NULL;
- }
+ _cairo_scaled_font_init (&scaled_font->base,
+ font_face,
+ font_matrix, ctm, options,
+ &cairo_ft_scaled_font_backend);
- status = _cairo_ft_unscaled_font_set_scale (unscaled,
- &scaled_font->base.scale);
- if (status) {
- free (scaled_font);
- _cairo_unscaled_font_destroy (&unscaled->base);
- _cairo_ft_unscaled_font_unlock_face (unscaled);
- return NULL;
- }
-
+ _cairo_ft_unscaled_font_set_scale (unscaled,
+ &scaled_font->base.scale);
metrics = &face->size->metrics;
/*
* Get to unscaled metrics so that the upper level can get back to
* user space
*/
if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
@@ -1588,20 +1544,18 @@ static cairo_status_t
int fcslant;
int fcweight;
cairo_matrix_t scale;
cairo_ft_font_transform_t sf;
cairo_ft_options_t ft_options;
unsigned char *family = (unsigned char*) toy_face->family;
pattern = FcPatternCreate ();
- if (!pattern) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (!pattern)
return CAIRO_STATUS_NO_MEMORY;
- }
switch (toy_face->weight)
{
case CAIRO_FONT_WEIGHT_BOLD:
fcweight = FC_WEIGHT_BOLD;
break;
case CAIRO_FONT_WEIGHT_NORMAL:
default:
@@ -1661,17 +1615,16 @@ static cairo_status_t
FREE_PATTERN:
FcPatternDestroy (pattern);
if (new_font) {
*font = new_font;
return CAIRO_STATUS_SUCCESS;
} else {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_NO_MEMORY;
}
}
static void
_cairo_ft_scaled_font_fini (void *abstract_font)
{
cairo_ft_scaled_font_t *scaled_font = abstract_font;
@@ -1686,71 +1639,65 @@ static int
_move_to (FT_Vector *to, void *closure)
{
cairo_path_fixed_t *path = closure;
cairo_fixed_t x, y;
x = _cairo_fixed_from_26_6 (to->x);
y = _cairo_fixed_from_26_6 (to->y);
- if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
- return 1;
- if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
- return 1;
+ _cairo_path_fixed_close_path (path);
+ _cairo_path_fixed_move_to (path, x, y);
return 0;
}
static int
_line_to (FT_Vector *to, void *closure)
{
cairo_path_fixed_t *path = closure;
cairo_fixed_t x, y;
x = _cairo_fixed_from_26_6 (to->x);
y = _cairo_fixed_from_26_6 (to->y);
- if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
- return 1;
+ _cairo_path_fixed_line_to (path, x, y);
return 0;
}
static int
_conic_to (FT_Vector *control, FT_Vector *to, void *closure)
{
cairo_path_fixed_t *path = closure;
cairo_fixed_t x0, y0;
cairo_fixed_t x1, y1;
cairo_fixed_t x2, y2;
cairo_fixed_t x3, y3;
cairo_point_t conic;
- if (_cairo_path_fixed_get_current_point (path, &x0, &y0) !=
- CAIRO_STATUS_SUCCESS)
- return 1;
+ _cairo_path_fixed_get_current_point (path, &x0, &y0);
conic.x = _cairo_fixed_from_26_6 (control->x);
conic.y = _cairo_fixed_from_26_6 (control->y);
x3 = _cairo_fixed_from_26_6 (to->x);
y3 = _cairo_fixed_from_26_6 (to->y);
x1 = x0 + 2.0/3.0 * (conic.x - x0);
y1 = y0 + 2.0/3.0 * (conic.y - y0);
x2 = x3 + 2.0/3.0 * (conic.x - x3);
y2 = y3 + 2.0/3.0 * (conic.y - y3);
- if (_cairo_path_fixed_curve_to (path,
- x1, y1,
- x2, y2,
- x3, y3) != CAIRO_STATUS_SUCCESS)
- return 1;
+ _cairo_path_fixed_curve_to (path,
+ x1, y1,
+ x2, y2,
+ x3, y3);
return 0;
}
static int
_cubic_to (FT_Vector *control1, FT_Vector *control2,
FT_Vector *to, void *closure)
{
@@ -1763,21 +1710,20 @@ static int
y0 = _cairo_fixed_from_26_6 (control1->y);
x1 = _cairo_fixed_from_26_6 (control2->x);
y1 = _cairo_fixed_from_26_6 (control2->y);
x2 = _cairo_fixed_from_26_6 (to->x);
y2 = _cairo_fixed_from_26_6 (to->y);
- if (_cairo_path_fixed_curve_to (path,
- x0, y0,
- x1, y1,
- x2, y2) != CAIRO_STATUS_SUCCESS)
- return 1;
+ _cairo_path_fixed_curve_to (path,
+ x0, y0,
+ x1, y1,
+ x2, y2);
return 0;
}
static cairo_status_t
_decompose_glyph_outline (FT_Face face,
cairo_font_options_t *options,
cairo_path_fixed_t **pathp)
@@ -1792,37 +1738,28 @@ static cairo_status_t
};
static const FT_Matrix invert_y = {
DOUBLE_TO_16_16 (1.0), 0,
0, DOUBLE_TO_16_16 (-1.0),
};
FT_GlyphSlot glyph;
cairo_path_fixed_t *path;
- cairo_status_t status;
path = _cairo_path_fixed_create ();
if (!path)
return CAIRO_STATUS_NO_MEMORY;
glyph = face->glyph;
/* Font glyphs have an inverted Y axis compared to cairo. */
FT_Outline_Transform (&glyph->outline, &invert_y);
- if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
- _cairo_path_fixed_destroy (path);
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
+ FT_Outline_Decompose (&glyph->outline, &outline_funcs, path);
- status = _cairo_path_fixed_close_path (path);
- if (status) {
- _cairo_path_fixed_destroy (path);
- return status;
- }
+ _cairo_path_fixed_close_path (path);
*pathp = path;
return CAIRO_STATUS_SUCCESS;
}
/*
* Translate glyph to match its metrics.
@@ -1856,26 +1793,24 @@ static cairo_int_status_t
cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
FT_GlyphSlot glyph;
FT_Face face;
FT_Error error;
int load_flags = scaled_font->ft_options.load_flags;
FT_Glyph_Metrics *metrics;
double x_factor, y_factor;
cairo_bool_t vertical_layout = FALSE;
- cairo_status_t status;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return CAIRO_STATUS_NO_MEMORY;
- status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
- &scaled_font->base.scale);
- if (status)
- goto FAIL;
+ _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
+ &scaled_font->base.scale);
/* Ignore global advance unconditionally */
load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
(info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)
load_flags |= FT_LOAD_NO_BITMAP;
@@ -2011,22 +1946,19 @@ static cairo_int_status_t
cairo_image_surface_t *surface;
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
status = _render_glyph_outline (face, &scaled_font->ft_options.base,
&surface);
} 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;
_cairo_scaled_glyph_set_surface (scaled_glyph,
&scaled_font->base,
surface);
}
@@ -2040,17 +1972,16 @@ static cairo_int_status_t
*/
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
error = FT_Load_Glyph (face,
_cairo_scaled_glyph_index(scaled_glyph),
load_flags | FT_LOAD_NO_BITMAP);
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
/*
* embolden glyphs if requested
*/
if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
FT_GlyphSlot_Embolden (glyph);
@@ -2250,60 +2181,49 @@ static cairo_status_t
*/
ft_options = font_face->ft_options;
*scaled_font = _cairo_ft_scaled_font_create (font_face->unscaled,
&font_face->base,
font_matrix, ctm,
options, ft_options);
- if (*scaled_font) {
+ if (*scaled_font)
return CAIRO_STATUS_SUCCESS;
- } else {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ else
return CAIRO_STATUS_NO_MEMORY;
- }
}
static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
CAIRO_FONT_TYPE_FT,
_cairo_ft_font_face_destroy,
_cairo_ft_font_face_scaled_font_create
};
static cairo_font_face_t *
_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
cairo_ft_options_t *ft_options)
{
- cairo_ft_font_face_t *font_face, **prev_font_face;
+ cairo_ft_font_face_t *font_face;
/* Looked for an existing matching font face */
- for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
+ for (font_face = unscaled->faces;
font_face;
- prev_font_face = &font_face->next, font_face = font_face->next)
+ font_face = font_face->next)
{
if (font_face->ft_options.load_flags == ft_options->load_flags &&
font_face->ft_options.extra_flags == ft_options->extra_flags &&
cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
- {
- if (! font_face->base.status)
- return cairo_font_face_reference (&font_face->base);
-
- /* The font_face has been left in an error state, abandon it. */
- *prev_font_face = font_face->next;
- break;
- }
+ return cairo_font_face_reference (&font_face->base);
}
/* No match found, create a new one */
font_face = malloc (sizeof (cairo_ft_font_face_t));
- if (!font_face) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (!font_face)
return NULL;
- }
font_face->unscaled = unscaled;
_cairo_unscaled_font_reference (&unscaled->base);
font_face->ft_options = *ft_options;
font_face->next = unscaled->faces;
unscaled->faces = font_face;
@@ -2451,18 +2371,20 @@ cairo_ft_font_face_create_for_pattern (F
}
_get_pattern_ft_options (pattern, &ft_options);
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
_cairo_unscaled_font_destroy (&unscaled->base);
if (font_face)
return font_face;
- else
+ else {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
+ }
}
/**
* cairo_ft_font_face_create_for_ft_face:
* @face: A FreeType face object, already opened. This must
* be kept around until the face's ref_count drops to
* zero and it is freed. Since the face may be referenced
* internally to Cairo, the best way to determine when it
@@ -2502,20 +2424,22 @@ cairo_ft_font_face_create_for_ft_face (F
ft_options.load_flags = load_flags;
ft_options.extra_flags = 0;
_cairo_font_options_init_default (&ft_options.base);
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
_cairo_unscaled_font_destroy (&unscaled->base);
- if (font_face)
+ if (font_face) {
return font_face;
- else
+ } else {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
+ }
}
/**
* cairo_ft_scaled_font_lock_face:
* @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
* object can be created by calling cairo_scaled_font_create() on a
* FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
* cairo_ft_font_face_create_for_face()).
@@ -2543,34 +2467,28 @@ cairo_ft_font_face_create_for_ft_face (F
* or %NULL if @scaled_font is in an error state (see
* cairo_scaled_font_status()) or there is insufficient memory.
**/
FT_Face
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;
face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
if (face == NULL) {
_cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
return NULL;
}
- status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
- &scaled_font->base.scale);
- if (status) {
- _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
- _cairo_scaled_font_set_error (&scaled_font->base, status);
- return NULL;
- }
+ _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
+ &scaled_font->base.scale);
/* NOTE: We deliberately release the unscaled font's mutex here,
* so that we are not holding a lock across two separate calls to
* cairo function, (which would give the application some
* opportunity for creating deadlock. This is obviously unsafe,
* but as documented, the user must add manual locking when using
* this function. */
CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex);
deleted file mode 100644
--- a/gfx/cairo/cairo/src/cairo-ft-font.c.orig
+++ /dev/null
@@ -1,2624 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2000 Keith Packard
- * Copyright © 2005 Red Hat, Inc
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Red Hat, Inc.
- *
- * Contributor(s):
- * Graydon Hoare <graydon@redhat.com>
- * Owen Taylor <otaylor@redhat.com>
- * Keith Packard <keithp@keithp.com>
- * Carl Worth <cworth@cworth.org>
- */
-
-#include "cairoint.h"
-
-#include "cairo-ft-private.h"
-
-#include <float.h>
-
-#include <fontconfig/fontconfig.h>
-#include <fontconfig/fcfreetype.h>
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_OUTLINE_H
-#include FT_IMAGE_H
-#include FT_TRUETYPE_TABLES_H
-#if HAVE_FT_GLYPHSLOT_EMBOLDEN
-#include FT_SYNTHESIS_H
-#endif
-
-#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
-#define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
-#define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
-#define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
-
-/* This is the max number of FT_face objects we keep open at once
- */
-#define MAX_OPEN_FACES 10
-
-/*
- * The simple 2x2 matrix is converted into separate scale and shape
- * factors so that hinting works right
- */
-
-typedef struct _cairo_ft_font_transform {
- double x_scale, y_scale;
- double shape[2][2];
-} cairo_ft_font_transform_t;
-
-/*
- * We create an object that corresponds to a single font on the disk;
- * (identified by a filename/id pair) these are shared between all
- * fonts using that file. For cairo_ft_font_face_create_for_ft_face(), we
- * just create a one-off version with a permanent face value.
- */
-
-typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
-
-struct _cairo_ft_unscaled_font {
- cairo_unscaled_font_t base;
-
- cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */
- FT_Face face; /* provided or cached face */
-
- /* only set if from_face is false */
- char *filename;
- int id;
-
- /* We temporarily scale the unscaled font as needed */
- cairo_bool_t have_scale;
- cairo_matrix_t current_scale;
- double x_scale; /* Extracted X scale factor */
- double y_scale; /* Extracted Y scale factor */
- cairo_bool_t have_shape; /* true if the current scale has a non-scale component*/
- cairo_matrix_t current_shape;
- FT_Matrix Current_Shape;
-
- cairo_mutex_t mutex;
- int lock_count;
-
- cairo_ft_font_face_t *faces; /* Linked list of faces for this font */
-};
-
-static int
-_cairo_ft_unscaled_font_keys_equal (const void *key_a,
- const void *key_b);
-
-static void
-_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
-
-typedef enum _cairo_ft_extra_flags {
- CAIRO_FT_OPTIONS_HINT_METRICS = (1 << 0),
- CAIRO_FT_OPTIONS_EMBOLDEN = (1 << 1)
-} cairo_ft_extra_flags_t;
-
-typedef struct _cairo_ft_options {
- cairo_font_options_t base;
- int load_flags; /* flags for FT_Load_Glyph */
- cairo_ft_extra_flags_t extra_flags; /* other flags that affect results */
-} cairo_ft_options_t;
-
-struct _cairo_ft_font_face {
- cairo_font_face_t base;
- cairo_ft_unscaled_font_t *unscaled;
- cairo_ft_options_t ft_options;
- cairo_ft_font_face_t *next;
-};
-
-static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
-
-/*
- * We maintain a hash table to map file/id => cairo_ft_unscaled_font_t.
- * The hash table itself isn't limited in size. However, we limit the
- * number of FT_Face objects we keep around; when we've exceeded that
- * limit and need to create a new FT_Face, we dump the FT_Face from a
- * random cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
- * there are any).
- */
-
-typedef struct _cairo_ft_unscaled_font_map {
- cairo_hash_table_t *hash_table;
- FT_Library ft_library;
- int num_open_faces;
-} cairo_ft_unscaled_font_map_t;
-
-static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
-
-static void
-_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
- cairo_ft_unscaled_font_t *unscaled)
-{
- if (unscaled->face) {
- FT_Done_Face (unscaled->face);
- unscaled->face = NULL;
- unscaled->have_scale = FALSE;
-
- font_map->num_open_faces--;
- }
-}
-
-static void
-_cairo_ft_unscaled_font_map_create (void)
-{
- cairo_ft_unscaled_font_map_t *font_map;
-
- /* This function is only intended to be called from
- * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can
- * detect some other call path. */
- assert (cairo_ft_unscaled_font_map == NULL);
-
- font_map = malloc (sizeof (cairo_ft_unscaled_font_map_t));
- if (font_map == NULL)
- goto FAIL;
-
- font_map->hash_table =
- _cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);
-
- if (font_map->hash_table == NULL)
- goto FAIL;
-
- if (FT_Init_FreeType (&font_map->ft_library))
- goto FAIL;
-
- font_map->num_open_faces = 0;
-
- cairo_ft_unscaled_font_map = font_map;
- return;
-
-FAIL:
- if (font_map) {
- if (font_map->hash_table)
- _cairo_hash_table_destroy (font_map->hash_table);
- free (font_map);
- }
- cairo_ft_unscaled_font_map = NULL;
-}
-
-static void
-_cairo_ft_unscaled_font_map_destroy (void)
-{
- cairo_ft_unscaled_font_t *unscaled;
- cairo_ft_unscaled_font_map_t *font_map;
-
- CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
-
- if (cairo_ft_unscaled_font_map) {
- font_map = cairo_ft_unscaled_font_map;
-
- /* This is rather inefficient, but destroying the hash table
- * is something we only do during debugging, (during
- * cairo_debug_reset_static_data), when efficiency is not
- * relevant. */
- while (1) {
- unscaled = _cairo_hash_table_random_entry (font_map->hash_table,
- NULL);
- if (unscaled == NULL)
- break;
- _cairo_hash_table_remove (font_map->hash_table,
- &unscaled->base.hash_entry);
-
- _font_map_release_face_lock_held (font_map, unscaled);
- _cairo_ft_unscaled_font_fini (unscaled);
- free (unscaled);
- }
-
- assert (font_map->num_open_faces == 0);
-
- FT_Done_FreeType (font_map->ft_library);
-
- _cairo_hash_table_destroy (font_map->hash_table);
-
- free (font_map);
-
- cairo_ft_unscaled_font_map = NULL;
- }
-
- CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
-}
-
-static cairo_ft_unscaled_font_map_t *
-_cairo_ft_unscaled_font_map_lock (void)
-{
- CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
-
- if (cairo_ft_unscaled_font_map == NULL)
- {
- _cairo_ft_unscaled_font_map_create ();
-
- if (cairo_ft_unscaled_font_map == NULL) {
- CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
- }
-
- return cairo_ft_unscaled_font_map;
-}
-
-static void
-_cairo_ft_unscaled_font_map_unlock (void)
-{
- CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
-}
-
-static void
-_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
- char *filename,
- int id)
-{
- unsigned long hash;
-
- key->filename = filename;
- key->id = id;
-
- /* 1607 is just an arbitrary prime. */
- hash = _cairo_hash_string (filename);
- hash += ((unsigned long) id) * 1607;
-
- key->base.hash_entry.hash = hash;
-}
-
-/**
- * _cairo_ft_unscaled_font_init:
- *
- * Initialize a cairo_ft_unscaled_font_t.
- *
- * There are two basic flavors of cairo_ft_unscaled_font_t, one
- * created from an FT_Face and the other created from a filename/id
- * pair. These two flavors are identified as from_face and !from_face.
- *
- * To initialize a from_face font, pass filename==NULL, id=0 and the
- * desired face.
- *
- * To initialize a !from_face font, pass the filename/id as desired
- * and face==NULL.
- *
- * Note that the code handles these two flavors in very distinct
- * ways. For example there is a hash_table mapping
- * filename/id->cairo_unscaled_font_t in the !from_face case, but no
- * parallel in the from_face case, (where the calling code would have
- * to do its own mapping to ensure similar sharing).
- **/
-static cairo_status_t
-_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
- const char *filename,
- int id,
- FT_Face face)
-{
- _cairo_unscaled_font_init (&unscaled->base,
- &cairo_ft_unscaled_font_backend);
-
- if (face) {
- unscaled->from_face = TRUE;
- unscaled->face = face;
- unscaled->filename = NULL;
- unscaled->id = 0;
- } else {
- char *filename_copy;
-
- unscaled->from_face = FALSE;
- unscaled->face = NULL;
-
- filename_copy = strdup (filename);
- 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);
- unscaled->lock_count = 0;
-
- unscaled->faces = NULL;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_bool_t
-_cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font)
-{
- return unscaled_font->backend == &cairo_ft_unscaled_font_backend;
-}
-
-/**
- * _cairo_ft_unscaled_font_fini:
- *
- * Free all data associated with a cairo_ft_unscaled_font_t.
- *
- * CAUTION: The unscaled->face field must be NULL before calling this
- * function. This is because the cairo_ft_unscaled_font_map keeps a
- * count of these faces (font_map->num_open_faces) so it maintains the
- * unscaled->face field while it has its lock held. See
- * _font_map_release_face_lock_held().
- **/
-static void
-_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
-{
- assert (unscaled->face == NULL);
-
- if (unscaled->filename) {
- free (unscaled->filename);
- unscaled->filename = NULL;
- }
-
- CAIRO_MUTEX_FINI (unscaled->mutex);
-}
-
-static int
-_cairo_ft_unscaled_font_keys_equal (const void *key_a,
- const void *key_b)
-{
- const cairo_ft_unscaled_font_t *unscaled_a = key_a;
- const cairo_ft_unscaled_font_t *unscaled_b = key_b;
-
- return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
- unscaled_a->id == unscaled_b->id);
-}
-
-/* Finds or creates a cairo_ft_unscaled_font for the filename/id from
- * pattern. Returns a new reference to the unscaled font.
- */
-static cairo_ft_unscaled_font_t *
-_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
-{
- cairo_ft_unscaled_font_t key, *unscaled;
- cairo_ft_unscaled_font_map_t *font_map;
- cairo_status_t status;
- FcChar8 *fc_filename;
- char *filename;
- int id;
-
- if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
- goto UNWIND;
- filename = (char *) fc_filename;
-
- if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
- goto UNWIND;
-
- font_map = _cairo_ft_unscaled_font_map_lock ();
- if (font_map == NULL)
- goto UNWIND;
-
- _cairo_ft_unscaled_font_init_key (&key, filename, id);
-
- /* Return existing unscaled font if it exists in the hash table. */
- if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
- (cairo_hash_entry_t **) &unscaled))
- {
- _cairo_unscaled_font_reference (&unscaled->base);
- _cairo_ft_unscaled_font_map_unlock ();
- return unscaled;
- }
-
- /* Otherwise create it and insert into hash table. */
- unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
- if (unscaled == NULL)
- goto UNWIND_FONT_MAP_LOCK;
-
- status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);
- if (status)
- goto UNWIND_UNSCALED_MALLOC;
-
- status = _cairo_hash_table_insert (font_map->hash_table,
- &unscaled->base.hash_entry);
- if (status)
- goto UNWIND_UNSCALED_FONT_INIT;
-
- _cairo_ft_unscaled_font_map_unlock ();
-
- return unscaled;
-
-UNWIND_UNSCALED_FONT_INIT:
- _cairo_ft_unscaled_font_fini (unscaled);
-UNWIND_UNSCALED_MALLOC:
- free (unscaled);
-UNWIND_FONT_MAP_LOCK:
- _cairo_ft_unscaled_font_map_unlock ();
-UNWIND:
- return NULL;
-}
-
-static cairo_ft_unscaled_font_t *
-_cairo_ft_unscaled_font_create_from_face (FT_Face face)
-{
- cairo_status_t status;
- cairo_ft_unscaled_font_t *unscaled;
-
- unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
- if (unscaled == NULL)
- return NULL;
-
- status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);
- if (status) {
- free (unscaled);
- return NULL;
- }
-
- return unscaled;
-}
-
-static void
-_cairo_ft_unscaled_font_destroy (void *abstract_font)
-{
- cairo_ft_unscaled_font_t *unscaled = abstract_font;
-
- if (unscaled == NULL)
- return;
-
- if (unscaled->from_face) {
- /* See comments in _ft_font_face_destroy about the "zombie" state
- * for a _ft_font_face.
- */
- if (unscaled->faces && !unscaled->faces->unscaled)
- cairo_font_face_destroy (&unscaled->faces->base);
- } else {
- cairo_ft_unscaled_font_map_t *font_map;
-
- font_map = _cairo_ft_unscaled_font_map_lock ();
- /* All created objects must have been mapped in the font map. */
- assert (font_map != NULL);
-
- _cairo_hash_table_remove (font_map->hash_table,
- &unscaled->base.hash_entry);
-
- _font_map_release_face_lock_held (font_map, unscaled);
- _cairo_ft_unscaled_font_fini (unscaled);
-
- _cairo_ft_unscaled_font_map_unlock ();
- }
-}
-
-static cairo_bool_t
-_has_unlocked_face (void *entry)
-{
- cairo_ft_unscaled_font_t *unscaled = entry;
-
- return (unscaled->lock_count == 0 && unscaled->face);
-}
-
-/* Ensures that an unscaled font has a face object. If we exceed
- * MAX_OPEN_FACES, try to close some.
- *
- * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
- * set the scale on the face, but just returns it at the last scale.
- */
-FT_Face
-_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
-{
- cairo_ft_unscaled_font_map_t *font_map;
- FT_Face face = NULL;
-
- CAIRO_MUTEX_LOCK (unscaled->mutex);
- unscaled->lock_count++;
-
- if (unscaled->face)
- return unscaled->face;
-
- /* If this unscaled font was created from an FT_Face then we just
- * returned it above. */
- assert (!unscaled->from_face);
-
- font_map = _cairo_ft_unscaled_font_map_lock ();
- {
- assert (font_map != NULL);
-
- while (font_map->num_open_faces >= MAX_OPEN_FACES)
- {
- cairo_ft_unscaled_font_t *entry;
-
- entry = _cairo_hash_table_random_entry (font_map->hash_table,
- _has_unlocked_face);
- if (entry == NULL)
- break;
-
- _font_map_release_face_lock_held (font_map, entry);
- }
- }
- _cairo_ft_unscaled_font_map_unlock ();
-
- if (FT_New_Face (font_map->ft_library,
- unscaled->filename,
- unscaled->id,
- &face) != FT_Err_Ok)
- {
- CAIRO_MUTEX_UNLOCK (unscaled->mutex);
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
-
- unscaled->face = face;
-
- font_map->num_open_faces++;
-
- return face;
-}
-slim_hidden_def (cairo_ft_scaled_font_lock_face);
-
-/* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
- */
-void
-_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
-{
- assert (unscaled->lock_count > 0);
-
- unscaled->lock_count--;
-
- CAIRO_MUTEX_UNLOCK (unscaled->mutex);
-}
-slim_hidden_def (cairo_ft_scaled_font_unlock_face);
-
-static void
-_compute_transform (cairo_ft_font_transform_t *sf,
- cairo_matrix_t *scale)
-{
- cairo_matrix_t normalized = *scale;
- double tx, ty;
-
- /* The font matrix has x and y "scale" components which we extract and
- * use as character scale values. These influence the way freetype
- * chooses hints, as well as selecting different bitmaps in
- * hand-rendered fonts. We also copy the normalized matrix to
- * freetype's transformation.
- */
-
- _cairo_matrix_compute_scale_factors (&normalized,
- &sf->x_scale, &sf->y_scale,
- /* XXX */ 1);
-
- if (sf->x_scale != 0 && sf->y_scale != 0) {
- cairo_matrix_scale (&normalized, 1.0 / sf->x_scale, 1.0 / sf->y_scale);
-
- _cairo_matrix_get_affine (&normalized,
- &sf->shape[0][0], &sf->shape[0][1],
- &sf->shape[1][0], &sf->shape[1][1],
- &tx, &ty);
- } else {
- sf->shape[0][0] = sf->shape[1][1] = 1.0;
- sf->shape[0][1] = sf->shape[1][0] = 0.0;
- }
-}
-
-/* Temporarily scales an unscaled font to the give scale. We catch
- * scaling to the same size, since changing a FT_Face is expensive.
- */
-static cairo_status_t
-_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
- cairo_matrix_t *scale)
-{
- cairo_ft_font_transform_t sf;
- FT_Matrix mat;
- FT_Error error;
-
- assert (unscaled->face != NULL);
-
- if (unscaled->have_scale &&
- scale->xx == unscaled->current_scale.xx &&
- scale->yx == unscaled->current_scale.yx &&
- scale->xy == unscaled->current_scale.xy &&
- scale->yy == unscaled->current_scale.yy)
- return CAIRO_STATUS_SUCCESS;
-
- unscaled->have_scale = TRUE;
- unscaled->current_scale = *scale;
-
- _compute_transform (&sf, scale);
-
- unscaled->x_scale = sf.x_scale;
- unscaled->y_scale = sf.y_scale;
-
- mat.xx = DOUBLE_TO_16_16(sf.shape[0][0]);
- mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1]);
- mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]);
- mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]);
-
- unscaled->have_shape = (mat.xx != 0x10000 ||
- mat.yx != 0x00000 ||
- mat.xy != 0x00000 ||
- mat.yy != 0x10000);
-
- unscaled->Current_Shape = mat;
- cairo_matrix_init (&unscaled->current_shape,
- sf.shape[0][0], sf.shape[0][1],
- sf.shape[1][0], sf.shape[1][1],
- 0.0, 0.0);
-
- FT_Set_Transform(unscaled->face, &mat, NULL);
-
- if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
- error = FT_Set_Char_Size (unscaled->face,
- sf.x_scale * 64.0,
- sf.y_scale * 64.0,
- 0, 0);
- if (error) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
- } else {
- double min_distance = DBL_MAX;
- int i;
- int best_i = 0;
-
- for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
-#if HAVE_FT_BITMAP_SIZE_Y_PPEM
- double size = unscaled->face->available_sizes[i].y_ppem / 64.;
-#else
- double size = unscaled->face->available_sizes[i].height;
-#endif
- double distance = fabs (size - sf.y_scale);
-
- if (distance <= min_distance) {
- min_distance = distance;
- best_i = i;
- }
- }
-#if HAVE_FT_BITMAP_SIZE_Y_PPEM
- error = FT_Set_Char_Size (unscaled->face,
- unscaled->face->available_sizes[best_i].x_ppem,
- unscaled->face->available_sizes[best_i].y_ppem,
- 0, 0);
- if (error)
-#endif
- error = FT_Set_Pixel_Sizes (unscaled->face,
- unscaled->face->available_sizes[best_i].width,
- unscaled->face->available_sizes[best_i].height);
- if (error) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/* Empirically-derived subpixel filtering values thanks to Keith
- * Packard and libXft. */
-static const int filters[3][3] = {
- /* red */
-#if 0
- { 65538*4/7,65538*2/7,65538*1/7 },
- /* green */
- { 65536*1/4, 65536*2/4, 65537*1/4 },
- /* blue */
- { 65538*1/7,65538*2/7,65538*4/7 },
-#endif
- { 65538*9/13,65538*3/13,65538*1/13 },
- /* green */
- { 65538*1/6, 65538*4/6, 65538*1/6 },
- /* blue */
- { 65538*1/13,65538*3/13,65538*9/13 },
-};
-
-/* Fills in val->image with an image surface created from @bitmap
- */
-static cairo_status_t
-_get_bitmap_surface (FT_Bitmap *bitmap,
- cairo_bool_t own_buffer,
- cairo_font_options_t *font_options,
- cairo_image_surface_t **surface)
-{
- int width, height, stride;
- unsigned char *data;
- int format = CAIRO_FORMAT_A8;
- cairo_bool_t subpixel = FALSE;
-
- width = bitmap->width;
- height = bitmap->rows;
-
- switch (bitmap->pixel_mode) {
- case FT_PIXEL_MODE_MONO:
- stride = (((width + 31) & ~31) >> 3);
- if (own_buffer) {
- data = bitmap->buffer;
- assert (stride == bitmap->pitch);
- } else {
- data = malloc (stride * height);
- if (!data) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- if (stride == bitmap->pitch) {
- memcpy (data, bitmap->buffer, stride * height);
- } else {
- int i;
- unsigned char *source, *dest;
-
- source = bitmap->buffer;
- dest = data;
- for (i = height; i; i--) {
- memcpy (dest, source, bitmap->pitch);
- memset (dest + bitmap->pitch, '\0', stride - bitmap->pitch);
-
- source += bitmap->pitch;
- dest += stride;
- }
- }
- }
-
-#ifndef WORDS_BIGENDIAN
- {
- unsigned char *d = data;
- int count = stride * height;
-
- while (count--) {
- *d = CAIRO_BITSWAP8 (*d);
- d++;
- }
- }
-#endif
- format = CAIRO_FORMAT_A1;
- break;
-
- case FT_PIXEL_MODE_LCD:
- case FT_PIXEL_MODE_LCD_V:
- case FT_PIXEL_MODE_GRAY:
- switch (font_options->antialias) {
- case CAIRO_ANTIALIAS_DEFAULT:
- case CAIRO_ANTIALIAS_GRAY:
- case CAIRO_ANTIALIAS_NONE:
- default:
- stride = bitmap->pitch;
- if (own_buffer) {
- data = bitmap->buffer;
- } else {
- data = malloc (stride * height);
- if (!data) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
- memcpy (data, bitmap->buffer, stride * height);
- }
- format = CAIRO_FORMAT_A8;
- break;
- case CAIRO_ANTIALIAS_SUBPIXEL: {
- int x, y;
- unsigned char *in_line, *out_line, *in;
- unsigned int *out;
- unsigned int red, green, blue;
- int rf, gf, bf;
- int s;
- int o, os;
- unsigned char *data_rgba;
- unsigned int width_rgba, stride_rgba;
- int vmul = 1;
- int hmul = 1;
-
- switch (font_options->subpixel_order) {
- case CAIRO_SUBPIXEL_ORDER_DEFAULT:
- case CAIRO_SUBPIXEL_ORDER_RGB:
- case CAIRO_SUBPIXEL_ORDER_BGR:
- default:
- width /= 3;
- hmul = 3;
- break;
- case CAIRO_SUBPIXEL_ORDER_VRGB:
- case CAIRO_SUBPIXEL_ORDER_VBGR:
- vmul = 3;
- height /= 3;
- break;
- }
- /*
- * Filter the glyph to soften the color fringes
- */
- width_rgba = width;
- 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) {
- case CAIRO_SUBPIXEL_ORDER_VRGB:
- os = stride;
- case CAIRO_SUBPIXEL_ORDER_DEFAULT:
- case CAIRO_SUBPIXEL_ORDER_RGB:
- default:
- rf = 0;
- gf = 1;
- bf = 2;
- break;
- case CAIRO_SUBPIXEL_ORDER_VBGR:
- os = stride;
- case CAIRO_SUBPIXEL_ORDER_BGR:
- bf = 0;
- gf = 1;
- rf = 2;
- break;
- }
- in_line = bitmap->buffer;
- out_line = data_rgba;
- for (y = 0; y < height; y++)
- {
- in = in_line;
- out = (unsigned int *) out_line;
- in_line += stride * vmul;
- out_line += stride_rgba;
- for (x = 0; x < width * hmul; x += hmul)
- {
- red = green = blue = 0;
- o = 0;
- for (s = 0; s < 3; s++)
- {
- red += filters[rf][s]*in[x+o];
- green += filters[gf][s]*in[x+o];
- blue += filters[bf][s]*in[x+o];
- o += os;
- }
- red = red / 65536;
- green = green / 65536;
- blue = blue / 65536;
- *out++ = (green << 24) | (red << 16) | (green << 8) | blue;
- }
- }
-
- /* Images here are stored in native format. The
- * backend must convert to its own format as needed
- */
-
- if (own_buffer)
- free (bitmap->buffer);
- data = data_rgba;
- stride = stride_rgba;
- format = CAIRO_FORMAT_ARGB32;
- subpixel = TRUE;
- break;
- }
- }
- break;
- case FT_PIXEL_MODE_GRAY2:
- 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;
- }
-
- *surface = (cairo_image_surface_t *)
- cairo_image_surface_create_for_data (data,
- format,
- width, height, stride);
- if ((*surface)->base.status) {
- free (data);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- if (subpixel)
- pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
-
- _cairo_image_surface_assume_ownership_of_data ((*surface));
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/* Converts an outline FT_GlyphSlot into an image
- *
- * This could go through _render_glyph_bitmap as well, letting
- * FreeType convert the outline to a bitmap, but doing it ourselves
- * has two minor advantages: first, we save a copy of the bitmap
- * buffer: we can directly use the buffer that FreeType renders
- * into.
- *
- * Second, it may help when we add support for subpixel
- * rendering: the Xft code does it this way. (Keith thinks that
- * it may also be possible to get the subpixel rendering with
- * FT_Render_Glyph: something worth looking into in more detail
- * when we add subpixel support. If so, we may want to eliminate
- * this version of the code path entirely.
- */
-static cairo_status_t
-_render_glyph_outline (FT_Face face,
- cairo_font_options_t *font_options,
- cairo_image_surface_t **surface)
-{
- FT_GlyphSlot glyphslot = face->glyph;
- FT_Outline *outline = &glyphslot->outline;
- FT_Bitmap bitmap;
- FT_BBox cbox;
- FT_Matrix matrix;
- int hmul = 1;
- int vmul = 1;
- unsigned int width, height, stride;
- cairo_bool_t subpixel = FALSE;
- cairo_status_t status;
-
- FT_Outline_Get_CBox (outline, &cbox);
-
- cbox.xMin &= -64;
- cbox.yMin &= -64;
- cbox.xMax = (cbox.xMax + 63) & -64;
- cbox.yMax = (cbox.yMax + 63) & -64;
-
- width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
- height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
- stride = (width * hmul + 3) & ~3;
-
- if (width * height == 0) {
- cairo_format_t format;
- /* Looks like fb handles zero-sized images just fine */
- switch (font_options->antialias) {
- case CAIRO_ANTIALIAS_NONE:
- format = CAIRO_FORMAT_A1;
- break;
- case CAIRO_ANTIALIAS_SUBPIXEL:
- format= CAIRO_FORMAT_ARGB32;
- break;
- case CAIRO_ANTIALIAS_DEFAULT:
- case CAIRO_ANTIALIAS_GRAY:
- default:
- format = CAIRO_FORMAT_A8;
- break;
- }
-
- (*surface) = (cairo_image_surface_t *)
- cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
- if ((*surface)->base.status)
- return CAIRO_STATUS_NO_MEMORY;
- } else {
-
- matrix.xx = matrix.yy = 0x10000L;
- matrix.xy = matrix.yx = 0;
-
- switch (font_options->antialias) {
- case CAIRO_ANTIALIAS_NONE:
- bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
- bitmap.num_grays = 1;
- stride = ((width + 31) & -32) >> 3;
- break;
- case CAIRO_ANTIALIAS_DEFAULT:
- case CAIRO_ANTIALIAS_GRAY:
- bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
- bitmap.num_grays = 256;
- stride = (width + 3) & -4;
- break;
- case CAIRO_ANTIALIAS_SUBPIXEL:
- switch (font_options->subpixel_order) {
- case CAIRO_SUBPIXEL_ORDER_RGB:
- case CAIRO_SUBPIXEL_ORDER_BGR:
- case CAIRO_SUBPIXEL_ORDER_DEFAULT:
- default:
- matrix.xx *= 3;
- hmul = 3;
- subpixel = TRUE;
- break;
- case CAIRO_SUBPIXEL_ORDER_VRGB:
- case CAIRO_SUBPIXEL_ORDER_VBGR:
- matrix.yy *= 3;
- vmul = 3;
- subpixel = TRUE;
- break;
- }
- FT_Outline_Transform (outline, &matrix);
-
- bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
- bitmap.num_grays = 256;
- stride = (width * hmul + 3) & -4;
- }
-
- bitmap.pitch = stride;
- bitmap.width = width * hmul;
- bitmap.rows = height * vmul;
- bitmap.buffer = calloc (1, stride * bitmap.rows);
-
- if (bitmap.buffer == NULL) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
-
- if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
- free (bitmap.buffer);
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
- if (status)
- return status;
- }
-
- /*
- * Note: the font's coordinate system is upside down from ours, so the
- * Y coordinate of the control box needs to be negated.
- */
- cairo_surface_set_device_offset (&(*surface)->base,
- floor ((double) cbox.xMin / 64.0),
- floor (-(double) cbox.yMax / 64.0));
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/* Converts a bitmap (or other) FT_GlyphSlot into an image */
-static cairo_status_t
-_render_glyph_bitmap (FT_Face face,
- cairo_font_options_t *font_options,
- cairo_image_surface_t **surface)
-{
- FT_GlyphSlot glyphslot = face->glyph;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- FT_Error error;
-
- /* According to the FreeType docs, glyphslot->format could be
- * something other than FT_GLYPH_FORMAT_OUTLINE or
- * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
- * the opportunity to convert such to
- * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
- * we avoid the FT_LOAD_NO_RECURSE flag.
- */
- error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
- if (error) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
- if (status)
- return status;
-
- /*
- * Note: the font's coordinate system is upside down from ours, so the
- * Y coordinate of the control box needs to be negated.
- */
- cairo_surface_set_device_offset (&(*surface)->base,
- glyphslot->bitmap_left,
- -glyphslot->bitmap_top);
-
- return status;
-}
-
-static cairo_status_t
-_transform_glyph_bitmap (cairo_matrix_t * shape,
- cairo_image_surface_t ** surface)
-{
- cairo_matrix_t original_to_transformed;
- cairo_matrix_t transformed_to_original;
- cairo_image_surface_t *old_image;
- cairo_surface_t *image;
- double x[4], y[4];
- double origin_x, origin_y;
- int origin_width, origin_height;
- int i;
- int x_min, y_min, x_max, y_max;
- int width, height;
- cairo_status_t status;
- cairo_surface_pattern_t pattern;
-
- /* We want to compute a transform that takes the origin
- * (device_x_offset, device_y_offset) to 0,0, then applies
- * the "shape" portion of the font transform
- */
- original_to_transformed = *shape;
-
- cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
- origin_width = cairo_image_surface_get_width (&(*surface)->base);
- origin_height = cairo_image_surface_get_height (&(*surface)->base);
-
- cairo_matrix_translate (&original_to_transformed,
- origin_x, origin_y);
-
- /* Find the bounding box of the original bitmap under that
- * transform
- */
- x[0] = 0; y[0] = 0;
- x[1] = origin_width; y[1] = 0;
- x[2] = origin_width; y[2] = origin_height;
- x[3] = 0; y[3] = origin_height;
-
- for (i = 0; i < 4; i++)
- cairo_matrix_transform_point (&original_to_transformed,
- &x[i], &y[i]);
-
- x_min = floor (x[0]); y_min = floor (y[0]);
- x_max = ceil (x[0]); y_max = ceil (y[0]);
-
- for (i = 1; i < 4; i++) {
- if (x[i] < x_min)
- x_min = floor (x[i]);
- if (x[i] > x_max)
- x_max = ceil (x[i]);
- if (y[i] < y_min)
- y_min = floor (y[i]);
- if (y[i] > y_max)
- y_max = ceil (y[i]);
- }
-
- /* Adjust the transform so that the bounding box starts at 0,0 ...
- * this gives our final transform from original bitmap to transformed
- * bitmap.
- */
- original_to_transformed.x0 -= x_min;
- original_to_transformed.y0 -= y_min;
-
- /* Create the transformed bitmap
- */
- width = x_max - x_min;
- height = y_max - y_min;
-
- transformed_to_original = original_to_transformed;
- status = cairo_matrix_invert (&transformed_to_original);
- if (status)
- return status;
-
- /* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
- width = (width + 3) & ~3;
- image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
- if (image->status)
- return CAIRO_STATUS_NO_MEMORY;
-
- /* Initialize it to empty
- */
- status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
- CAIRO_COLOR_TRANSPARENT,
- 0, 0,
- width, height);
- if (status) {
- cairo_surface_destroy (image);
- return status;
- }
-
- /* Draw the original bitmap transformed into the new bitmap
- */
- _cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
- cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
-
- status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
- &pattern.base, NULL, image,
- 0, 0, 0, 0, 0, 0,
- width,
- height);
-
- _cairo_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.
- */
- origin_x = - origin_x;
- origin_y = - origin_y;
- cairo_matrix_transform_point (&original_to_transformed,
- &origin_x, &origin_y);
-
- old_image = (*surface);
- (*surface) = (cairo_image_surface_t *)image;
- cairo_surface_destroy (&old_image->base);
-
- cairo_surface_set_device_offset (&(*surface)->base,
- - _cairo_lround (origin_x),
- - _cairo_lround (origin_y));
- return status;
-}
-
-static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
- _cairo_ft_unscaled_font_destroy,
-#if 0
- _cairo_ft_unscaled_font_create_glyph
-#endif
-};
-
-/* cairo_ft_scaled_font_t */
-
-typedef struct _cairo_ft_scaled_font {
- cairo_scaled_font_t base;
- cairo_ft_unscaled_font_t *unscaled;
- cairo_ft_options_t ft_options;
-} cairo_ft_scaled_font_t;
-
-const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
-
-/* The load flags passed to FT_Load_Glyph control aspects like hinting and
- * antialiasing. Here we compute them from the fields of a FcPattern.
- */
-static void
-_get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
-{
- FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
- cairo_ft_options_t ft_options;
- int rgba;
-#ifdef FC_HINT_STYLE
- int hintstyle;
-#endif
-
- _cairo_font_options_init_default (&ft_options.base);
- ft_options.load_flags = FT_LOAD_DEFAULT;
- ft_options.extra_flags = 0;
-
-#ifndef FC_EMBEDDED_BITMAP
-#define FC_EMBEDDED_BITMAP "embeddedbitmap"
-#endif
-
- /* Check whether to force use of embedded bitmaps */
- if (FcPatternGetBool (pattern,
- FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
- bitmap = FcFalse;
-
- /* disable antialiasing if requested */
- if (FcPatternGetBool (pattern,
- FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
- antialias = FcTrue;
-
- if (antialias) {
- cairo_subpixel_order_t subpixel_order;
-
- if (!bitmap)
- ft_options.load_flags |= FT_LOAD_NO_BITMAP;
-
- /* disable hinting if requested */
- if (FcPatternGetBool (pattern,
- FC_HINTING, 0, &hinting) != FcResultMatch)
- hinting = FcTrue;
-
- if (FcPatternGetInteger (pattern,
- FC_RGBA, 0, &rgba) != FcResultMatch)
- rgba = FC_RGBA_UNKNOWN;
-
- switch (rgba) {
- case FC_RGBA_RGB:
- subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
- break;
- case FC_RGBA_BGR:
- subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
- break;
- case FC_RGBA_VRGB:
- subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
- break;
- case FC_RGBA_VBGR:
- subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
- break;
- case FC_RGBA_UNKNOWN:
- case FC_RGBA_NONE:
- default:
- subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
- break;
- }
-
- if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
- ft_options.base.subpixel_order = subpixel_order;
- ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
- }
-
-#ifdef FC_HINT_STYLE
- if (FcPatternGetInteger (pattern,
- FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
- hintstyle = FC_HINT_FULL;
-
- if (!hinting)
- hintstyle = FC_HINT_NONE;
-
- switch (hintstyle) {
- case FC_HINT_NONE:
- ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
- break;
- case FC_HINT_SLIGHT:
- ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
- break;
- case FC_HINT_MEDIUM:
- default:
- ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM;
- break;
- case FC_HINT_FULL:
- ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL;
- break;
- }
-#else /* !FC_HINT_STYLE */
- if (!hinting) {
- ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
- }
-#endif /* FC_FHINT_STYLE */
- } else {
- ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
- }
-
- /* force autohinting if requested */
- if (FcPatternGetBool (pattern,
- FC_AUTOHINT, 0, &autohint) != FcResultMatch)
- autohint = FcFalse;
-
- if (autohint)
- ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT;
-
- if (FcPatternGetBool (pattern,
- FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch)
- vertical_layout = FcFalse;
-
- if (vertical_layout)
- ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT;
-
-#ifndef FC_EMBOLDEN
-#define FC_EMBOLDEN "embolden"
-#endif
- if (FcPatternGetBool (pattern,
- FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
- embolden = FcFalse;
-
- if (embolden)
- ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
-
- *ret = ft_options;
-}
-
-static void
-_cairo_ft_options_merge (cairo_ft_options_t *options,
- cairo_ft_options_t *other)
-{
- int load_flags = other->load_flags;
- int load_target = FT_LOAD_TARGET_NORMAL;
-
- /* clear load target mode */
- load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags)));
-
- if (load_flags & FT_LOAD_NO_HINTING)
- other->base.hint_style = CAIRO_HINT_STYLE_NONE;
-
- if (other->base.antialias == CAIRO_ANTIALIAS_NONE ||
- options->base.antialias == CAIRO_ANTIALIAS_NONE) {
- options->base.antialias = CAIRO_ANTIALIAS_NONE;
- options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
- }
-
- if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL &&
- (options->base.antialias == CAIRO_ANTIALIAS_DEFAULT ||
- options->base.antialias == CAIRO_ANTIALIAS_GRAY)) {
- options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
- options->base.subpixel_order = other->base.subpixel_order;
- }
-
- if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
- options->base.hint_style = other->base.hint_style;
-
- if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
- options->base.hint_style = CAIRO_HINT_STYLE_NONE;
-
- if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
- if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
- load_flags |= FT_LOAD_NO_HINTING;
- else
- load_target = FT_LOAD_TARGET_MONO;
- load_flags |= FT_LOAD_MONOCHROME;
- } else {
- switch (options->base.hint_style) {
- case CAIRO_HINT_STYLE_NONE:
- load_flags |= FT_LOAD_NO_HINTING;
- break;
- case CAIRO_HINT_STYLE_SLIGHT:
- load_target = FT_LOAD_TARGET_LIGHT;
- break;
- case CAIRO_HINT_STYLE_MEDIUM:
- break;
- case CAIRO_HINT_STYLE_FULL:
- case CAIRO_HINT_STYLE_DEFAULT:
- if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
- switch (options->base.subpixel_order) {
- case CAIRO_SUBPIXEL_ORDER_DEFAULT:
- case CAIRO_SUBPIXEL_ORDER_RGB:
- case CAIRO_SUBPIXEL_ORDER_BGR:
- load_target |= FT_LOAD_TARGET_LCD;
- break;
- case CAIRO_SUBPIXEL_ORDER_VRGB:
- case CAIRO_SUBPIXEL_ORDER_VBGR:
- load_target |= FT_LOAD_TARGET_LCD_V;
- break;
- }
- }
- break;
- }
- }
-
- options->load_flags = load_flags | load_target;
- options->extra_flags = other->extra_flags;
-}
-
-static cairo_scaled_font_t *
-_cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
- cairo_font_face_t *font_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_ft_options_t ft_options)
-{
- cairo_ft_scaled_font_t *scaled_font = NULL;
- 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)
- return NULL;
-
- 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;
- }
-
- _cairo_unscaled_font_reference (&unscaled->base);
- scaled_font->unscaled = unscaled;
-
- if (options->hint_metrics != CAIRO_HINT_METRICS_OFF)
- ft_options.extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS;
-
- _cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
- _cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
-
- status = _cairo_scaled_font_init (&scaled_font->base,
- font_face,
- font_matrix, ctm, options,
- &cairo_ft_scaled_font_backend);
- if (status) {
- free (scaled_font);
- _cairo_unscaled_font_destroy (&unscaled->base);
- _cairo_ft_unscaled_font_unlock_face (unscaled);
- return NULL;
- }
-
- status = _cairo_ft_unscaled_font_set_scale (unscaled,
- &scaled_font->base.scale);
- if (status) {
- free (scaled_font);
- _cairo_unscaled_font_destroy (&unscaled->base);
- _cairo_ft_unscaled_font_unlock_face (unscaled);
- return NULL;
- }
-
-
- metrics = &face->size->metrics;
-
- /*
- * Get to unscaled metrics so that the upper level can get back to
- * user space
- */
- if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
- double x_factor, y_factor;
-
- if (unscaled->x_scale == 0)
- x_factor = 0;
- else
- x_factor = 1 / unscaled->x_scale;
-
- if (unscaled->y_scale == 0)
- y_factor = 0;
- else
- y_factor = 1 / unscaled->y_scale;
-
- fs_metrics.ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor;
- fs_metrics.descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor;
- fs_metrics.height = DOUBLE_FROM_26_6(metrics->height) * y_factor;
- if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
- fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor;
- fs_metrics.max_y_advance = 0;
- } else {
- fs_metrics.max_x_advance = 0;
- fs_metrics.max_y_advance = DOUBLE_FROM_26_6(metrics->max_advance) * y_factor;
- }
- } else {
- double scale = face->units_per_EM;
-
- fs_metrics.ascent = face->ascender / scale;
- fs_metrics.descent = - face->descender / scale;
- fs_metrics.height = face->height / scale;
- if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
- fs_metrics.max_x_advance = face->max_advance_width / scale;
- fs_metrics.max_y_advance = 0;
- } else {
- fs_metrics.max_x_advance = 0;
- fs_metrics.max_y_advance = face->max_advance_height / scale;
- }
- }
-
- _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
-
- _cairo_ft_unscaled_font_unlock_face (unscaled);
-
- return &scaled_font->base;
-}
-
-cairo_bool_t
-_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
-{
- return scaled_font->backend == &cairo_ft_scaled_font_backend;
-}
-
-static cairo_status_t
-_cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *font_options,
- cairo_scaled_font_t **font)
-{
- FcPattern *pattern, *resolved;
- cairo_ft_unscaled_font_t *unscaled;
- cairo_scaled_font_t *new_font = NULL;
- FcResult result;
- int fcslant;
- int fcweight;
- cairo_matrix_t scale;
- cairo_ft_font_transform_t sf;
- cairo_ft_options_t ft_options;
- unsigned char *family = (unsigned char*) toy_face->family;
-
- pattern = FcPatternCreate ();
- if (!pattern) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- switch (toy_face->weight)
- {
- case CAIRO_FONT_WEIGHT_BOLD:
- fcweight = FC_WEIGHT_BOLD;
- break;
- case CAIRO_FONT_WEIGHT_NORMAL:
- default:
- fcweight = FC_WEIGHT_MEDIUM;
- break;
- }
-
- switch (toy_face->slant)
- {
- case CAIRO_FONT_SLANT_ITALIC:
- fcslant = FC_SLANT_ITALIC;
- break;
- case CAIRO_FONT_SLANT_OBLIQUE:
- fcslant = FC_SLANT_OBLIQUE;
- break;
- case CAIRO_FONT_SLANT_NORMAL:
- default:
- fcslant = FC_SLANT_ROMAN;
- break;
- }
-
- if (!FcPatternAddString (pattern, FC_FAMILY, family))
- goto FREE_PATTERN;
- if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant))
- goto FREE_PATTERN;
- if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight))
- goto FREE_PATTERN;
-
- cairo_matrix_multiply (&scale, font_matrix, ctm);
- _compute_transform (&sf, &scale);
-
- FcPatternAddInteger (pattern, FC_PIXEL_SIZE, sf.y_scale);
-
- FcConfigSubstitute (NULL, pattern, FcMatchPattern);
- cairo_ft_font_options_substitute (font_options, pattern);
- FcDefaultSubstitute (pattern);
-
- resolved = FcFontMatch (NULL, pattern, &result);
- if (!resolved)
- goto FREE_PATTERN;
-
- unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved);
- if (!unscaled)
- goto FREE_RESOLVED;
-
- _get_pattern_ft_options (resolved, &ft_options);
-
- new_font = _cairo_ft_scaled_font_create (unscaled,
- &toy_face->base,
- font_matrix, ctm,
- font_options, ft_options);
-
- _cairo_unscaled_font_destroy (&unscaled->base);
-
- FREE_RESOLVED:
- FcPatternDestroy (resolved);
-
- FREE_PATTERN:
- FcPatternDestroy (pattern);
-
- if (new_font) {
- *font = new_font;
- return CAIRO_STATUS_SUCCESS;
- } else {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
-}
-
-static void
-_cairo_ft_scaled_font_fini (void *abstract_font)
-{
- cairo_ft_scaled_font_t *scaled_font = abstract_font;
-
- if (scaled_font == NULL)
- return;
-
- _cairo_unscaled_font_destroy (&scaled_font->unscaled->base);
-}
-
-static int
-_move_to (FT_Vector *to, void *closure)
-{
- cairo_path_fixed_t *path = closure;
- cairo_fixed_t x, y;
-
- x = _cairo_fixed_from_26_6 (to->x);
- y = _cairo_fixed_from_26_6 (to->y);
-
- if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
- return 1;
- if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
- return 1;
-
- return 0;
-}
-
-static int
-_line_to (FT_Vector *to, void *closure)
-{
- cairo_path_fixed_t *path = closure;
- cairo_fixed_t x, y;
-
- x = _cairo_fixed_from_26_6 (to->x);
- y = _cairo_fixed_from_26_6 (to->y);
-
- if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
- return 1;
-
- return 0;
-}
-
-static int
-_conic_to (FT_Vector *control, FT_Vector *to, void *closure)
-{
- cairo_path_fixed_t *path = closure;
-
- cairo_fixed_t x0, y0;
- cairo_fixed_t x1, y1;
- cairo_fixed_t x2, y2;
- cairo_fixed_t x3, y3;
- cairo_point_t conic;
-
- 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);
-
- x3 = _cairo_fixed_from_26_6 (to->x);
- y3 = _cairo_fixed_from_26_6 (to->y);
-
- x1 = x0 + 2.0/3.0 * (conic.x - x0);
- y1 = y0 + 2.0/3.0 * (conic.y - y0);
-
- x2 = x3 + 2.0/3.0 * (conic.x - x3);
- y2 = y3 + 2.0/3.0 * (conic.y - y3);
-
- if (_cairo_path_fixed_curve_to (path,
- x1, y1,
- x2, y2,
- x3, y3) != CAIRO_STATUS_SUCCESS)
- return 1;
-
- return 0;
-}
-
-static int
-_cubic_to (FT_Vector *control1, FT_Vector *control2,
- FT_Vector *to, void *closure)
-{
- cairo_path_fixed_t *path = closure;
- cairo_fixed_t x0, y0;
- cairo_fixed_t x1, y1;
- cairo_fixed_t x2, y2;
-
- x0 = _cairo_fixed_from_26_6 (control1->x);
- y0 = _cairo_fixed_from_26_6 (control1->y);
-
- x1 = _cairo_fixed_from_26_6 (control2->x);
- y1 = _cairo_fixed_from_26_6 (control2->y);
-
- x2 = _cairo_fixed_from_26_6 (to->x);
- y2 = _cairo_fixed_from_26_6 (to->y);
-
- if (_cairo_path_fixed_curve_to (path,
- x0, y0,
- x1, y1,
- x2, y2) != CAIRO_STATUS_SUCCESS)
- return 1;
-
- return 0;
-}
-
-static cairo_status_t
-_decompose_glyph_outline (FT_Face face,
- cairo_font_options_t *options,
- cairo_path_fixed_t **pathp)
-{
- static const FT_Outline_Funcs outline_funcs = {
- (FT_Outline_MoveToFunc)_move_to,
- (FT_Outline_LineToFunc)_line_to,
- (FT_Outline_ConicToFunc)_conic_to,
- (FT_Outline_CubicToFunc)_cubic_to,
- 0, /* shift */
- 0, /* delta */
- };
- static const FT_Matrix invert_y = {
- DOUBLE_TO_16_16 (1.0), 0,
- 0, DOUBLE_TO_16_16 (-1.0),
- };
-
- FT_GlyphSlot glyph;
- cairo_path_fixed_t *path;
- cairo_status_t status;
-
- path = _cairo_path_fixed_create ();
- if (!path)
- return CAIRO_STATUS_NO_MEMORY;
-
- glyph = face->glyph;
-
- /* Font glyphs have an inverted Y axis compared to cairo. */
- FT_Outline_Transform (&glyph->outline, &invert_y);
- if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
- _cairo_path_fixed_destroy (path);
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- status = _cairo_path_fixed_close_path (path);
- if (status) {
- _cairo_path_fixed_destroy (path);
- return status;
- }
-
- *pathp = path;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/*
- * Translate glyph to match its metrics.
- */
-static void
-_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font,
- FT_GlyphSlot glyph)
-{
- cairo_ft_scaled_font_t *scaled_font = abstract_font;
- FT_Vector vector;
-
- vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
- vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
-
- if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
- FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape);
- FT_Outline_Translate(&glyph->outline, vector.x, vector.y);
- } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
- glyph->bitmap_left += vector.x / 64;
- glyph->bitmap_top += vector.y / 64;
- }
-}
-
-static cairo_int_status_t
-_cairo_ft_scaled_glyph_init (void *abstract_font,
- cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_glyph_info_t info)
-{
- cairo_text_extents_t fs_metrics;
- cairo_ft_scaled_font_t *scaled_font = abstract_font;
- cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
- FT_GlyphSlot glyph;
- FT_Face face;
- FT_Error error;
- int load_flags = scaled_font->ft_options.load_flags;
- FT_Glyph_Metrics *metrics;
- double x_factor, y_factor;
- cairo_bool_t vertical_layout = FALSE;
- cairo_status_t status;
-
- face = _cairo_ft_unscaled_font_lock_face (unscaled);
- if (!face)
- return CAIRO_STATUS_NO_MEMORY;
-
- status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
- &scaled_font->base.scale);
- if (status)
- goto FAIL;
-
- /* Ignore global advance unconditionally */
- load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
-
- if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
- (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)
- load_flags |= FT_LOAD_NO_BITMAP;
-
- /*
- * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as
- * suggested by freetype people.
- */
- if (load_flags & FT_LOAD_VERTICAL_LAYOUT) {
- load_flags &= ~FT_LOAD_VERTICAL_LAYOUT;
- vertical_layout = TRUE;
- }
-
- error = FT_Load_Glyph (scaled_font->unscaled->face,
- _cairo_scaled_glyph_index(scaled_glyph),
- load_flags);
-
- if (error) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto FAIL;
- }
-
- glyph = face->glyph;
-
-#if HAVE_FT_GLYPHSLOT_EMBOLDEN
- /*
- * embolden glyphs if requested
- */
- if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
- FT_GlyphSlot_Embolden (glyph);
-#endif
-
- if (vertical_layout)
- _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
-
- if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
-
- cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
- /*
- * Compute font-space metrics
- */
- metrics = &glyph->metrics;
-
- if (unscaled->x_scale == 0)
- x_factor = 0;
- else
- x_factor = 1 / unscaled->x_scale;
-
- if (unscaled->y_scale == 0)
- y_factor = 0;
- else
- y_factor = 1 / unscaled->y_scale;
-
- /*
- * Note: Y coordinates of the horizontal bearing need to be negated.
- *
- * Scale metrics back to glyph space from the scaled glyph space returned
- * by FreeType
- *
- * If we want hinted metrics but aren't asking for hinted glyphs from
- * FreeType, then we need to do the metric hinting ourselves.
- */
-
- if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING))
- {
- FT_Pos x1, x2;
- FT_Pos y1, y2;
- FT_Pos advance;
-
- if (!vertical_layout) {
- x1 = (metrics->horiBearingX) & -64;
- x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
- y1 = (-metrics->horiBearingY) & -64;
- y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
-
- advance = ((metrics->horiAdvance + 32) & -64);
-
- fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
- fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
-
- fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
- fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
-
- fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor;
- fs_metrics.y_advance = 0;
- } else {
- x1 = (metrics->vertBearingX) & -64;
- x2 = (metrics->vertBearingX + metrics->width + 63) & -64;
- y1 = (metrics->vertBearingY) & -64;
- y2 = (metrics->vertBearingY + metrics->height + 63) & -64;
-
- advance = ((metrics->vertAdvance + 32) & -64);
-
- fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
- fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
-
- fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
- fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
-
- fs_metrics.x_advance = 0;
- fs_metrics.y_advance = DOUBLE_FROM_26_6 (advance) * y_factor;
- }
- } else {
- fs_metrics.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor;
- fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor;
-
- if (!vertical_layout) {
- fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
- fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor;
-
- if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
- fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
- else
- fs_metrics.x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor;
- fs_metrics.y_advance = 0 * y_factor;
- } else {
- fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor;
- fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor;
-
- fs_metrics.x_advance = 0 * x_factor;
- if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
- fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
- else
- fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor;
- }
- }
-
- _cairo_scaled_glyph_set_metrics (scaled_glyph,
- &scaled_font->base,
- &fs_metrics);
- }
-
- if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
- cairo_image_surface_t *surface;
-
- if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
- status = _render_glyph_outline (face, &scaled_font->ft_options.base,
- &surface);
- } else {
- status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
- &surface);
- 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;
-
- _cairo_scaled_glyph_set_surface (scaled_glyph,
- &scaled_font->base,
- surface);
- }
-
- if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
- cairo_path_fixed_t *path;
-
- /*
- * A kludge -- the above code will trash the outline,
- * so reload it. This will probably never occur though
- */
- if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
- error = FT_Load_Glyph (face,
- _cairo_scaled_glyph_index(scaled_glyph),
- load_flags | FT_LOAD_NO_BITMAP);
-
- 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
- /*
- * embolden glyphs if requested
- */
- if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
- FT_GlyphSlot_Embolden (glyph);
-#endif
- if (vertical_layout)
- _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
-
- }
- if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
- status = _decompose_glyph_outline (face, &scaled_font->ft_options.base,
- &path);
- else
- status = CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (status)
- goto FAIL;
-
- _cairo_scaled_glyph_set_path (scaled_glyph,
- &scaled_font->base,
- path);
- }
- FAIL:
- _cairo_ft_unscaled_font_unlock_face (unscaled);
-
- return status;
-}
-
-static unsigned long
-_cairo_ft_ucs4_to_index (void *abstract_font,
- uint32_t ucs4)
-{
- cairo_ft_scaled_font_t *scaled_font = abstract_font;
- cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
- FT_Face face;
- FT_UInt index;
-
- face = _cairo_ft_unscaled_font_lock_face (unscaled);
- if (!face)
- return 0;
- index = FT_Get_Char_Index (face, ucs4);
- _cairo_ft_unscaled_font_unlock_face (unscaled);
- return index;
-}
-
-static cairo_int_status_t
-_cairo_ft_load_truetype_table (void *abstract_font,
- unsigned long tag,
- long offset,
- unsigned char *buffer,
- unsigned long *length)
-{
- cairo_ft_scaled_font_t *scaled_font = abstract_font;
- cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
- FT_Face face;
- cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
-#if HAVE_FT_LOAD_SFNT_TABLE
- face = _cairo_ft_unscaled_font_lock_face (unscaled);
- if (!face)
- return CAIRO_STATUS_NO_MEMORY;
-
- if (FT_IS_SFNT (face) &&
- FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0)
- status = CAIRO_STATUS_SUCCESS;
-
- _cairo_ft_unscaled_font_unlock_face (unscaled);
-#endif
-
- return status;
-}
-
-static void
-_cairo_ft_map_glyphs_to_unicode (void *abstract_font,
- cairo_scaled_font_subset_t *font_subset)
-{
- cairo_ft_scaled_font_t *scaled_font = abstract_font;
- cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
- FT_Face face;
- FT_UInt glyph;
- unsigned long charcode;
- unsigned int i;
- int count;
-
- face = _cairo_ft_unscaled_font_lock_face (unscaled);
- if (!face)
- return;
-
- count = font_subset->num_glyphs;
- charcode = FT_Get_First_Char( face, &glyph);
- while (glyph != 0 && count > 0)
- {
- for (i = 0; i < font_subset->num_glyphs; i++) {
- if (font_subset->glyphs[i] == glyph) {
- font_subset->to_unicode[i] = charcode;
- count--;
- break;
- }
- }
- charcode = FT_Get_Next_Char(face, charcode, &glyph);
- }
- _cairo_ft_unscaled_font_unlock_face (unscaled);
-}
-
-const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
- CAIRO_FONT_TYPE_FT,
- _cairo_ft_scaled_font_create_toy,
- _cairo_ft_scaled_font_fini,
- _cairo_ft_scaled_glyph_init,
- NULL, /* text_to_glyphs */
- _cairo_ft_ucs4_to_index,
- NULL, /* show_glyphs */
- _cairo_ft_load_truetype_table,
- _cairo_ft_map_glyphs_to_unicode,
-};
-
-/* cairo_ft_font_face_t */
-
-static void
-_cairo_ft_font_face_destroy (void *abstract_face)
-{
- cairo_ft_font_face_t *font_face = abstract_face;
-
- cairo_ft_font_face_t *tmp_face = NULL;
- cairo_ft_font_face_t *last_face = NULL;
-
- if (font_face == NULL)
- return;
-
- /* When destroying the face created by cairo_ft_font_face_create_for_ft_face,
- * we have a special "zombie" state for the face when the unscaled font
- * is still alive but there are no public references to the font face.
- *
- * We go from:
- *
- * font_face ------> unscaled
- * <-....weak....../
- *
- * To:
- *
- * font_face <------- unscaled
- */
-
- if (font_face->unscaled &&
- font_face->unscaled->from_face &&
- font_face->unscaled->base.ref_count > 1)
- {
- cairo_font_face_reference (&font_face->base);
-
- _cairo_unscaled_font_destroy (&font_face->unscaled->base);
- font_face->unscaled = NULL;
-
- return;
- }
-
- if (font_face->unscaled) {
- /* Remove face from linked list */
- for (tmp_face = font_face->unscaled->faces;
- tmp_face;
- tmp_face = tmp_face->next)
- {
- if (tmp_face == font_face) {
- if (last_face)
- last_face->next = tmp_face->next;
- else
- font_face->unscaled->faces = tmp_face->next;
- }
-
- last_face = tmp_face;
- }
-
- _cairo_unscaled_font_destroy (&font_face->unscaled->base);
- font_face->unscaled = NULL;
- }
-}
-
-static cairo_status_t
-_cairo_ft_font_face_scaled_font_create (void *abstract_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_ft_font_face_t *font_face = abstract_face;
- cairo_ft_options_t ft_options;
-
- /* The handling of font options is different depending on how the
- * font face was created. When the user creates a font face with
- * cairo_ft_font_face_create_for_ft_face(), then the load flags
- * passed in augment the load flags for the options. But for
- * cairo_ft_font_face_create_for_pattern(), the load flags are
- * derived from a pattern where the user has called
- * cairo_ft_font_options_substitute(), so *just* use those load
- * flags and ignore the options.
- */
-
- ft_options = font_face->ft_options;
-
- *scaled_font = _cairo_ft_scaled_font_create (font_face->unscaled,
- &font_face->base,
- font_matrix, ctm,
- options, ft_options);
- if (*scaled_font) {
- return CAIRO_STATUS_SUCCESS;
- } 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,
- _cairo_ft_font_face_destroy,
- _cairo_ft_font_face_scaled_font_create
-};
-
-static cairo_font_face_t *
-_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
- cairo_ft_options_t *ft_options)
-{
- cairo_ft_font_face_t *font_face, **prev_font_face;
-
- /* Looked for an existing matching font face */
- for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
- font_face;
- 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) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
-
- font_face->unscaled = unscaled;
- _cairo_unscaled_font_reference (&unscaled->base);
-
- font_face->ft_options = *ft_options;
-
- font_face->next = unscaled->faces;
- unscaled->faces = font_face;
-
- _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
-
- return &font_face->base;
-}
-
-/* implement the platform-specific interface */
-
-/**
- * cairo_ft_font_options_substitute:
- * @options: a #cairo_font_options_t object
- * @pattern: an existing #FcPattern
- *
- * Add options to a #FcPattern based on a #cairo_font_options_t font
- * options object. Options that are already in the pattern, are not overridden,
- * so you should call this function after calling FcConfigSubstitute() (the
- * user's settings should override options based on the surface type), but
- * before calling FcDefaultSubstitute().
- **/
-void
-cairo_ft_font_options_substitute (const cairo_font_options_t *options,
- FcPattern *pattern)
-{
- FcValue v;
-
- if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
- {
- if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddBool (pattern, FC_ANTIALIAS, options->antialias != CAIRO_ANTIALIAS_NONE);
- if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
- FcPatternDel (pattern, FC_RGBA);
- FcPatternAddInteger (pattern, FC_RGBA, FC_RGBA_NONE);
- }
- }
- }
-
- if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
- {
- if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
- {
- int rgba;
-
- if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
- switch (options->subpixel_order) {
- case CAIRO_SUBPIXEL_ORDER_DEFAULT:
- case CAIRO_SUBPIXEL_ORDER_RGB:
- default:
- rgba = FC_RGBA_RGB;
- break;
- case CAIRO_SUBPIXEL_ORDER_BGR:
- rgba = FC_RGBA_BGR;
- break;
- case CAIRO_SUBPIXEL_ORDER_VRGB:
- rgba = FC_RGBA_VRGB;
- break;
- case CAIRO_SUBPIXEL_ORDER_VBGR:
- rgba = FC_RGBA_VBGR;
- break;
- }
- } else {
- rgba = FC_RGBA_NONE;
- }
-
- FcPatternAddInteger (pattern, FC_RGBA, rgba);
- }
- }
-
- if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
- {
- if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
- {
- FcPatternAddBool (pattern, FC_HINTING, options->hint_style != CAIRO_HINT_STYLE_NONE);
- }
-
-#ifdef FC_HINT_STYLE
- if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
- {
- int hint_style;
-
- switch (options->hint_style) {
- case CAIRO_HINT_STYLE_NONE:
- hint_style = FC_HINT_NONE;
- break;
- case CAIRO_HINT_STYLE_SLIGHT:
- hint_style = FC_HINT_SLIGHT;
- break;
- case CAIRO_HINT_STYLE_MEDIUM:
- hint_style = FC_HINT_MEDIUM;
- break;
- case CAIRO_HINT_STYLE_FULL:
- case CAIRO_HINT_STYLE_DEFAULT:
- default:
- hint_style = FC_HINT_FULL;
- break;
- }
-
- FcPatternAddInteger (pattern, FC_HINT_STYLE, hint_style);
- }
-#endif
- }
-}
-slim_hidden_def (cairo_ft_font_options_substitute);
-
-/**
- * cairo_ft_font_face_create_for_pattern:
- * @pattern: A fully resolved fontconfig
- * pattern. A pattern can be resolved, by, among other things, calling
- * FcConfigSubstitute(), FcDefaultSubstitute(), then
- * FcFontMatch(). Cairo will call FcPatternReference() on this
- * pattern, so you should not further modify the pattern, but you can
- * release your reference to the pattern with FcPatternDestroy() if
- * you no longer need to access it.
- *
- * Creates a new font face for the FreeType font backend based on a
- * fontconfig pattern. 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 FreeType backend and can be used with functions such
- * as cairo_ft_font_lock_face().
- *
- * Font rendering options are represented both here and when you
- * call cairo_scaled_font_create(). Font options that have a representation
- * in a #FcPattern must be passed in here; to modify #FcPattern
- * appropriately to reflect the options in a #cairo_font_options_t, call
- * cairo_ft_font_options_substitute().
- *
- * 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_ft_font_face_create_for_pattern (FcPattern *pattern)
-{
- cairo_ft_unscaled_font_t *unscaled;
- cairo_font_face_t *font_face;
- cairo_ft_options_t ft_options;
-
- unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern);
- if (unscaled == NULL) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return (cairo_font_face_t *)&_cairo_font_face_nil;
- }
-
- _get_pattern_ft_options (pattern, &ft_options);
- font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
- _cairo_unscaled_font_destroy (&unscaled->base);
-
- if (font_face)
- return font_face;
- else
- return (cairo_font_face_t *)&_cairo_font_face_nil;
-}
-
-/**
- * cairo_ft_font_face_create_for_ft_face:
- * @face: A FreeType face object, already opened. This must
- * be kept around until the face's ref_count drops to
- * zero and it is freed. Since the face may be referenced
- * internally to Cairo, the best way to determine when it
- * is safe to free the face is to pass a
- * #cairo_destroy_func_t to cairo_font_face_set_user_data()
- * @load_flags: flags to pass to FT_Load_Glyph when loading
- * glyphs from the font. These flags are OR'ed together with
- * the flags derived from the #cairo_font_options_t passed
- * to cairo_scaled_font_create(), so only a few values such
- * as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
- * are useful. You should not pass any of the flags affecting
- * the load target, such as %FT_LOAD_TARGET_LIGHT.
- *
- * Creates a new font face for the FreeType font backend from a
- * pre-opened FreeType face. 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 FreeType backend and can be used with functions such
- * as cairo_ft_font_lock_face().
- *
- * 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_ft_font_face_create_for_ft_face (FT_Face face,
- int load_flags)
-{
- cairo_ft_unscaled_font_t *unscaled;
- cairo_font_face_t *font_face;
- cairo_ft_options_t ft_options;
-
- unscaled = _cairo_ft_unscaled_font_create_from_face (face);
- if (unscaled == NULL) {
- _cairo_error (CAIRO_STATUS_NO_MEMORY);
- return (cairo_font_face_t *)&_cairo_font_face_nil;
- }
-
- ft_options.load_flags = load_flags;
- ft_options.extra_flags = 0;
- _cairo_font_options_init_default (&ft_options.base);
-
- font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
- _cairo_unscaled_font_destroy (&unscaled->base);
-
- if (font_face)
- return font_face;
- else
- return (cairo_font_face_t *)&_cairo_font_face_nil;
-}
-
-/**
- * cairo_ft_scaled_font_lock_face:
- * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
- * object can be created by calling cairo_scaled_font_create() on a
- * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
- * cairo_ft_font_face_create_for_face()).
- *
- * cairo_ft_font_lock_face() gets the #FT_Face object from a FreeType
- * backend font and scales it appropriately for the font. You must
- * release the face with cairo_ft_font_unlock_face()
- * when you are done using it. Since the #FT_Face object can be
- * shared between multiple #cairo_scaled_font_t objects, you must not
- * lock any other font objects until you unlock this one. A count is
- * kept of the number of times cairo_ft_font_lock_face() is
- * called. cairo_ft_font_unlock_face() must be called the same number
- * of times.
- *
- * You must be careful when using this function in a library or in a
- * threaded application, because freetype's design makes it unsafe to
- * call freetype functions simultaneously from multiple threads, (even
- * if using distinct FT_Face objects). Because of this, application
- * code that acquires an FT_Face object with this call must add it's
- * own locking to protect any use of that object, (and which also must
- * protect any other calls into cairo as almost any cairo function
- * might result in a call into the freetype library).
- *
- * Return value: The #FT_Face object for @font, scaled appropriately,
- * or %NULL if @scaled_font is in an error state (see
- * cairo_scaled_font_status()) or there is insufficient memory.
- **/
-FT_Face
-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;
-
- face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
- if (face == NULL) {
- _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
-
- status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
- &scaled_font->base.scale);
- if (status) {
- _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
- _cairo_scaled_font_set_error (&scaled_font->base, status);
- return NULL;
- }
-
- /* NOTE: We deliberately release the unscaled font's mutex here,
- * so that we are not holding a lock across two separate calls to
- * cairo function, (which would give the application some
- * opportunity for creating deadlock. This is obviously unsafe,
- * but as documented, the user must add manual locking when using
- * this function. */
- CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex);
-
- return face;
-}
-
-/**
- * cairo_ft_scaled_font_unlock_face:
- * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
- * object can be created by calling cairo_scaled_font_create() on a
- * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
- * cairo_ft_font_face_create_for_ft_face()).
- *
- * Releases a face obtained with cairo_ft_scaled_font_lock_face().
- **/
-void
-cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
-{
- cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
-
- if (scaled_font->base.status)
- return;
-
- /* NOTE: We released the unscaled font's mutex at the end of
- * cairo_ft_scaled_font_lock_face, so we have to acquire it again
- * as _cairo_ft_unscaled_font_unlock_face expects it to be held
- * when we call into it. */
- CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex);
-
- _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
-}
-
-/* We expose our unscaled font implementation internally for the the
- * PDF backend, which needs to keep track of the the different
- * fonts-on-disk used by a document, so it can embed them.
- */
-cairo_unscaled_font_t *
-_cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *abstract_font)
-{
- cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
-
- return &scaled_font->unscaled->base;
-}
-
-cairo_bool_t
-_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font)
-{
- cairo_ft_scaled_font_t *ft_scaled_font;
-
- if (!_cairo_scaled_font_is_ft (scaled_font))
- return FALSE;
-
- ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
- if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)
- return TRUE;
- return FALSE;
-}
-
-void
-_cairo_ft_font_reset_static_data (void)
-{
- _cairo_ft_unscaled_font_map_destroy ();
-}
--- a/gfx/cairo/cairo/src/cairo-glitz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c
@@ -28,31 +28,31 @@
#include "cairo-glitz.h"
#include "cairo-glitz-private.h"
typedef struct _cairo_glitz_surface {
cairo_surface_t base;
glitz_surface_t *surface;
glitz_format_t *format;
- cairo_bool_t has_clip;
- pixman_region16_t clip;
+ pixman_region16_t *clip;
} cairo_glitz_surface_t;
static const cairo_surface_backend_t *
_cairo_glitz_surface_get_backend (void);
static cairo_status_t
_cairo_glitz_surface_finish (void *abstract_surface)
{
cairo_glitz_surface_t *surface = abstract_surface;
- if (surface->has_clip) {
- glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
- pixman_region_fini (&surface->clip);
+ if (surface->clip)
+ {
+ glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
+ pixman_region_destroy (surface->clip);
}
glitz_surface_destroy (surface->surface);
return CAIRO_STATUS_SUCCESS;
}
static glitz_format_name_t
@@ -203,35 +203,35 @@ static cairo_status_t
buffer = glitz_buffer_create_for_data (pixels);
if (!buffer) {
free (pixels);
return CAIRO_STATUS_NO_MEMORY;
}
/* clear out the glitz clip; the clip affects glitz_get_pixels */
- if (surface->has_clip)
+ if (surface->clip)
glitz_surface_set_clip_region (surface->surface,
0, 0, NULL, 0);
glitz_get_pixels (surface->surface,
x1, y1,
width, height,
&pf,
buffer);
glitz_buffer_destroy (buffer);
/* restore the clip, if any */
- if (surface->has_clip) {
+ if (surface->clip) {
glitz_box_t *box;
int n;
- box = (glitz_box_t *) pixman_region_rects (&surface->clip);
- n = pixman_region_num_rects (&surface->clip);
+ box = (glitz_box_t *) pixman_region_rects (surface->clip);
+ n = pixman_region_num_rects (surface->clip);
glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
}
image = (cairo_image_surface_t *)
_cairo_image_surface_create_with_masks (pixels,
&format,
width, height,
pf.bytes_per_line);
@@ -663,17 +663,17 @@ static cairo_int_status_t
(((int) (gradient->stops[i].color.blue >> 8)));
params[n_base_params + 3 * i + 0] = gradient->stops[i].x;
params[n_base_params + 3 * i + 1] = i << 16;
params[n_base_params + 3 * i + 2] = 0;
}
glitz_set_pixels (src->surface, 0, 0, gradient->n_stops, 1,
- (glitz_pixel_format_t *)&format, buffer);
+ &format, buffer);
glitz_buffer_destroy (buffer);
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR)
{
cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern;
params[0] = grad->gradient.p1.x;
@@ -817,43 +817,36 @@ static cairo_int_status_t
{
cairo_color_t combined;
cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
combined = src_solid->color;
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
- _cairo_pattern_init_solid (&tmp.solid, &combined,
- CAIRO_COLOR_IS_OPAQUE (&combined) ?
- CAIRO_CONTENT_COLOR :
- CAIRO_CONTENT_COLOR_ALPHA);
+ _cairo_pattern_init_solid (&tmp.solid, &combined);
mask = NULL;
} else {
- status = _cairo_pattern_init_copy (&tmp.base, src);
- if (status)
- return status;
+ _cairo_pattern_init_copy (&tmp.base, src);
}
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
src_x, src_y,
width, height,
src_out, sattr);
_cairo_pattern_fini (&tmp.base);
if (status)
return status;
if (mask)
{
- status = _cairo_pattern_init_copy (&tmp.base, mask);
- if (status)
- return status;
+ _cairo_pattern_init_copy (&tmp.base, mask);
status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
mask_x, mask_y,
width, height,
mask_out, mattr);
if (status)
_cairo_glitz_pattern_release_surface (&tmp.base, *src_out, sattr);
@@ -1004,18 +997,17 @@ static cairo_int_status_t
default:
if (_glitz_ensure_target (dst->surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
src = (cairo_glitz_surface_t *)
_cairo_surface_create_similar_solid (&dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
1, 1,
- (cairo_color_t *) color,
- NULL);
+ (cairo_color_t *) color);
if (src->base.status)
return CAIRO_STATUS_NO_MEMORY;
glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT);
while (n_rects--)
{
glitz_composite (_glitz_operator (op),
@@ -1074,19 +1066,17 @@ static cairo_int_status_t
if (op == CAIRO_OPERATOR_SATURATE)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (_glitz_ensure_target (dst->surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
{
- status = _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
- if (status)
- return status;
+ _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern);
status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base,
dst,
src_x, src_y,
width, height,
&src, &attributes);
src_pattern = &tmp_src_pattern.base;
}
@@ -1288,42 +1278,36 @@ static cairo_int_status_t
{
cairo_glitz_surface_t *surface = abstract_surface;
if (region)
{
glitz_box_t *box;
int n;
- if (!surface->has_clip) {
- pixman_region_init (&surface->clip);
- surface->has_clip = TRUE;
- }
+ if (!surface->clip)
+ {
+ surface->clip = pixman_region_create ();
+ if (!surface->clip)
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+ pixman_region_copy (surface->clip, region);
- if (pixman_region_copy (&surface->clip, region) !=
- PIXMAN_REGION_STATUS_SUCCESS)
- {
- pixman_region_fini (&surface->clip);
- surface->has_clip = FALSE;
- return CAIRO_STATUS_NO_MEMORY;
- }
-
- box = (glitz_box_t *) pixman_region_rects (&surface->clip);
- n = pixman_region_num_rects (&surface->clip);
-
+ box = (glitz_box_t *) pixman_region_rects (surface->clip);
+ n = pixman_region_num_rects (surface->clip);
glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
}
else
{
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
- if (surface->has_clip) {
- pixman_region_fini (&surface->clip);
- surface->has_clip = FALSE;
- }
+ if (surface->clip)
+ pixman_region_destroy (surface->clip);
+
+ surface->clip = NULL;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_glitz_surface_get_extents (void *abstract_surface,
cairo_rectangle_int16_t *rectangle)
@@ -2183,43 +2167,16 @@ static cairo_status_t
{
cairo_glitz_surface_t *surface = abstract_surface;
glitz_surface_flush (surface->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,
_cairo_glitz_surface_finish,
_cairo_glitz_surface_acquire_source_image,
_cairo_glitz_surface_release_source_image,
_cairo_glitz_surface_acquire_dest_image,
_cairo_glitz_surface_release_dest_image,
@@ -2232,28 +2189,17 @@ static const cairo_surface_backend_t cai
_cairo_glitz_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_glitz_surface_get_extents,
_cairo_glitz_surface_old_show_glyphs,
NULL, /* get_font_options */
_cairo_glitz_surface_flush,
NULL, /* mark_dirty_rectangle */
_cairo_glitz_surface_scaled_font_fini,
- _cairo_glitz_surface_scaled_glyph_fini,
-
- NULL, /* paint */
- NULL, /* mask */
- NULL, /* stroke */
- NULL, /* fill */
- NULL, /* show_glyphs */
-
- NULL, /* snapshot */
- _cairo_glitz_surface_is_similar,
-
- _cairo_glitz_surface_reset
+ _cairo_glitz_surface_scaled_glyph_fini
};
static const cairo_surface_backend_t *
_cairo_glitz_surface_get_backend (void)
{
return &cairo_glitz_surface_backend;
}
@@ -2289,15 +2235,15 @@ cairo_glitz_surface_create (glitz_surfac
}
format = glitz_surface_get_format (surface);
_cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend,
_glitz_format_to_content(format));
glitz_surface_reference (surface);
- crsurface->surface = surface;
- crsurface->format = format;
- crsurface->has_clip = FALSE;
+ crsurface->surface = surface;
+ crsurface->format = format;
+ crsurface->clip = NULL;
return (cairo_surface_t *) crsurface;
}
slim_hidden_def (cairo_glitz_surface_create);
--- a/gfx/cairo/cairo/src/cairo-gstate.c
+++ b/gfx/cairo/cairo/src/cairo-gstate.c
@@ -30,16 +30,18 @@
*
* The Initial Developer of the Original Code is University of Southern
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
+#include <stdlib.h>
+
#include "cairoint.h"
#include "cairo-clip-private.h"
#include "cairo-gstate-private.h"
static cairo_status_t
_cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other);
@@ -57,18 +59,16 @@ static void
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_glyph_t *transformed_glyphs);
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;
gstate->antialias = CAIRO_ANTIALIAS_DEFAULT;
_cairo_stroke_style_init (&gstate->stroke_style);
gstate->fill_rule = CAIRO_GSTATE_FILL_RULE_DEFAULT;
@@ -86,22 +86,23 @@ cairo_status_t
gstate->target = cairo_surface_reference (target);
gstate->parent_target = NULL;
gstate->original_target = cairo_surface_reference (target);
_cairo_gstate_identity_matrix (gstate);
gstate->source_ctm_inverse = gstate->ctm_inverse;
- gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK,
- CAIRO_CONTENT_COLOR);
+ gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
if (gstate->source->status)
return CAIRO_STATUS_NO_MEMORY;
- return target ? target->status : CAIRO_STATUS_NULL_POINTER;
+ gstate->next = NULL;
+
+ return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_gstate_init_copy:
*
* Initialize @gstate by performing a deep copy of state fields from
* @other. Note that gstate->next is not copied but is set to NULL by
* this function.
@@ -125,19 +126,17 @@ static cairo_status_t
gstate->font_face = cairo_font_face_reference (other->font_face);
gstate->scaled_font = cairo_scaled_font_reference (other->scaled_font);
gstate->font_matrix = other->font_matrix;
_cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
- status = _cairo_clip_init_copy (&gstate->clip, &other->clip);
- if (status)
- return status;
+ _cairo_clip_init_copy (&gstate->clip, &other->clip);
gstate->target = cairo_surface_reference (other->target);
/* parent_target is always set to NULL; it's only ever set by redirect_target */
gstate->parent_target = NULL;
gstate->original_target = cairo_surface_reference (other->original_target);
gstate->ctm = other->ctm;
gstate->ctm_inverse = other->ctm_inverse;
@@ -156,32 +155,32 @@ void
_cairo_stroke_style_fini (&gstate->stroke_style);
cairo_font_face_destroy (gstate->font_face);
gstate->font_face = NULL;
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
- _cairo_clip_reset (&gstate->clip);
+ _cairo_clip_fini (&gstate->clip);
cairo_surface_destroy (gstate->target);
gstate->target = NULL;
cairo_surface_destroy (gstate->parent_target);
gstate->parent_target = NULL;
cairo_surface_destroy (gstate->original_target);
gstate->target = NULL;
cairo_pattern_destroy (gstate->source);
gstate->source = NULL;
}
-static void
+void
_cairo_gstate_destroy (cairo_gstate_t *gstate)
{
if (gstate == NULL)
return;
_cairo_gstate_fini (gstate);
free (gstate);
}
@@ -193,17 +192,17 @@ static void
* Create a new #cairo_gstate_t setting all graphics state parameters
* to the same values as contained in @other. gstate->next will be set
* to NULL and may be used by the caller to chain cairo_gstate_t
* objects together.
*
* Return value: a new cairo_gstate_t or NULL if there is insufficient
* memory.
**/
-static cairo_gstate_t*
+cairo_gstate_t*
_cairo_gstate_clone (cairo_gstate_t *other)
{
cairo_status_t status;
cairo_gstate_t *gstate;
assert (other != NULL);
gstate = malloc (sizeof (cairo_gstate_t));
@@ -214,65 +213,16 @@ static cairo_gstate_t*
if (status) {
free (gstate);
return NULL;
}
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)
{
cairo_status_t status;
if (cpath == NULL)
return CAIRO_STATUS_SUCCESS;
@@ -297,47 +247,41 @@ static cairo_status_t
* Redirect @gstate rendering to a "child" target. The original
* "parent" target with which the gstate was created will not be
* affected. See _cairo_gstate_get_target().
*
* Unless the redirected target has the same device offsets as the
* original #cairo_t target, the clip will be INVALID after this call,
* and the caller should either recreate or reset the clip.
**/
-cairo_status_t
+void
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
{
- cairo_status_t status;
-
/* If this gstate is already redirected, this is an error; we need a
* new gstate to be able to redirect */
assert (gstate->parent_target == NULL);
/* Set up our new parent_target based on our current target;
* gstate->parent_target will take the ref that is held by gstate->target
*/
cairo_surface_destroy (gstate->parent_target);
gstate->parent_target = gstate->target;
/* Now set up our new target; we overwrite gstate->target directly,
* since its ref is now owned by gstate->parent_target */
gstate->target = cairo_surface_reference (child);
- _cairo_clip_reset (&gstate->clip);
- status = _cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
- if (status)
- return status;
+ _cairo_clip_fini (&gstate->clip);
+ _cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
/* The clip is in surface backend coordinates for the previous target;
* translate it into the child's backend coordinates. */
_cairo_clip_translate (&gstate->clip,
_cairo_fixed_from_double (child->device_transform.x0 - gstate->parent_target->device_transform.x0),
_cairo_fixed_from_double (child->device_transform.y0 - gstate->parent_target->device_transform.y0));
-
- return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_gstate_is_redirected
* @gstate: a #cairo_gstate_t
*
* Return value: TRUE if the gstate is redirected to a target
* different than the original, FALSE otherwise.
@@ -407,17 +351,17 @@ cairo_clip_t *
cairo_status_t
_cairo_gstate_set_source (cairo_gstate_t *gstate,
cairo_pattern_t *source)
{
if (source->status)
return source->status;
- source = cairo_pattern_reference (source);
+ cairo_pattern_reference (source);
cairo_pattern_destroy (gstate->source);
gstate->source = source;
gstate->source_ctm_inverse = gstate->ctm_inverse;
return CAIRO_STATUS_SUCCESS;
}
cairo_pattern_t *
@@ -558,34 +502,16 @@ cairo_status_t
if (offset < 0)
offset += ceil (-offset / dash_total + 0.5) * dash_total;
gstate->stroke_style.dash_offset = offset;
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)
{
gstate->stroke_style.miter_limit = limit;
return CAIRO_STATUS_SUCCESS;
}
@@ -652,26 +578,23 @@ cairo_status_t
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_transform (cairo_gstate_t *gstate,
const cairo_matrix_t *matrix)
{
cairo_matrix_t tmp;
- cairo_status_t status;
_cairo_gstate_unset_scaled_font (gstate);
tmp = *matrix;
cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
- status = cairo_matrix_invert (&tmp);
- if (status)
- return status;
+ cairo_matrix_invert (&tmp);
cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_set_matrix (cairo_gstate_t *gstate,
const cairo_matrix_t *matrix)
@@ -685,49 +608,59 @@ cairo_status_t
gstate->ctm_inverse = *matrix;
status = cairo_matrix_invert (&gstate->ctm_inverse);
if (status)
return status;
return CAIRO_STATUS_SUCCESS;
}
-void
+cairo_status_t
_cairo_gstate_identity_matrix (cairo_gstate_t *gstate)
{
_cairo_gstate_unset_scaled_font (gstate);
cairo_matrix_init_identity (&gstate->ctm);
cairo_matrix_init_identity (&gstate->ctm_inverse);
+
+ return CAIRO_STATUS_SUCCESS;
}
-void
+cairo_status_t
_cairo_gstate_user_to_device (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm, x, y);
+
+ return CAIRO_STATUS_SUCCESS;
}
-void
+cairo_status_t
_cairo_gstate_user_to_device_distance (cairo_gstate_t *gstate,
double *dx, double *dy)
{
cairo_matrix_transform_distance (&gstate->ctm, dx, dy);
+
+ return CAIRO_STATUS_SUCCESS;
}
-void
+cairo_status_t
_cairo_gstate_device_to_user (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
+
+ return CAIRO_STATUS_SUCCESS;
}
-void
+cairo_status_t
_cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate,
double *dx, double *dy)
{
cairo_matrix_transform_distance (&gstate->ctm_inverse, dx, dy);
+
+ return CAIRO_STATUS_SUCCESS;
}
void
_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
{
cairo_matrix_transform_point (&gstate->ctm, x, y);
cairo_matrix_transform_point (&gstate->target->device_transform, x, y);
}
@@ -759,77 +692,70 @@ cairo_status_t
{
cairo_status_t status;
_cairo_pen_init (&gstate);
return CAIRO_STATUS_SUCCESS;
}
*/
-static cairo_status_t
+static void
_cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_pattern_t *original,
cairo_matrix_t *ctm_inverse)
{
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) {
surface_pattern = (cairo_surface_pattern_t *) original;
surface = surface_pattern->surface;
if (_cairo_surface_has_device_transform (surface))
_cairo_pattern_transform (pattern, &surface->device_transform);
}
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
_cairo_gstate_copy_transformed_source (cairo_gstate_t *gstate,
cairo_pattern_t *pattern)
{
- return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
- gstate->source,
- &gstate->source_ctm_inverse);
+ _cairo_gstate_copy_transformed_pattern (gstate, pattern,
+ gstate->source,
+ &gstate->source_ctm_inverse);
}
-static cairo_status_t
+static void
_cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate,
cairo_pattern_t *pattern,
cairo_pattern_t *mask)
{
- return _cairo_gstate_copy_transformed_pattern (gstate, pattern,
- mask,
- &gstate->ctm_inverse);
+ _cairo_gstate_copy_transformed_pattern (gstate, pattern,
+ mask,
+ &gstate->ctm_inverse);
}
cairo_status_t
_cairo_gstate_paint (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_pattern_union_t pattern;
if (gstate->source->status)
return gstate->source->status;
status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
if (status)
return status;
- status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
- if (status)
- return status;
+ _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
status = _cairo_surface_paint (gstate->target,
gstate->op,
&pattern.base);
_cairo_pattern_fini (&pattern.base);
return status;
@@ -926,32 +852,26 @@ cairo_status_t
if (gstate->source->status)
return gstate->source->status;
status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
if (status)
return status;
- status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
- if (status)
- return status;
-
- status = _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
- if (status)
- goto CLEANUP_SOURCE;
+ _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
+ _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
status = _cairo_surface_mask (gstate->target,
gstate->op,
&source_pattern.base,
&mask_pattern.base);
+ _cairo_pattern_fini (&source_pattern.base);
_cairo_pattern_fini (&mask_pattern.base);
-CLEANUP_SOURCE:
- _cairo_pattern_fini (&source_pattern.base);
return status;
}
cairo_status_t
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_status_t status;
@@ -962,20 +882,17 @@ cairo_status_t
if (gstate->stroke_style.line_width <= 0.0)
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
if (status)
return status;
- status = _cairo_gstate_copy_transformed_source (gstate,
- &source_pattern.base);
- if (status)
- return status;
+ _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
status = _cairo_surface_stroke (gstate->target,
gstate->op,
&source_pattern.base,
path,
&gstate->stroke_style,
&gstate->ctm,
&gstate->ctm_inverse,
@@ -1032,19 +949,17 @@ cairo_status_t
if (gstate->source->status)
return gstate->source->status;
status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
if (status)
return status;
- status = _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
- if (status)
- return status;
+ _cairo_gstate_copy_transformed_source (gstate, &pattern.base);
status = _cairo_surface_fill (gstate->target,
gstate->op,
&pattern.base,
path,
gstate->fill_rule,
gstate->tolerance,
gstate->antialias);
@@ -1081,23 +996,39 @@ BAIL:
_cairo_traps_fini (&traps);
return status;
}
cairo_status_t
_cairo_gstate_copy_page (cairo_gstate_t *gstate)
{
- return _cairo_surface_copy_page (gstate->target);
+ cairo_int_status_t status;
+
+ status = _cairo_surface_copy_page (gstate->target);
+
+ /* It's fine if some surfaces just don't support this. */
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+ return CAIRO_STATUS_SUCCESS;
+
+ return status;
}
cairo_status_t
_cairo_gstate_show_page (cairo_gstate_t *gstate)
{
- return _cairo_surface_show_page (gstate->target);
+ cairo_int_status_t status;
+
+ status = _cairo_surface_show_page (gstate->target);
+
+ /* It's fine if some surfaces just don't support this. */
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED)
+ return CAIRO_STATUS_SUCCESS;
+
+ return status;
}
static void
_cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate,
cairo_traps_t *traps,
double *x1, double *y1,
double *x2, double *y2)
{
@@ -1189,19 +1120,17 @@ cairo_status_t
_cairo_traps_fini (&traps);
return status;
}
cairo_status_t
_cairo_gstate_reset_clip (cairo_gstate_t *gstate)
{
- _cairo_clip_reset (&gstate->clip);
-
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_clip_reset (&gstate->clip);
}
cairo_status_t
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
return _cairo_clip_clip (&gstate->clip,
path, gstate->fill_rule, gstate->tolerance,
gstate->antialias, gstate->target);
@@ -1256,25 +1185,22 @@ static void
cairo_status_t
_cairo_gstate_select_font_face (cairo_gstate_t *gstate,
const char *family,
cairo_font_slant_t slant,
cairo_font_weight_t weight)
{
cairo_font_face_t *font_face;
- cairo_status_t status;
font_face = _cairo_toy_font_face_create (family, slant, weight);
if (font_face->status)
return font_face->status;
- status = _cairo_gstate_set_font_face (gstate, font_face);
- if (status)
- return status;
+ _cairo_gstate_set_font_face (gstate, font_face);
cairo_font_face_destroy (font_face);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_set_font_size (cairo_gstate_t *gstate,
double size)
@@ -1299,23 +1225,25 @@ cairo_status_t
void
_cairo_gstate_get_font_matrix (cairo_gstate_t *gstate,
cairo_matrix_t *matrix)
{
*matrix = gstate->font_matrix;
}
-void
+cairo_status_t
_cairo_gstate_set_font_options (cairo_gstate_t *gstate,
const cairo_font_options_t *options)
{
_cairo_gstate_unset_scaled_font (gstate);
gstate->font_options = *options;
+
+ return CAIRO_STATUS_SUCCESS;
}
void
_cairo_gstate_get_font_options (cairo_gstate_t *gstate,
cairo_font_options_t *options)
{
*options = gstate->font_options;
}
@@ -1424,93 +1352,92 @@ cairo_status_t
* CTM (for user-input glyph vectors), and return values by the CTM inverse
* (for font responses such as metrics or glyph vectors).
*
*/
static cairo_status_t
_cairo_gstate_ensure_font_face (cairo_gstate_t *gstate)
{
- cairo_font_face_t *font_face;
-
- if (gstate->font_face != NULL)
- return gstate->font_face->status;
-
+ if (!gstate->font_face) {
+ cairo_font_face_t *font_face;
- font_face = _cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
- CAIRO_FONT_SLANT_DEFAULT,
- CAIRO_FONT_WEIGHT_DEFAULT);
- if (font_face->status)
- return font_face->status;
-
- gstate->font_face = font_face;
+ font_face = _cairo_toy_font_face_create (CAIRO_FONT_FAMILY_DEFAULT,
+ CAIRO_FONT_SLANT_DEFAULT,
+ CAIRO_FONT_WEIGHT_DEFAULT);
+ if (font_face->status)
+ return font_face->status;
+ else
+ gstate->font_face = font_face;
+ }
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate)
{
cairo_status_t status;
cairo_font_options_t options;
- cairo_scaled_font_t *scaled_font;
- if (gstate->scaled_font != NULL)
- return gstate->scaled_font->status;
+ if (gstate->scaled_font)
+ return CAIRO_STATUS_SUCCESS;
status = _cairo_gstate_ensure_font_face (gstate);
if (status)
return status;
cairo_surface_get_font_options (gstate->target, &options);
cairo_font_options_merge (&options, &gstate->font_options);
- scaled_font = cairo_scaled_font_create (gstate->font_face,
- &gstate->font_matrix,
- &gstate->ctm,
- &options);
+ gstate->scaled_font = cairo_scaled_font_create (gstate->font_face,
+ &gstate->font_matrix,
+ &gstate->ctm,
+ &options);
- status = cairo_scaled_font_status (scaled_font);
- if (status)
- return status;
-
- gstate->scaled_font = scaled_font;
+ if (!gstate->scaled_font)
+ return CAIRO_STATUS_NO_MEMORY;
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
cairo_font_extents_t *extents)
{
cairo_status_t status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
cairo_scaled_font_extents (gstate->scaled_font, extents);
- return cairo_scaled_font_status (gstate->scaled_font);
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
const char *utf8,
double x,
double y,
cairo_glyph_t **glyphs,
int *num_glyphs)
{
cairo_status_t status;
status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
- return _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
- utf8, glyphs, num_glyphs);
+ status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
+ utf8, glyphs, num_glyphs);
+
+ if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs))
+ return status;
+
+ return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_gstate_set_font_face (cairo_gstate_t *gstate,
cairo_font_face_t *font_face)
{
if (font_face && font_face->status)
return font_face->status;
@@ -1536,17 +1463,17 @@ cairo_status_t
status = _cairo_gstate_ensure_scaled_font (gstate);
if (status)
return status;
cairo_scaled_font_glyph_extents (gstate->scaled_font,
glyphs, num_glyphs,
extents);
- return cairo_scaled_font_status (gstate->scaled_font);
+ return CAIRO_STATUS_SUCCESS;
}
#define STACK_GLYPHS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (cairo_glyph_t)))
cairo_status_t
_cairo_gstate_show_glyphs (cairo_gstate_t *gstate,
const cairo_glyph_t *glyphs,
int num_glyphs)
{
@@ -1573,30 +1500,27 @@ cairo_status_t
transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
if (transformed_glyphs == NULL)
return CAIRO_STATUS_NO_MEMORY;
}
_cairo_gstate_transform_glyphs_to_backend (gstate, glyphs, num_glyphs,
transformed_glyphs);
- status = _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
- if (status)
- goto CLEANUP_GLYPHS;
+ _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
status = _cairo_surface_show_glyphs (gstate->target,
gstate->op,
&source_pattern.base,
transformed_glyphs,
num_glyphs,
gstate->scaled_font);
_cairo_pattern_fini (&source_pattern.base);
-CLEANUP_GLYPHS:
if (transformed_glyphs != stack_transformed_glyphs)
free (transformed_glyphs);
return status;
}
cairo_status_t
_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
--- a/gfx/cairo/cairo/src/cairo-hash-private.h
+++ b/gfx/cairo/cairo/src/cairo-hash-private.h
@@ -34,23 +34,61 @@
* Keith Packard <keithp@keithp.com>
* Graydon Hoare <graydon@redhat.com>
* Carl Worth <cworth@cworth.org>
*/
#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);
typedef cairo_bool_t
(*cairo_hash_predicate_func_t) (void *entry);
typedef void
(*cairo_hash_callback_func_t) (void *entry,
--- a/gfx/cairo/cairo/src/cairo-hash.c
+++ b/gfx/cairo/cairo/src/cairo-hash.c
@@ -110,17 +110,17 @@ static const cairo_hash_table_arrangemen
{ 8388608, 18455029, 18455027 },
{ 16777216, 36911011, 36911009 },
{ 33554432, 73819861, 73819859 },
{ 67108864, 147639589, 147639587 },
{ 134217728, 295279081, 295279079 },
{ 268435456, 590559793, 590559791 }
};
-#define NUM_HASH_TABLE_ARRANGEMENTS ARRAY_LENGTH (hash_table_arrangements)
+#define NUM_HASH_TABLE_ARRANGEMENTS ((int)(sizeof(hash_table_arrangements)/sizeof(hash_table_arrangements[0])))
struct _cairo_hash_table {
cairo_hash_keys_equal_func_t keys_equal;
const cairo_hash_table_arrangement_t *arrangement;
cairo_hash_entry_t **entries;
unsigned long live_entries;
@@ -476,22 +476,18 @@ cairo_status_t
/* User is being bad, let's crash. */
ASSERT_NOT_REACHED;
}
*entry = key_and_value;
hash_table->live_entries++;
status = _cairo_hash_table_resize (hash_table);
- if (status) {
- /* abort the insert... */
- *entry = DEAD_ENTRY;
- hash_table->live_entries--;
+ if (status)
return status;
- }
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_hash_table_remove:
* @hash_table: a hash table
* @key: key of entry to be removed
@@ -560,14 +556,11 @@ void
entry = hash_table->entries[i];
if (ENTRY_IS_LIVE(entry))
hash_callback (entry, closure);
}
/* If some elements were deleted during the iteration,
* the table may need resizing. Just do this every time
* as the check is inexpensive.
*/
- if (--hash_table->iterating == 0) {
- /* Should we fail to shrink the hash table, it is left unaltered,
- * and we don't need to propagate the error status. */
+ if (--hash_table->iterating == 0)
_cairo_hash_table_resize (hash_table);
- }
}
--- a/gfx/cairo/cairo/src/cairo-image-surface.c
+++ b/gfx/cairo/cairo/src/cairo-image-surface.c
@@ -31,17 +31,17 @@
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
*/
#include "cairoint.h"
-static const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
+const cairo_image_surface_t _cairo_image_surface_nil_invalid_format = {
{
&cairo_image_surface_backend, /* backend */
CAIRO_SURFACE_TYPE_IMAGE,
CAIRO_CONTENT_COLOR,
CAIRO_REF_COUNT_INVALID, /* ref_count */
CAIRO_STATUS_INVALID_FORMAT, /* status */
FALSE, /* finished */
{ 0, /* size */
@@ -126,17 +126,17 @@ cairo_surface_t *
surface->stride = pixman_image_get_stride (pixman_image);
surface->depth = pixman_image_get_depth (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_internal_format_t
+static cairo_format_t
_cairo_format_from_pixman_format (pixman_format_t *pixman_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. */
@@ -162,17 +162,17 @@ static cairo_internal_format_t
return CAIRO_INTERNAL_FORMAT_BGR24;
}
break;
case 16:
if (am == 0x0 &&
rm == 0xf800 &&
gm == 0x07e0 &&
bm == 0x001f)
- return CAIRO_INTERNAL_FORMAT_RGB16_565;
+ return CAIRO_FORMAT_RGB16_565;
break;
case 8:
if (am == 0xff &&
rm == 0x0 &&
gm == 0x0 &&
bm == 0x0)
return CAIRO_FORMAT_A8;
break;
@@ -207,67 +207,67 @@ static cairo_internal_format_t
cairo_surface_t *
_cairo_image_surface_create_with_masks (unsigned char *data,
cairo_format_masks_t *format,
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;
+ pixman_format_t *pixman_format;
+ pixman_image_t *pixman_image;
+ cairo_format_t cairo_format;
+
+ pixman_format = pixman_format_create_masks (format->bpp,
+ format->alpha_mask,
+ format->red_mask,
+ format->green_mask,
+ format->blue_mask);
- pixman_format_init_masks (&pixman_format,
- format->bpp,
- format->alpha_mask,
- format->red_mask,
- format->green_mask,
- format->blue_mask);
+ if (pixman_format == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
- cairo_format = _cairo_format_from_pixman_format (&pixman_format);
+ cairo_format = _cairo_format_from_pixman_format (pixman_format);
- pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data,
- &pixman_format,
+ pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
width, height, format->bpp, stride);
+ pixman_format_destroy (pixman_format);
+
if (pixman_image == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
cairo_format);
- if (cairo_surface_status (surface)) {
- pixman_image_destroy (pixman_image);
- }
return surface;
}
-static void
-_init_pixman_format (pixman_format_t *pixman_format, cairo_format_t format)
+static pixman_format_t *
+_create_pixman_format (cairo_format_t format)
{
- int ret;
switch (format) {
case CAIRO_FORMAT_A1:
- ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_A1);
+ return pixman_format_create (PIXMAN_FORMAT_NAME_A1);
break;
case CAIRO_FORMAT_A8:
- ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_A8);
+ return pixman_format_create (PIXMAN_FORMAT_NAME_A8);
break;
case CAIRO_FORMAT_RGB24:
- ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_RGB24);
+ return pixman_format_create (PIXMAN_FORMAT_NAME_RGB24);
break;
case CAIRO_FORMAT_ARGB32:
default:
- ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_ARGB32);
+ return pixman_format_create (PIXMAN_FORMAT_NAME_ARGB32);
break;
}
- assert (ret);
}
/**
* cairo_image_surface_create:
* @format: format of pixels in the surface to create
* @width: width of the surface, in pixels
* @height: height of the surface, in pixels
*
@@ -285,37 +285,41 @@ static void
* pointer to a "nil" surface if an error such as out of memory
* occurs. You can use cairo_surface_status() to check for this.
**/
cairo_surface_t *
cairo_image_surface_create (cairo_format_t format,
int width,
int height)
{
- cairo_surface_t *surface;
- pixman_format_t pixman_format;
- pixman_image_t *pixman_image;
+ cairo_surface_t *surface;
+ pixman_format_t *pixman_format;
+ pixman_image_t *pixman_image;
if (! CAIRO_FORMAT_VALID (format)) {
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
}
- _init_pixman_format (&pixman_format, 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_image = pixman_image_create (pixman_format, width, height);
+
+ pixman_format_destroy (pixman_format);
+
if (pixman_image == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
- if (cairo_surface_status (surface)) {
- pixman_image_destroy (pixman_image);
- }
return surface;
}
slim_hidden_def (cairo_image_surface_create);
cairo_surface_t *
_cairo_image_surface_create_with_content (cairo_content_t content,
int width,
@@ -360,39 +364,42 @@ cairo_surface_t *
**/
cairo_surface_t *
cairo_image_surface_create_for_data (unsigned char *data,
cairo_format_t format,
int width,
int height,
int stride)
{
- cairo_surface_t *surface;
- pixman_format_t pixman_format;
- pixman_image_t *pixman_image;
+ cairo_surface_t *surface;
+ pixman_format_t *pixman_format;
+ pixman_image_t *pixman_image;
if (! CAIRO_FORMAT_VALID (format))
return (cairo_surface_t*) &_cairo_surface_nil;
- _init_pixman_format (&pixman_format, format);
+ pixman_format = _create_pixman_format (format);
+ if (pixman_format == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
- pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data,
- &pixman_format,
+ pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
width, height,
_cairo_format_bpp (format),
stride);
+
+ pixman_format_destroy (pixman_format);
+
if (pixman_image == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
surface = _cairo_image_surface_create_for_pixman_image (pixman_image, format);
- if (cairo_surface_status (surface)) {
- pixman_image_destroy (pixman_image);
- }
return surface;
}
slim_hidden_def (cairo_image_surface_create_for_data);
cairo_surface_t *