--- a/configure.in
+++ b/configure.in
@@ -5867,17 +5867,16 @@ MOZ_ARG_ENABLE_BOOL(tree-freetype,
[ --enable-tree-freetype Enable Tree FreeType],
MOZ_TREE_FREETYPE=1,
MOZ_TREE_FREETYPE= )
if test -n "$MOZ_TREE_FREETYPE"; then
AC_DEFINE(MOZ_TREE_FREETYPE)
AC_SUBST(MOZ_TREE_FREETYPE)
MOZ_ENABLE_CAIRO_FT=1
FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
- FC_FONT_FEATURE="#define CAIRO_DISABLE_FONTCONFIG 1"
FT2_CFLAGS="-I${topsrcdir}/modules/freetype2/include"
CAIRO_FT_CFLAGS="-I${topsrcdir}/modules/freetype2/include"
FT2_LIBS="${LIBXUL_DIST}/lib/freetype2.lib"
CAIRO_FT_LIBS = "${LIBXUL_DIST}/lib/freetype2.lib"
AC_DEFINE(HAVE_FT_BITMAP_SIZE_Y_PPEM)
AC_DEFINE(HAVE_FT_GLYPHSLOT_EMBOLDEN)
AC_DEFINE(HAVE_FT_LOAD_SFNT_TABLE)
AC_SUBST(CAIRO_FT_CFLAGS)
@@ -7538,16 +7537,17 @@ if test "$MOZ_TREE_CAIRO"; then
# Define macros for cairo-features.h
if test "$MOZ_X11"; then
XLIB_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_SURFACE 1"
XLIB_XRENDER_SURFACE_FEATURE="#define CAIRO_HAS_XLIB_XRENDER_SURFACE 1"
PS_SURFACE_FEATURE="#define CAIRO_HAS_PS_SURFACE 1"
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
+ FC_FONT_FEATURE="#define CAIRO_HAS_FC_FONT 1"
MOZ_ENABLE_CAIRO_FT=1
CAIRO_FT_CFLAGS="$FT2_CFLAGS"
fi
if test "$MOZ_WIDGET_TOOLKIT" = "qt"; then
QPAINTER_SURFACE_FEATURE="#define CAIRO_HAS_QPAINTER_SURFACE 1"
fi
if test "$MOZ_WIDGET_TOOLKIT" = "mac" -o "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
QUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_SURFACE 1"
@@ -7561,25 +7561,27 @@ if test "$MOZ_TREE_CAIRO"; then
else
WIN32_FONT_FEATURE=
fi
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
fi
if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then
OS2_SURFACE_FEATURE="#define CAIRO_HAS_OS2_SURFACE 1"
FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
+ FC_FONT_FEATURE="#define CAIRO_HAS_FC_FONT 1"
PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
MOZ_ENABLE_CAIRO_FT=1
CAIRO_FT_CFLAGS="-I${MZFTCFGFT2}/include"
CAIRO_FT_LIBS="-L${MZFTCFGFT2}/lib -lmozft -lmzfntcfg"
fi
if test "$MOZ_WIDGET_TOOLKIT" = "beos"; then
PKG_CHECK_MODULES(CAIRO_FT, fontconfig freetype2)
BEOS_SURFACE_FEATURE="#define CAIRO_HAS_BEOS_SURFACE 1"
FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
+ FC_FONT_FEATURE="#define CAIRO_HAS_FC_FONT 1"
MOZ_ENABLE_CAIRO_FT=1
fi
AC_SUBST(MOZ_ENABLE_CAIRO_FT)
AC_SUBST(CAIRO_FT_CFLAGS)
if test "$MOZ_DEBUG"; then
SANITY_CHECKING_FEATURE="#define CAIRO_DO_SANITY_CHECKING 1"
else
--- a/content/canvas/test/test_2d.path.isPointInPath.edge.html
+++ b/content/canvas/test/test_2d.path.isPointInPath.edge.html
@@ -10,17 +10,17 @@
SimpleTest.waitForExplicitFinish();
MochiKit.DOM.addLoadEvent(function () {
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
ctx.rect(0, 0, 20, 20);
-todo(ctx.isPointInPath(0, 0) === true, "ctx.isPointInPath(0, 0) === true");
+ok(ctx.isPointInPath(0, 0) === true, "ctx.isPointInPath(0, 0) === true");
ok(ctx.isPointInPath(10, 0) === true, "ctx.isPointInPath(10, 0) === true");
ok(ctx.isPointInPath(20, 0) === true, "ctx.isPointInPath(20, 0) === true");
ok(ctx.isPointInPath(20, 10) === true, "ctx.isPointInPath(20, 10) === true");
ok(ctx.isPointInPath(20, 20) === true, "ctx.isPointInPath(20, 20) === true");
ok(ctx.isPointInPath(10, 20) === true, "ctx.isPointInPath(10, 20) === true");
ok(ctx.isPointInPath(0, 20) === true, "ctx.isPointInPath(0, 20) === true");
ok(ctx.isPointInPath(0, 10) === true, "ctx.isPointInPath(0, 10) === true");
ok(ctx.isPointInPath(10, -0.01) === false, "ctx.isPointInPath(10, -0.01) === false");
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -21,39 +21,37 @@ Some specific things:
max-font-size.patch: Clamp freetype font size to 1000 to avoid overflow issues
win32-logical-font-scale.patch: set CAIRO_WIN32_LOGICAL_FONT_SCALE to 1
nonfatal-assertions.patch: Make assertions non-fatal
buggy-repeat.patch: Unconditionally turn on buggy-repeat handling to bandaid bug 413583.
-tmpfile_wince.patch: Make Windows CE use tmpfile() on windows mobile due to the lack of _open_osfhandle and no fs permissions.
-
cairo-version-fixes.patch: fix up cairo-version.c/cairo-version.h for in-place builds
win32-ddb-dib.patch: fix for bug 455513; not upstream yet pending feebdack
qpainter-type.patch: add SURFACE_TYPE_QPAINTER to cairo.h
wince-fixes.patch: stubs out win32 functions we use but are not supported on win32. Also implements ExtSelectClipRgn in terms of other functions available on wince.
-ft-done-face.patch: bug 467874; only destroy FT_Faces created by cairo
-
-wince-fontconfig.patch: bug 462908; fixes required to compile for windows ce. Also allows for building without fontconfig
-
-glyph-safety-margin.patch: Change the glyph dropping safety margin from 2em to 10em for bug 460023. Upstream commit: 28a72648ba7abe02ebd4df7234424e333b85dc9c.
-
win32-vertically-offset-glyph.patch: bug 454098; vertical positioning errors when drawing glyph runs including delta-y offsets on screen via GDI
ignore-rank0.patch: bug 474886; Not redrawing the background when changing page on flickr
win32-canvas-glyph-position.patch: bug 475092; horizontal positioning errors when drawing glyph runs with delta-y offsets to canvas through win32-font
win32-cleartype-clipping.patch: bug 445087; some glyphs are clipped, mainly on right-hand edge, when ClearType is enabled and drawing to RGBA canvas
+on-edge.patch: reverts the in-fill semantic change.
+
+wrap-source_image.patch: make sure we don't free the source image until we're done with it.
+
+zero-sized.patch: deal with zero sized surface in ways less likely to crash.
+
==== pixman patches ====
endian.patch: include cairo-platform.h for endian macros
==== disable printing patch ====
disable-printing.patch: allows us to use NS_PRINTING to disable printing.
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -87,42 +87,47 @@ CSRCS = \
cairo-font-face.c \
cairo-font-face-twin.c \
cairo-font-face-twin-data.c \
cairo-font-options.c \
cairo-freelist.c \
cairo-gstate.c \
cairo-hash.c \
cairo-hull.c \
+ cairo-image-info.c \
cairo-image-surface.c \
cairo-lzw.c \
cairo-matrix.c \
cairo-meta-surface.c \
cairo-misc.c \
cairo-mutex.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-in-fill.c \
cairo-path-stroke.c \
cairo-pattern.c \
cairo-pen.c \
cairo-polygon.c \
cairo-rectangle.c \
cairo-region.c \
cairo-scaled-font.c \
cairo-scaled-font-subsets.c \
cairo-skiplist.c \
cairo-slope.c \
+ cairo-spans.c \
cairo-spline.c \
cairo-stroke-style.c \
cairo-surface.c \
cairo-surface-fallback.c \
+ cairo-tor-scan-converter.c \
+ cairo-toy-font-face.c \
cairo-traps.c \
cairo-unicode.c \
cairo-user-font.c \
cairo-version.c \
cairo-wideint.c \
$(NULL)
EXPORTS = cairo.h cairo-version.h cairo-features.h cairo-platform.h cairo-deprecated.h cairo-rename.h
--- a/gfx/cairo/cairo/src/cairo-analysis-surface.c
+++ b/gfx/cairo/cairo/src/cairo-analysis-surface.c
@@ -91,37 +91,37 @@ cairo_int_status_t
assert (status_a == CAIRO_STATUS_SUCCESS &&
status_b == CAIRO_STATUS_SUCCESS);
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
- cairo_pattern_t *pattern)
+ const cairo_pattern_t *pattern)
{
cairo_surface_t *analysis = &surface->base;
- cairo_surface_pattern_t *surface_pattern;
+ const cairo_surface_pattern_t *surface_pattern;
cairo_status_t status;
cairo_bool_t old_has_ctm;
cairo_matrix_t old_ctm, p2d;
cairo_rectangle_int_t old_clip;
cairo_rectangle_int_t meta_extents;
int old_width;
int old_height;
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
- surface_pattern = (cairo_surface_pattern_t *) pattern;
+ surface_pattern = (const cairo_surface_pattern_t *) pattern;
assert (_cairo_surface_is_meta (surface_pattern->surface));
old_width = surface->width;
old_height = surface->height;
old_clip = surface->current_clip;
status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents);
- if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ if (_cairo_status_is_error (status))
return status;
surface->width = meta_extents.width;
surface->height = meta_extents.height;
surface->current_clip.x = 0;
surface->current_clip.y = 0;
surface->current_clip.width = surface->width;
surface->current_clip.height = surface->height;
@@ -278,111 +278,110 @@ static cairo_status_t
static cairo_int_status_t
_cairo_analysis_surface_intersect_clip_path (void *abstract_surface,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
cairo_antialias_t antialias)
{
cairo_analysis_surface_t *surface = abstract_surface;
- double x1, y1, x2, y2;
- cairo_rectangle_int_t extent;
if (path == NULL) {
surface->current_clip.x = 0;
surface->current_clip.y = 0;
surface->current_clip.width = surface->width;
surface->current_clip.height = surface->height;
} else {
- cairo_status_t status;
-
- status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2, tolerance);
- if (status)
- return status;
+ cairo_rectangle_int_t extents;
+ cairo_bool_t is_empty;
- extent.x = floor (x1);
- extent.y = floor (y1);
- extent.width = ceil (x2) - extent.x;
- extent.height = ceil (y2) - extent.y;
-
- _cairo_rectangle_intersect (&surface->current_clip, &extent);
+ _cairo_path_fixed_approximate_clip_extents (path, &extents);
+ is_empty = _cairo_rectangle_intersect (&surface->current_clip,
+ &extents);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_analysis_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle)
{
cairo_analysis_surface_t *surface = abstract_surface;
return _cairo_surface_get_extents (surface->target, rectangle);
}
static cairo_int_status_t
_cairo_analysis_surface_paint (void *abstract_surface,
- cairo_operator_t op,
- cairo_pattern_t *source)
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ cairo_rectangle_int_t *paint_extents)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_rectangle_int_t extents;
+ cairo_bool_t is_empty;
if (!surface->target->backend->paint)
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
else
backend_status = (*surface->target->backend->paint) (surface->target, op,
- source);
+ source, NULL);
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
- if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ if (_cairo_status_is_error (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
+
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
- _cairo_rectangle_intersect (&extents, &source_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
}
- _cairo_rectangle_intersect (&extents, &surface->current_clip);
+ is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+ if (paint_extents)
+ *paint_extents = extents;
status = _add_operation (surface, &extents, backend_status);
return status;
}
static cairo_int_status_t
_cairo_analysis_surface_mask (void *abstract_surface,
cairo_operator_t op,
- cairo_pattern_t *source,
- cairo_pattern_t *mask)
+ const cairo_pattern_t *source,
+ const cairo_pattern_t *mask,
+ cairo_rectangle_int_t *mask_extents)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_int_status_t status, backend_status;
cairo_rectangle_int_t extents;
+ cairo_bool_t is_empty;
if (!surface->target->backend->mask)
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
else
backend_status = (*surface->target->backend->mask) (surface->target, op,
- source, mask);
+ source, mask, NULL);
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS;
cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS;
if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
- cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source;
+ const cairo_surface_pattern_t *surface_pattern = (const cairo_surface_pattern_t *) source;
if (_cairo_surface_is_meta (surface_pattern->surface)) {
backend_source_status =
_analyze_meta_surface_pattern (surface, source);
if (_cairo_status_is_error (backend_source_status))
return backend_source_status;
}
}
@@ -397,236 +396,230 @@ static cairo_int_status_t
}
backend_status =
_cairo_analysis_surface_merge_status (backend_source_status,
backend_mask_status);
}
status = _cairo_surface_get_extents (&surface->base, &extents);
- if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ if (_cairo_status_is_error (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
+
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
- _cairo_rectangle_intersect (&extents, &source_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
+ }
- status = _cairo_pattern_get_extents (mask, &source_extents);
- if (status)
+ if (_cairo_operator_bounded_by_mask (op)) {
+ cairo_rectangle_int_t mask_extents;
+
+ status = _cairo_pattern_get_extents (mask, &mask_extents);
+ if (unlikely (status))
return status;
- _cairo_rectangle_intersect (&extents, &source_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
}
- _cairo_rectangle_intersect (&extents, &surface->current_clip);
+ is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
+ if (mask_extents)
+ *mask_extents = extents;
status = _add_operation (surface, &extents, backend_status);
return status;
}
static cairo_int_status_t
_cairo_analysis_surface_stroke (void *abstract_surface,
cairo_operator_t op,
- cairo_pattern_t *source,
+ const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
- cairo_antialias_t antialias)
+ cairo_antialias_t antialias,
+ cairo_rectangle_int_t *stroke_extents)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
- cairo_traps_t traps;
- cairo_rectangle_int_t extents;
+ cairo_rectangle_int_t extents;
+ cairo_bool_t is_empty;
if (!surface->target->backend->stroke)
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
else
backend_status = (*surface->target->backend->stroke) (surface->target, op,
source, path, style,
ctm, ctm_inverse,
- tolerance, antialias);
+ tolerance, antialias, NULL);
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
- if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ if (_cairo_status_is_error (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
+
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
- _cairo_rectangle_intersect (&extents, &source_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
}
- _cairo_rectangle_intersect (&extents, &surface->current_clip);
+ is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
- cairo_box_t box;
-
- _cairo_box_from_rectangle (&box, &extents);
+ cairo_rectangle_int_t mask_extents;
- _cairo_traps_init (&traps);
- _cairo_traps_limit (&traps, &box);
- status = _cairo_path_fixed_stroke_to_traps (path,
- style,
- ctm, ctm_inverse,
- tolerance,
- &traps);
- if (status) {
- _cairo_traps_fini (&traps);
- return status;
- }
+ _cairo_path_fixed_approximate_stroke_extents (path,
+ style, ctm,
+ &mask_extents);
- _cairo_traps_extents (&traps, &box);
- _cairo_traps_fini (&traps);
-
- _cairo_box_round_to_rectangle (&box, &extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
}
+ if (stroke_extents)
+ *stroke_extents = extents;
status = _add_operation (surface, &extents, backend_status);
return status;
}
static cairo_int_status_t
_cairo_analysis_surface_fill (void *abstract_surface,
cairo_operator_t op,
- cairo_pattern_t *source,
+ const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
- cairo_antialias_t antialias)
+ cairo_antialias_t antialias,
+ cairo_rectangle_int_t *fill_extents)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
- cairo_traps_t traps;
- cairo_rectangle_int_t extents;
+ cairo_rectangle_int_t extents;
+ cairo_bool_t is_empty;
if (!surface->target->backend->fill)
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
else
backend_status = (*surface->target->backend->fill) (surface->target, op,
source, path, fill_rule,
- tolerance, antialias);
+ tolerance, antialias, NULL);
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
- if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ if (_cairo_status_is_error (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
+
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
- _cairo_rectangle_intersect (&extents, &source_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
}
- _cairo_rectangle_intersect (&extents, &surface->current_clip);
+ is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
- cairo_box_t box;
+ cairo_rectangle_int_t mask_extents;
- _cairo_box_from_rectangle (&box, &extents);
+ _cairo_path_fixed_approximate_fill_extents (path,
+ &mask_extents);
- _cairo_traps_init (&traps);
- _cairo_traps_limit (&traps, &box);
- status = _cairo_path_fixed_fill_to_traps (path,
- fill_rule,
- tolerance,
- &traps);
- if (status) {
- _cairo_traps_fini (&traps);
- return status;
- }
-
- _cairo_traps_extents (&traps, &box);
- _cairo_traps_fini (&traps);
-
- _cairo_box_round_to_rectangle (&box, &extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
}
+ if (fill_extents)
+ *fill_extents = extents;
status = _add_operation (surface, &extents, backend_status);
return status;
}
static cairo_int_status_t
_cairo_analysis_surface_show_glyphs (void *abstract_surface,
cairo_operator_t op,
- cairo_pattern_t *source,
+ const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- int *remaining_glyphs)
+ int *remaining_glyphs,
+ cairo_rectangle_int_t *show_glyphs_extents)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_rectangle_int_t extents, glyph_extents;
+ cairo_bool_t is_empty;
/* Adapted from _cairo_surface_show_glyphs */
if (surface->target->backend->show_glyphs)
backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
source,
glyphs, num_glyphs,
scaled_font,
- remaining_glyphs);
+ remaining_glyphs, NULL);
else if (surface->target->backend->show_text_glyphs)
backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
source,
NULL, 0,
glyphs, num_glyphs,
NULL, 0,
FALSE,
- scaled_font);
+ scaled_font, NULL);
else
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
- if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ if (_cairo_status_is_error (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
+
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
- _cairo_rectangle_intersect (&extents, &source_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
}
- _cairo_rectangle_intersect (&extents, &surface->current_clip);
+ is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs,
num_glyphs,
&glyph_extents);
- if (status)
+ if (unlikely (status))
return status;
- _cairo_rectangle_intersect (&extents, &glyph_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
}
+ if (show_glyphs_extents)
+ *show_glyphs_extents = extents;
status = _add_operation (surface, &extents, backend_status);
return status;
}
static cairo_bool_t
_cairo_analysis_surface_has_show_text_glyphs (void *abstract_surface)
@@ -634,80 +627,85 @@ static cairo_bool_t
cairo_analysis_surface_t *surface = abstract_surface;
return cairo_surface_has_show_text_glyphs (surface->target);
}
static cairo_int_status_t
_cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
cairo_operator_t op,
- cairo_pattern_t *source,
+ const cairo_pattern_t *source,
const char *utf8,
int utf8_len,
cairo_glyph_t *glyphs,
int num_glyphs,
const cairo_text_cluster_t *clusters,
int num_clusters,
cairo_text_cluster_flags_t cluster_flags,
- cairo_scaled_font_t *scaled_font)
+ cairo_scaled_font_t *scaled_font,
+ cairo_rectangle_int_t *show_text_glyphs_extents)
{
cairo_analysis_surface_t *surface = abstract_surface;
cairo_status_t status, backend_status;
cairo_rectangle_int_t extents, glyph_extents;
+ cairo_bool_t is_empty;
/* Adapted from _cairo_surface_show_glyphs */
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
if (surface->target->backend->show_text_glyphs)
backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
source,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters, cluster_flags,
- scaled_font);
+ scaled_font, NULL);
if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
int remaining_glyphs = num_glyphs;
backend_status = surface->target->backend->show_glyphs (surface->target, op,
source,
glyphs, num_glyphs,
scaled_font,
- &remaining_glyphs);
+ &remaining_glyphs, NULL);
glyphs += num_glyphs - remaining_glyphs;
num_glyphs = remaining_glyphs;
if (remaining_glyphs == 0)
backend_status = CAIRO_STATUS_SUCCESS;
}
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
backend_status = _analyze_meta_surface_pattern (surface, source);
status = _cairo_surface_get_extents (&surface->base, &extents);
- if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ if (_cairo_status_is_error (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
+
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
- _cairo_rectangle_intersect (&extents, &source_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
}
- _cairo_rectangle_intersect (&extents, &surface->current_clip);
+ is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs,
num_glyphs,
&glyph_extents);
- if (status)
+ if (unlikely (status))
return status;
- _cairo_rectangle_intersect (&extents, &glyph_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
}
+ if (show_text_glyphs_extents)
+ *show_text_glyphs_extents = extents;
status = _add_operation (surface, &extents, backend_status);
return status;
}
static const cairo_surface_backend_t cairo_analysis_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
@@ -716,16 +714,18 @@ static const cairo_surface_backend_t cai
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
+ NULL, /* create_span_renderer */
+ NULL, /* check_span_renderer */
NULL, /* copy_page */
NULL, /* show_page */
NULL, /* set_clip_region */
_cairo_analysis_surface_intersect_clip_path,
_cairo_analysis_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
@@ -737,34 +737,35 @@ static const cairo_surface_backend_t cai
_cairo_analysis_surface_stroke,
_cairo_analysis_surface_fill,
_cairo_analysis_surface_show_glyphs,
NULL, /* snapshot */
NULL, /* is_similar */
NULL, /* reset */
NULL, /* fill_stroke */
NULL, /* create_solid_pattern_surface */
+ NULL, /* can_repaint_solid_pattern_surface */
_cairo_analysis_surface_has_show_text_glyphs,
_cairo_analysis_surface_show_text_glyphs
};
cairo_surface_t *
_cairo_analysis_surface_create (cairo_surface_t *target,
int width,
int height)
{
cairo_analysis_surface_t *surface;
cairo_status_t status;
status = target->status;
- if (status)
+ if (unlikely (status))
return _cairo_surface_create_in_error (status);
surface = malloc (sizeof (cairo_analysis_surface_t));
- if (surface == NULL)
+ if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
/* I believe the content type here is truly arbitrary. I'm quite
* sure nothing will ever use this value. */
_cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
CAIRO_CONTENT_COLOR_ALPHA);
surface->width = width;
@@ -876,66 +877,73 @@ static cairo_int_status_t
/* These typedefs are just to silence the compiler... */
typedef cairo_int_status_t
(*_set_clip_region_func) (void *surface,
cairo_region_t *region);
typedef cairo_int_status_t
(*_paint_func) (void *surface,
cairo_operator_t op,
- cairo_pattern_t *source);
+ const cairo_pattern_t *source,
+ cairo_rectangle_int_t *extents);
typedef cairo_int_status_t
(*_mask_func) (void *surface,
cairo_operator_t op,
- cairo_pattern_t *source,
- cairo_pattern_t *mask);
+ const cairo_pattern_t *source,
+ const cairo_pattern_t *mask,
+ cairo_rectangle_int_t *extents);
typedef cairo_int_status_t
(*_stroke_func) (void *surface,
cairo_operator_t op,
- cairo_pattern_t *source,
+ const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_stroke_style_t *style,
cairo_matrix_t *ctm,
cairo_matrix_t *ctm_inverse,
double tolerance,
- cairo_antialias_t antialias);
+ cairo_antialias_t antialias,
+ cairo_rectangle_int_t *extents);
typedef cairo_int_status_t
(*_fill_func) (void *surface,
cairo_operator_t op,
- cairo_pattern_t *source,
+ const cairo_pattern_t *source,
cairo_path_fixed_t *path,
cairo_fill_rule_t fill_rule,
double tolerance,
- cairo_antialias_t antialias);
+ cairo_antialias_t antialias,
+ cairo_rectangle_int_t *extents);
typedef cairo_int_status_t
(*_show_glyphs_func) (void *surface,
cairo_operator_t op,
- cairo_pattern_t *source,
+ const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
- int *remaining_glyphs);
+ int *remaining_glyphs,
+ cairo_rectangle_int_t *extents);
static const cairo_surface_backend_t cairo_null_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
NULL, /* create_similar */
NULL, /* finish */
NULL, /* acquire_source_image */
NULL, /* release_source_image */
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
NULL, /* composite */
NULL, /* fill_rectangles */
NULL, /* composite_trapezoids */
+ NULL, /* create_span_renderer */
+ NULL, /* check_span_renderer */
NULL, /* copy_page */
NULL, /* show_page */
(_set_clip_region_func) _return_success, /* set_clip_region */
NULL, /* intersect_clip_path */
NULL, /* get_extents */
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
@@ -947,26 +955,27 @@ static const cairo_surface_backend_t cai
(_stroke_func) _return_success, /* stroke */
(_fill_func) _return_success, /* fill */
(_show_glyphs_func) _return_success, /* show_glyphs */
NULL, /* snapshot */
NULL, /* is_similar */
NULL, /* reset */
NULL, /* fill_stroke */
NULL, /* create_solid_pattern_surface */
+ NULL, /* can_repaint_solid_pattern_surface */
NULL, /* has_show_text_glyphs */
NULL /* show_text_glyphs */
};
cairo_surface_t *
_cairo_null_surface_create (cairo_content_t content)
{
cairo_surface_t *surface;
surface = malloc (sizeof (cairo_surface_t));
- if (surface == NULL) {
+ if (unlikely (surface == NULL)) {
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
_cairo_surface_init (surface, &cairo_null_surface_backend, content);
return surface;
}
--- a/gfx/cairo/cairo/src/cairo-array.c
+++ b/gfx/cairo/cairo/src/cairo-array.c
@@ -133,27 +133,27 @@ cairo_status_t
else
new_size = old_size * 2;
while (new_size < required_size)
new_size = new_size * 2;
if (array->elements == NULL) {
array->elements = malloc (sizeof (char *));
- if (array->elements == NULL)
+ if (unlikely (array->elements == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
*array->elements = NULL;
}
array->size = new_size;
new_elements = _cairo_realloc_ab (*array->elements,
array->size, array->element_size);
- if (new_elements == NULL) {
+ if (unlikely (new_elements == NULL)) {
array->size = old_size;
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
*array->elements = new_elements;
return CAIRO_STATUS_SUCCESS;
}
@@ -274,17 +274,17 @@ cairo_status_t
int num_elements)
{
cairo_status_t status;
void *dest;
assert (! array->is_snapshot);
status = _cairo_array_allocate (array, num_elements, &dest);
- if (status)
+ if (unlikely (status))
return status;
memcpy (dest, elements, num_elements * array->element_size);
return CAIRO_STATUS_SUCCESS;
}
/**
@@ -305,17 +305,17 @@ cairo_status_t
unsigned int num_elements,
void **elements)
{
cairo_status_t status;
assert (! array->is_snapshot);
status = _cairo_array_grow_by (array, num_elements);
- if (status)
+ if (unlikely (status))
return status;
assert (array->num_elements + num_elements <= array->size);
*elements = &(*array->elements)[array->num_elements * array->element_size];
array->num_elements += num_elements;
@@ -377,24 +377,28 @@ void
* @array: a #cairo_user_data_array_t
*
* Destroys all current keys in the user data array and deallocates
* any memory allocated for the array itself.
**/
void
_cairo_user_data_array_fini (cairo_user_data_array_t *array)
{
- int i, num_slots;
- cairo_user_data_slot_t *slots;
+ unsigned int num_slots;
num_slots = array->num_elements;
- slots = _cairo_array_index (array, 0);
- for (i = 0; i < num_slots; i++) {
- if (slots[i].user_data != NULL && slots[i].destroy != NULL)
- slots[i].destroy (slots[i].user_data);
+ if (num_slots) {
+ cairo_user_data_slot_t *slots;
+
+ slots = _cairo_array_index (array, 0);
+ do {
+ if (slots->user_data != NULL && slots->destroy != NULL)
+ slots->destroy (slots->user_data);
+ slots++;
+ } while (--num_slots);
}
_cairo_array_fini (array);
}
/**
* _cairo_user_data_array_get_data:
* @array: a #cairo_user_data_array_t
@@ -480,13 +484,49 @@ cairo_status_t
}
if (slot) {
*slot = new_slot;
return CAIRO_STATUS_SUCCESS;
}
status = _cairo_array_append (array, &new_slot);
- if (status)
+ if (unlikely (status))
return status;
return CAIRO_STATUS_SUCCESS;
}
+
+cairo_status_t
+_cairo_user_data_array_copy (cairo_user_data_array_t *dst,
+ cairo_user_data_array_t *src)
+{
+ /* discard any existing user-data */
+ if (dst->num_elements != 0) {
+ _cairo_user_data_array_fini (dst);
+ _cairo_user_data_array_init (dst);
+ }
+
+ if (src->num_elements == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ return _cairo_array_append_multiple (dst,
+ _cairo_array_index (src, 0),
+ src->num_elements);
+}
+
+void
+_cairo_user_data_array_foreach (cairo_user_data_array_t *array,
+ void (*func) (const void *key,
+ void *elt,
+ void *closure),
+ void *closure)
+{
+ cairo_user_data_slot_t *slots;
+ int i, num_slots;
+
+ num_slots = array->num_elements;
+ slots = _cairo_array_index (array, 0);
+ for (i = 0; i < num_slots; i++) {
+ if (slots[i].user_data != NULL)
+ func (slots[i].key, slots[i].user_data, closure);
+ }
+}
--- a/gfx/cairo/cairo/src/cairo-base85-stream.c
+++ b/gfx/cairo/cairo/src/cairo-base85-stream.c
@@ -112,21 +112,22 @@ cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output)
{
cairo_base85_stream_t *stream;
if (output->status)
return _cairo_output_stream_create_in_error (output->status);
stream = malloc (sizeof (cairo_base85_stream_t));
- if (stream == NULL) {
+ if (unlikely (stream == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
}
_cairo_output_stream_init (&stream->base,
_cairo_base85_stream_write,
+ NULL,
_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
@@ -33,16 +33,17 @@
* Carl D. Worth <cworth@cworth.org>
*/
/* Provide definitions for standalone compilation */
#include "cairoint.h"
#include "cairo-skiplist-private.h"
#include "cairo-freelist-private.h"
+#include "cairo-combsort-private.h"
#define DEBUG_VALIDATE 0
#define DEBUG_PRINT_STATE 0
typedef cairo_point_t cairo_bo_point32_t;
typedef struct _cairo_bo_point128 {
cairo_int128_t x;
@@ -81,17 +82,17 @@ struct _cairo_bo_traps {
cairo_fixed_t xmax;
cairo_fixed_t ymax;
};
struct _cairo_bo_edge {
cairo_bo_point32_t top;
cairo_bo_point32_t middle;
cairo_bo_point32_t bottom;
- cairo_bool_t reversed;
+ int dir;
cairo_bo_edge_t *prev;
cairo_bo_edge_t *next;
cairo_bo_trap_t *deferred_trap;
sweep_line_elt_t *sweep_line_elt;
};
struct _sweep_line_elt {
cairo_bo_edge_t *edge;
@@ -123,18 +124,16 @@ typedef struct _cairo_bo_event {
#define SKIP_ELT_TO_EVENT(elt) SKIP_LIST_ELT_TO_DATA (cairo_bo_event_t, (elt))
typedef struct _cairo_bo_event_queue {
cairo_skip_list_t intersection_queue;
cairo_bo_event_t *startstop_events;
cairo_bo_event_t **sorted_startstop_event_ptrs;
- unsigned next_startstop_event_index;
- unsigned num_startstop_events;
} cairo_bo_event_queue_t;
/* 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;
@@ -192,21 +191,31 @@ static int
* bits. That's not true in general as there could be overflow. We
* should prevent that before the tessellation algorithm
* begins.
*/
int32_t adx = a->bottom.x - a->top.x;
int32_t bdx = b->bottom.x - b->top.x;
/* Since the dy's are all positive by construction we can fast
- * path the case where the two edges point in different directions
- * with respect to x. */
- if ((adx ^ bdx) < 0) {
- return adx < 0 ? -1 : +1;
- } else {
+ * path several common cases.
+ */
+
+ /* First check for vertical lines. */
+ if (adx == 0)
+ return -bdx;
+ if (bdx == 0)
+ return adx;
+
+ /* Then where the two edges point in different directions wrt x. */
+ if ((adx ^ bdx) < 0)
+ return adx;
+
+ /* Finally we actually need to do the general comparison. */
+ {
int32_t ady = a->bottom.y - a->top.y;
int32_t bdy = b->bottom.y - b->top.y;
cairo_int64_t adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
cairo_int64_t bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
return _cairo_int64_cmp (adx_bdy, bdx_ady);
}
}
@@ -214,84 +223,149 @@ static int
/*
* We need to compare the x-coordinates of a pair of lines for a particular y,
* without loss of precision.
*
* The x-coordinate along an edge for a given y is:
* X = A_x + (Y - A_y) * A_dx / A_dy
*
* So the inequality we wish to test is:
- * A_x + (Y - A_y) * A_dx / A_dy -?- B_x + (Y - B_y) * B_dx / B_dy,
- * where -?- is our inequality operator.
+ * A_x + (Y - A_y) * A_dx / A_dy ∘ B_x + (Y - B_y) * B_dx / B_dy,
+ * where ∘ is our inequality operator.
*
* By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
* all positive, so we can rearrange it thus without causing a sign change:
- * A_dy * B_dy * (A_x - B_x) -?- (Y - B_y) * B_dx * A_dy
+ * A_dy * B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx * A_dy
* - (Y - A_y) * A_dx * B_dy
*
* Given the assumption that all the deltas fit within 32 bits, we can compute
- * this comparison directly using 128 bit arithmetic.
+ * this comparison directly using 128 bit arithmetic. For certain, but common,
+ * input we can reduce this down to a single 32 bit compare by inspecting the
+ * deltas.
*
* (And put the burden of the work on developing fast 128 bit ops, which are
* required throughout the tessellator.)
*
* See the similar discussion for _slope_compare().
*/
static int
edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
const cairo_bo_edge_t *b,
int32_t y)
{
/* XXX: We're assuming here that dx and dy will still fit in 32
* bits. That's not true in general as there could be overflow. We
* should prevent that before the tessellation algorithm
* begins.
*/
+ int32_t dx;
int32_t adx, ady;
int32_t bdx, bdy;
- cairo_int128_t L, R;
-
- adx = a->bottom.x - a->top.x;
- ady = a->bottom.y - a->top.y;
+ enum {
+ HAVE_NONE = 0x0,
+ HAVE_DX = 0x1,
+ HAVE_ADX = 0x2,
+ HAVE_DX_ADX = HAVE_DX | HAVE_ADX,
+ HAVE_BDX = 0x4,
+ HAVE_DX_BDX = HAVE_DX | HAVE_BDX,
+ HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
+ HAVE_ALL = HAVE_DX | HAVE_ADX | HAVE_BDX
+ } have_dx_adx_bdx = HAVE_ALL;
- bdx = b->bottom.x - b->top.x;
- bdy = b->bottom.y - b->top.y;
+ ady = a->bottom.y - a->top.y;
+ adx = a->bottom.x - a->top.x;
+ if (adx == 0)
+ have_dx_adx_bdx &= ~HAVE_ADX;
- L = _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy),
- a->top.x - b->top.x);
+ bdy = b->bottom.y - b->top.y;
+ bdx = b->bottom.x - b->top.x;
+ if (bdx == 0)
+ have_dx_adx_bdx &= ~HAVE_BDX;
+
+ dx = a->top.x - b->top.x;
+ if (dx == 0)
+ have_dx_adx_bdx &= ~HAVE_DX;
- R = _cairo_int128_sub (_cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx,
- ady),
- y - b->top.y),
- _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx,
- bdy),
- y - a->top.y));
+#define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
+#define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->top.y)
+#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->top.y)
+ switch (have_dx_adx_bdx) {
+ default:
+ case HAVE_NONE:
+ return 0;
+ case HAVE_DX:
+ /* A_dy * B_dy * (A_x - B_x) ∘ 0 */
+ return dx; /* ady * bdy is positive definite */
+ case HAVE_ADX:
+ /* 0 ∘ - (Y - A_y) * A_dx * B_dy */
+ return adx; /* bdy * (y - a->top.y) is positive definite */
+ case HAVE_BDX:
+ /* 0 ∘ (Y - B_y) * B_dx * A_dy */
+ return -bdx; /* ady * (y - b->top.y) is positive definite */
+ case HAVE_ADX_BDX:
+ /* 0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
+ if ((adx ^ bdx) < 0) {
+ return adx;
+ } else if (a->top.y == b->top.y) { /* common origin */
+ cairo_int64_t adx_bdy, bdx_ady;
+
+ /* ∴ A_dx * B_dy ∘ B_dx * A_dy */
+
+ adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
+ bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
- /* return _cairo_int128_cmp (L, R); */
- if (_cairo_int128_lt (L, R))
- return -1;
- if (_cairo_int128_gt (L, R))
- return 1;
- return 0;
+ return _cairo_int64_cmp (adx_bdy, bdx_ady);
+ } else
+ return _cairo_int128_cmp (A, B);
+ case HAVE_DX_ADX:
+ /* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */
+ if ((-adx ^ dx) < 0) {
+ return dx;
+ } else {
+ cairo_int64_t ady_dx, dy_adx;
+
+ ady_dx = _cairo_int32x32_64_mul (ady, dx);
+ dy_adx = _cairo_int32x32_64_mul (a->top.y - y, adx);
+
+ return _cairo_int64_cmp (ady_dx, dy_adx);
+ }
+ case HAVE_DX_BDX:
+ /* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */
+ if ((bdx ^ dx) < 0) {
+ return dx;
+ } else {
+ cairo_int64_t bdy_dx, dy_bdx;
+
+ bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
+ dy_bdx = _cairo_int32x32_64_mul (y - b->top.y, bdx);
+
+ return _cairo_int64_cmp (bdy_dx, dy_bdx);
+ }
+ case HAVE_ALL:
+ return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
+ }
+#undef B
+#undef A
+#undef L
}
/*
* We need to compare the x-coordinate of a line for a particular y wrt to a
* given x, without loss of precision.
*
* The x-coordinate along an edge for a given y is:
* X = A_x + (Y - A_y) * A_dx / A_dy
*
* So the inequality we wish to test is:
- * A_x + (Y - A_y) * A_dx / A_dy -?- X
- * where -?- is our inequality operator.
+ * A_x + (Y - A_y) * A_dx / A_dy ∘ X
+ * where ∘ is our inequality operator.
*
* By construction, we know that A_dy (and (Y - A_y)) are
* all positive, so we can rearrange it thus without causing a sign change:
- * (Y - A_y) * A_dx -?- (X - A_x) * A_dy
+ * (Y - A_y) * A_dx ∘ (X - A_x) * A_dy
*
* Given the assumption that all the deltas fit within 32 bits, we can compute
* this comparison directly using 64 bit arithmetic.
*
* See the similar discussion for _slope_compare() and
* edges_compare_x_for_y_general().
*/
static int
@@ -299,20 +373,25 @@ edge_compare_for_y_against_x (const cair
int32_t y,
int32_t x)
{
int32_t adx, ady;
int32_t dx, dy;
cairo_int64_t L, R;
adx = a->bottom.x - a->top.x;
- ady = a->bottom.y - a->top.y;
+ dx = x - a->top.x;
+
+ if (adx == 0)
+ return -dx;
+ if ((adx ^ dx) < 0)
+ return adx;
dy = y - a->top.y;
- dx = x - a->top.x;
+ ady = a->bottom.y - a->top.y;
L = _cairo_int32x32_64_mul (dy, adx);
R = _cairo_int32x32_64_mul (dx, ady);
return _cairo_int64_cmp (L, R);
}
static int
@@ -347,17 +426,17 @@ edges_compare_x_for_y (const cairo_bo_ed
else
have_ax_bx &= ~HAVE_BX;
switch (have_ax_bx) {
default:
case HAVE_NEITHER:
return edges_compare_x_for_y_general (a, b, y);
case HAVE_AX:
- return - edge_compare_for_y_against_x (b, y, ax);
+ return -edge_compare_for_y_against_x (b, y, ax);
case HAVE_BX:
return edge_compare_for_y_against_x (a, y, bx);
case HAVE_BOTH:
return ax - bx;
}
}
static int
@@ -545,31 +624,28 @@ cairo_bo_event_compare_abstract (void *
{
cairo_bo_event_t *event_a = a;
cairo_bo_event_t *event_b = b;
return cairo_bo_event_compare (event_a, event_b);
}
static int
-cairo_bo_event_compare_pointers (void const *voida,
- void const *voidb)
+cairo_bo_event_compare_pointers (const cairo_bo_event_t *a,
+ const cairo_bo_event_t *b)
{
- cairo_bo_event_t const * const *a = voida;
- cairo_bo_event_t const * const *b = voidb;
- if (*a != *b) {
- int cmp = cairo_bo_event_compare (*a, *b);
- if (cmp)
- return cmp;
- if (*a < *b)
- return -1;
- if (*a > *b)
- return +1;
- }
- return 0;
+ int cmp;
+
+ if (a == b)
+ return 0;
+ cmp = cairo_bo_event_compare (a, b);
+ if (cmp)
+ return cmp;
+
+ return a - b;
}
static inline cairo_int64_t
det32_64 (int32_t a,
int32_t b,
int32_t c,
int32_t d)
{
@@ -619,22 +695,71 @@ intersect_lines (cairo_bo_edge_t *a,
* cairo_bo_tessellate_polygon().
*/
int32_t dx1 = a->top.x - a->bottom.x;
int32_t dy1 = a->top.y - a->bottom.y;
int32_t dx2 = b->top.x - b->bottom.x;
int32_t dy2 = b->top.y - b->bottom.y;
- cairo_int64_t den_det = det32_64 (dx1, dy1, dx2, dy2);
+ cairo_int64_t den_det;
+ cairo_int64_t R;
cairo_quorem64_t qr;
+ den_det = det32_64 (dx1, dy1, dx2, dy2);
if (_cairo_int64_is_zero (den_det))
return CAIRO_BO_STATUS_PARALLEL;
+ /* Q: Can we determine that the lines do not intersect (within range)
+ * much more cheaply than computing the intersection point i.e. by
+ * avoiding the division?
+ *
+ * X = ax + t * adx = bx + s * bdx;
+ * Y = ay + t * ady = by + s * bdy;
+ * ∴ t * (ady*bdx - bdy*adx) = bdx * (by - ay) + bdy * (ax - bx)
+ * => t * L = R
+ *
+ * Therefore we can reject any intersection (under the criteria for
+ * valid intersection events) if:
+ * L^R < 0 => t < 0, or
+ * L<R => t > 1
+ *
+ * (where top/bottom must at least extend to the line endpoints).
+ *
+ * A similar substitution can be performed for s, yielding:
+ * s * (ady*bdx - bdy*adx) = ady * (ax - bx) - adx * (ay - by)
+ */
+ R = det32_64 (dx2, dy2, b->top.x - a->top.x, b->top.y - a->top.y);
+ if (_cairo_int64_is_zero (R))
+ return CAIRO_BO_STATUS_NO_INTERSECTION;
+ if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (R))
+ return CAIRO_BO_STATUS_NO_INTERSECTION;
+ if (_cairo_int64_negative (den_det)) {
+ if (_cairo_int64_ge (den_det, R))
+ return CAIRO_BO_STATUS_NO_INTERSECTION;
+ } else {
+ if (_cairo_int64_le (den_det, R))
+ return CAIRO_BO_STATUS_NO_INTERSECTION;
+ }
+
+ R = det32_64 (dy1, dx1, a->top.y - b->top.y, a->top.x - b->top.x);
+ if (_cairo_int64_is_zero (R))
+ return CAIRO_BO_STATUS_NO_INTERSECTION;
+ if (_cairo_int64_negative (den_det) ^ _cairo_int64_negative (R))
+ return CAIRO_BO_STATUS_NO_INTERSECTION;
+ if (_cairo_int64_negative (den_det)) {
+ if (_cairo_int64_ge (den_det, R))
+ return CAIRO_BO_STATUS_NO_INTERSECTION;
+ } else {
+ if (_cairo_int64_le (den_det, R))
+ return CAIRO_BO_STATUS_NO_INTERSECTION;
+ }
+
+ /* We now know that the two lines should intersect within range. */
+
a_det = det32_64 (a->top.x, a->top.y,
a->bottom.x, a->bottom.y);
b_det = det32_64 (b->top.x, b->top.y,
b->bottom.x, b->bottom.y);
/* x = det (a_det, dx1, b_det, dx2) / den_det */
qr = _cairo_int_96by64_32x64_divrem (det64x32_128 (a_det, dx1,
b_det, dx2),
@@ -810,81 +935,83 @@ static void
static cairo_bo_event_t *
_cairo_bo_event_dequeue (cairo_bo_event_queue_t *event_queue)
{
skip_elt_t *elt = event_queue->intersection_queue.chains[0];
cairo_bo_event_t *intersection = elt ? SKIP_ELT_TO_EVENT (elt) : NULL;
cairo_bo_event_t *startstop;
- if (event_queue->next_startstop_event_index == event_queue->num_startstop_events)
+ startstop = *event_queue->sorted_startstop_event_ptrs;
+ if (startstop == NULL)
return intersection;
- startstop = event_queue->sorted_startstop_event_ptrs[
- event_queue->next_startstop_event_index];
- if (!intersection || cairo_bo_event_compare (startstop, intersection) <= 0)
+ if (intersection == NULL ||
+ cairo_bo_event_compare (startstop, intersection) <= 0)
{
- event_queue->next_startstop_event_index++;
+ event_queue->sorted_startstop_event_ptrs++;
return startstop;
}
+
return intersection;
}
+CAIRO_COMBSORT_DECLARE (_cairo_bo_event_queue_sort,
+ cairo_bo_event_t *,
+ cairo_bo_event_compare_pointers)
+
static cairo_status_t
_cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
cairo_bo_edge_t *edges,
int num_edges)
{
int i;
cairo_bo_event_t *events, **sorted_event_ptrs;
unsigned num_events = 2*num_edges;
- memset (event_queue, 0, sizeof(*event_queue));
-
- _cairo_skip_list_init (&event_queue->intersection_queue,
- cairo_bo_event_compare_abstract,
- 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 = _cairo_malloc_ab (num_events, sizeof (cairo_bo_event_t) + sizeof(cairo_bo_event_t*));
- if (events == NULL)
+ events = _cairo_malloc_ab_plus_c (num_events,
+ sizeof (cairo_bo_event_t) +
+ sizeof (cairo_bo_event_t *),
+ sizeof (cairo_bo_event_t *));
+ if (unlikely (events == NULL))
return _cairo_error (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->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];
+ sorted_event_ptrs[i] = &events[2*i];
+ sorted_event_ptrs[i+num_edges] = &events[2*i+1];
/* Initialize "middle" to top */
edges[i].middle = edges[i].top;
_cairo_bo_event_init (&events[2*i],
CAIRO_BO_EVENT_TYPE_START,
&edges[i], NULL,
edges[i].top);
_cairo_bo_event_init (&events[2*i+1],
CAIRO_BO_EVENT_TYPE_STOP,
&edges[i], NULL,
edges[i].bottom);
}
- qsort (sorted_event_ptrs, num_events,
- sizeof(cairo_bo_event_t *),
- cairo_bo_event_compare_pointers);
+ _cairo_bo_event_queue_sort (sorted_event_ptrs, num_events);
+ event_queue->sorted_startstop_event_ptrs[num_events] = NULL;
+
+ _cairo_skip_list_init (&event_queue->intersection_queue,
+ cairo_bo_event_compare_abstract,
+ sizeof (cairo_bo_event_t));
+
return CAIRO_STATUS_SUCCESS;
}
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)
@@ -925,18 +1052,19 @@ static cairo_status_t
return _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));
+ _sweep_line_elt_compare,
+ sizeof (sweep_line_elt_t));
+
sweep_line->head = NULL;
sweep_line->tail = NULL;
sweep_line->current_y = 0;
}
static void
_cairo_bo_sweep_line_fini (cairo_bo_sweep_line_t *sweep_line)
{
@@ -947,18 +1075,18 @@ static cairo_status_t
_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)
+ 1 /* unique inserts*/);
+ if (unlikely (sweep_line_elt == NULL))
return _cairo_error (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;
@@ -978,17 +1106,18 @@ static cairo_status_t
}
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;
- _cairo_skip_list_delete_given (&sweep_line->active_edges, &edge->sweep_line_elt->elt);
+ _cairo_skip_list_delete_given (&sweep_line->active_edges,
+ &edge->sweep_line_elt->elt);
left_next = &sweep_line->head;
if (edge->prev)
left_next = &edge->prev->next;
right_prev = &sweep_line->tail;
if (edge->next)
right_prev = &edge->next->prev;
@@ -1307,20 +1436,17 @@ static cairo_status_t
cairo_bo_traps_t *bo_traps)
{
cairo_status_t status;
int in_out = 0;
cairo_bo_edge_t *edge;
for (edge = head; edge; edge = edge->next) {
if (fill_rule == CAIRO_FILL_RULE_WINDING) {
- if (edge->reversed)
- in_out++;
- else
- in_out--;
+ in_out += edge->dir;
if (in_out == 0) {
status = _cairo_bo_edge_end_trap (edge, top, bo_traps);
if (status)
return status;
continue;
}
} else {
in_out++;
@@ -1359,21 +1485,25 @@ static cairo_status_t
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;
+ if (num_edges == 0)
+ return CAIRO_STATUS_SUCCESS;
+
status = _cairo_bo_event_queue_init (&event_queue, edges, num_edges);
if (status)
return status;
_cairo_bo_sweep_line_init (&sweep_line);
+
_cairo_bo_traps_init (&bo_traps, traps, xmin, ymin, xmax, ymax);
#if DEBUG_PRINT_STATE
print_state ("After initializing", &event_queue, &sweep_line);
#endif
while (1)
{
@@ -1527,21 +1657,20 @@ cairo_status_t
int num_bo_edges;
int i;
if (0 == polygon->num_edges)
return CAIRO_STATUS_SUCCESS;
has_limits = _cairo_traps_get_limit (traps, &limit);
- if (polygon->num_edges < ARRAY_LENGTH (stack_edges)) {
- edges = stack_edges;
- } else {
+ edges = stack_edges;
+ if (polygon->num_edges > ARRAY_LENGTH (stack_edges)) {
edges = _cairo_malloc_ab (polygon->num_edges, sizeof (cairo_bo_edge_t));
- if (edges == NULL)
+ if (unlikely (edges == NULL))
return _cairo_error (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);
@@ -1599,20 +1728,17 @@ cairo_status_t
assert (top.y < bot.y &&
"BUG: clamping the input range flipped the "
"orientation of an edge");
edge->top.x = top.x;
edge->top.y = top.y;
edge->bottom.x = bot.x;
edge->bottom.y = bot.y;
- /* XXX: The 'clockWise' name that cairo_polygon_t uses is
- * totally bogus. It's really a (negated!) description of
- * whether the edge is reversed. */
- edge->reversed = (! polygon->edges[i].clockWise);
+ edge->dir = polygon->edges[i].dir;
edge->deferred_trap = NULL;
edge->prev = NULL;
edge->next = NULL;
edge->sweep_line_elt = NULL;
num_bo_edges++;
}
--- a/gfx/cairo/cairo/src/cairo-beos-surface.cpp
+++ b/gfx/cairo/cairo/src/cairo-beos-surface.cpp
@@ -31,30 +31,31 @@
* The Initial Developer of the Original Code is Christian Biesinger
* <cbiesinger@web.de>
*
* Contributor(s):
*/
// This is a C++ file in order to use the C++ BeOS API
+#include "cairoint.h"
+
+#include "cairo-beos.h"
+
#include <new>
#include <Bitmap.h>
#include <Region.h>
#if 0
#include <DirectWindow.h>
#endif
#include <Screen.h>
#include <Window.h>
#include <Locker.h>
-#include "cairoint.h"
-#include "cairo-beos.h"
-
#define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)(CAIRO_STATUS_SUCCESS)
struct cairo_beos_surface_t {
cairo_surface_t base;
BView* view;
/*
@@ -253,17 +254,17 @@ unpremultiply_rgba (unsigned char* data,
* The returned data must be freed with free().
**/
static unsigned char*
premultiply_rgba (unsigned char* data,
int width,
int height,
int stride)
{
- unsigned char* retdata = reinterpret_cast<unsigned char*>(malloc(stride * height));
+ unsigned char* retdata = reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height, stride));
if (!retdata)
return NULL;
unsigned char* end = data + stride * height;
for (unsigned char* in = data, *out = retdata;
in < end;
in += stride, out += stride)
{
@@ -316,17 +317,17 @@ static cairo_image_surface_t*
int width = bounds.IntegerWidth() + 1;
int height = bounds.IntegerHeight() + 1;
unsigned char* premultiplied;
if (cformat == CAIRO_FORMAT_ARGB32) {
premultiplied = premultiply_rgba(bits, width, height,
bitmap->BytesPerRow());
} else {
premultiplied = reinterpret_cast<unsigned char*>(
- malloc(bitmap->BytesPerRow() * height));
+ _cairo_malloc_ab(bitmap->BytesPerRow(), height));
if (premultiplied)
memcpy(premultiplied, bits, bitmap->BytesPerRow() * height);
}
if (!premultiplied)
return NULL;
cairo_image_surface_t* surf = reinterpret_cast<cairo_image_surface_t*>
(cairo_image_surface_create_for_data(premultiplied,
@@ -889,16 +890,18 @@ static const struct _cairo_surface_backe
_cairo_beos_surface_acquire_source_image,
_cairo_beos_surface_release_source_image,
_cairo_beos_surface_acquire_dest_image,
_cairo_beos_surface_release_dest_image,
NULL, /* clone_similar */
_cairo_beos_surface_composite, /* composite */
_cairo_beos_surface_fill_rectangles,
NULL, /* composite_trapezoids */
+ NULL, /* create_span_renderer */
+ NULL, /* check_span_renderer */
NULL, /* copy_page */
NULL, /* show_page */
_cairo_beos_surface_set_clip_region,
NULL, /* intersect_clip_path */
_cairo_beos_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
@@ -940,17 +943,17 @@ static cairo_surface_t *
/**
* cairo_beos_surface_create:
* @view: The view to draw on
*
* Creates a Cairo surface that draws onto a BeOS BView.
* The caller must ensure that the view does not get deleted before the surface.
* If the view is attached to a bitmap rather than an on-screen window, use
- * cairo_beos_surface_create_for_bitmap instead of this function.
+ * cairo_beos_surface_create_for_bitmap() instead of this function.
**/
cairo_surface_t *
cairo_beos_surface_create (BView* view)
{
return cairo_beos_surface_create_for_bitmap(view, NULL);
}
/**
@@ -971,38 +974,8 @@ cairo_beos_surface_create (BView* view)
* The view must already be attached to the bitmap.
**/
cairo_surface_t *
cairo_beos_surface_create_for_bitmap (BView* view,
BBitmap* bmp)
{
return _cairo_beos_surface_create_internal(view, bmp);
}
-
-// ---------------------------------------------------------------------------
-// Cairo uses locks without explicit initialization. To support that, we
-// provide a class here which manages the locks and is in global scope, so the
-// compiler will instantiate it on library load and destroy it on library
-// unload.
-
-class BeLocks {
- public:
- BLocker cairo_toy_font_face_hash_table_mutex;
- BLocker cairo_scaled_font_map_mutex;
- BLocker cairo_ft_unscaled_font_map_mutex;
-};
-
-static BeLocks locks;
-
-void* cairo_toy_font_face_hash_table_mutex = &locks.cairo_toy_font_face_hash_table_mutex;
-void* cairo_scaled_font_map_mutex = &locks.cairo_scaled_font_map_mutex;
-void* cairo_ft_unscaled_font_map_mutex = &locks.cairo_ft_unscaled_font_map_mutex;
-
-void _cairo_beos_lock (void* locker) {
- BLocker* bLocker = reinterpret_cast<BLocker*>(locker);
- bLocker->Lock();
-}
-
-void _cairo_beos_unlock (void* locker) {
- BLocker* bLocker = reinterpret_cast<BLocker*>(locker);
- bLocker->Unlock();
-}
-
--- a/gfx/cairo/cairo/src/cairo-cache-private.h
+++ b/gfx/cairo/cairo/src/cairo-cache-private.h
@@ -92,35 +92,39 @@ typedef cairo_bool_t
(*cairo_cache_keys_equal_func_t) (const void *key_a, const void *key_b);
typedef void
(*cairo_cache_callback_func_t) (void *entry,
void *closure);
cairo_private cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
+ cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size);
cairo_private void
_cairo_cache_destroy (cairo_cache_t *cache);
cairo_private void
_cairo_cache_freeze (cairo_cache_t *cache);
cairo_private void
_cairo_cache_thaw (cairo_cache_t *cache);
-cairo_private cairo_bool_t
+cairo_private void *
_cairo_cache_lookup (cairo_cache_t *cache,
- cairo_cache_entry_t *key,
- cairo_cache_entry_t **entry_return);
+ cairo_cache_entry_t *key);
cairo_private cairo_status_t
_cairo_cache_insert (cairo_cache_t *cache,
cairo_cache_entry_t *entry);
cairo_private void
-_cairo_cache_foreach (cairo_cache_t *cache,
+_cairo_cache_remove (cairo_cache_t *cache,
+ cairo_cache_entry_t *entry);
+
+cairo_private void
+_cairo_cache_foreach (cairo_cache_t *cache,
cairo_cache_callback_func_t cache_callback,
void *closure);
#endif
--- a/gfx/cairo/cairo/src/cairo-cache.c
+++ b/gfx/cairo/cairo/src/cairo-cache.c
@@ -34,62 +34,63 @@
* Keith Packard <keithp@keithp.com>
* Graydon Hoare <graydon@redhat.com>
* Carl Worth <cworth@cworth.org>
*/
#include "cairoint.h"
static void
-_cairo_cache_remove (cairo_cache_t *cache,
- cairo_cache_entry_t *entry);
+_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
+ unsigned long additional);
-static void
-_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
- unsigned long additional);
+static cairo_bool_t
+_cairo_cache_entry_is_non_zero (const void *entry)
+{
+ return ((const cairo_cache_entry_t *) entry)->size;
+}
static cairo_status_t
_cairo_cache_init (cairo_cache_t *cache,
cairo_cache_keys_equal_func_t keys_equal,
+ cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
{
cache->hash_table = _cairo_hash_table_create (keys_equal);
- if (cache->hash_table == NULL)
+ if (unlikely (cache->hash_table == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (predicate == NULL)
+ predicate = _cairo_cache_entry_is_non_zero;
+ cache->predicate = predicate;
cache->entry_destroy = entry_destroy;
cache->max_size = max_size;
cache->size = 0;
cache->freeze_count = 0;
return CAIRO_STATUS_SUCCESS;
}
static void
+_cairo_cache_pluck (void *entry, void *closure)
+{
+ _cairo_cache_remove (closure, entry);
+}
+
+static void
_cairo_cache_fini (cairo_cache_t *cache)
{
- cairo_cache_entry_t *entry;
-
- /* We have to manually remove all entries from the cache ourselves
- * rather than relying on _cairo_hash_table_destroy() to do that
- * since otherwise the cache->entry_destroy callback would not get
- * called on each entry. */
-
- while (1) {
- entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
- if (entry == NULL)
- break;
- _cairo_cache_remove (cache, entry);
- }
-
+ _cairo_hash_table_foreach (cache->hash_table,
+ _cairo_cache_pluck,
+ cache);
+ assert (cache->size == 0);
_cairo_hash_table_destroy (cache->hash_table);
- cache->size = 0;
}
/**
* _cairo_cache_create:
* @keys_equal: a function to return %TRUE if two keys are equal
* @entry_destroy: destroy notifier for cache entries
* @max_size: the maximum size for this cache
* Returns: the newly created #cairo_cache_t
@@ -118,30 +119,35 @@ static void
* in some cases the memory overhead of adding a reference count to
* the entry would be objectionable. In such cases, the
* _cairo_cache_freeze() and _cairo_cache_thaw() calls can be
* used to establish a window during which no automatic removal of
* entries will occur.
**/
cairo_cache_t *
_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal,
+ cairo_cache_predicate_func_t predicate,
cairo_destroy_func_t entry_destroy,
unsigned long max_size)
{
cairo_status_t status;
cairo_cache_t *cache;
cache = malloc (sizeof (cairo_cache_t));
- if (cache == NULL) {
+ if (unlikely (cache == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
- status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size);
- if (status) {
+ status = _cairo_cache_init (cache,
+ keys_equal,
+ predicate,
+ entry_destroy,
+ max_size);
+ if (unlikely (status)) {
free (cache);
return NULL;
}
return cache;
}
/**
@@ -217,42 +223,41 @@ void
* Performs a lookup in @cache looking for an entry which has a key
* that matches @key, (as determined by the keys_equal() function
* passed to _cairo_cache_create()).
*
* Return value: %TRUE if there is an entry in the cache that matches
* @key, (which will now be in *entry_return). %FALSE otherwise, (in
* which case *entry_return will be %NULL).
**/
-cairo_bool_t
+void *
_cairo_cache_lookup (cairo_cache_t *cache,
- cairo_cache_entry_t *key,
- cairo_cache_entry_t **entry_return)
+ cairo_cache_entry_t *key)
{
return _cairo_hash_table_lookup (cache->hash_table,
- (cairo_hash_entry_t *) key,
- (cairo_hash_entry_t **) entry_return);
+ (cairo_hash_entry_t *) key);
}
/**
* _cairo_cache_remove_random:
* @cache: a cache
*
* Remove a random entry from the cache.
*
* Return value: %TRUE if an entry was successfully removed.
* %FALSE if there are no entries that can be removed.
**/
static cairo_bool_t
_cairo_cache_remove_random (cairo_cache_t *cache)
{
cairo_cache_entry_t *entry;
- entry = _cairo_hash_table_random_entry (cache->hash_table, NULL);
- if (entry == NULL)
+ entry = _cairo_hash_table_random_entry (cache->hash_table,
+ cache->predicate);
+ if (unlikely (entry == NULL))
return FALSE;
_cairo_cache_remove (cache, entry);
return TRUE;
}
/**
@@ -295,37 +300,32 @@ cairo_status_t
cairo_cache_entry_t *entry)
{
cairo_status_t status;
_cairo_cache_shrink_to_accommodate (cache, entry->size);
status = _cairo_hash_table_insert (cache->hash_table,
(cairo_hash_entry_t *) entry);
- if (status)
+ if (unlikely (status))
return status;
cache->size += entry->size;
return CAIRO_STATUS_SUCCESS;
}
/**
* _cairo_cache_remove:
* @cache: a cache
* @entry: an entry that exists in the cache
*
* Remove an existing entry from the cache.
- *
- * (Note: If any caller wanted access to a non-static version of this
- * function, an improved version would require only a key rather than
- * an entry. Fixing that would require fixing _cairo_hash_table_remove
- * to return (a copy of?) the entry being removed.)
**/
-static void
+void
_cairo_cache_remove (cairo_cache_t *cache,
cairo_cache_entry_t *entry)
{
cache->size -= entry->size;
_cairo_hash_table_remove (cache->hash_table,
(cairo_hash_entry_t *) entry);
@@ -338,26 +338,38 @@ static void
* @cache: a cache
* @cache_callback: function to be called for each entry
* @closure: additional argument to be passed to @cache_callback
*
* Call @cache_callback for each entry in the cache, in a
* non-specified order.
**/
void
-_cairo_cache_foreach (cairo_cache_t *cache,
+_cairo_cache_foreach (cairo_cache_t *cache,
cairo_cache_callback_func_t cache_callback,
void *closure)
{
_cairo_hash_table_foreach (cache->hash_table,
cache_callback,
closure);
}
unsigned long
_cairo_hash_string (const char *c)
{
/* This is the djb2 hash. */
- unsigned long hash = 5381;
+ unsigned long hash = _CAIRO_HASH_INIT_VALUE;
while (c && *c)
hash = ((hash << 5) + hash) + *c++;
return hash;
}
+
+unsigned long
+_cairo_hash_bytes (unsigned long hash,
+ const void *ptr,
+ unsigned int length)
+{
+ const uint8_t *bytes = ptr;
+ /* This is the djb2 hash. */
+ while (length--)
+ hash = ((hash << 5) + hash) + *bytes++;
+ return hash;
+}
--- a/gfx/cairo/cairo/src/cairo-cff-subset.c
+++ b/gfx/cairo/cairo/src/cairo-cff-subset.c
@@ -103,16 +103,17 @@ typedef struct _cairo_cff_font {
/* Font Data */
unsigned char *data;
unsigned long data_length;
unsigned char *current_ptr;
unsigned char *data_end;
cff_header_t *header;
char *font_name;
+ char *ps_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;
@@ -293,17 +294,17 @@ cff_index_read (cairo_array_t *index, un
end = decode_index_offset (p, offset_size);
p += offset_size;
if (p > end_ptr)
return CAIRO_INT_STATUS_UNSUPPORTED;
element.length = end - start;
element.is_copy = FALSE;
element.data = data + start;
status = _cairo_array_append (index, &element);
- if (status)
+ if (unlikely (status))
return status;
start = end;
}
p = data + end;
}
*ptr = p;
return CAIRO_STATUS_SUCCESS;
@@ -319,17 +320,17 @@ cff_index_write (cairo_array_t *index, c
cff_index_element_t *element;
uint16_t count;
unsigned char buf[5];
cairo_status_t status;
num_elem = _cairo_array_num_elements (index);
count = cpu_to_be16 ((uint16_t) num_elem);
status = _cairo_array_append_multiple (output, &count, 2);
- if (status)
+ if (unlikely (status))
return status;
if (num_elem == 0)
return CAIRO_STATUS_SUCCESS;
/* Find maximum offset to determine offset size */
offset = 1;
for (i = 0; i < num_elem; i++) {
@@ -342,40 +343,40 @@ cff_index_write (cairo_array_t *index, c
offset_size = 2;
else if (offset < 0x1000000)
offset_size = 3;
else
offset_size = 4;
buf[0] = (unsigned char) offset_size;
status = _cairo_array_append (output, buf);
- if (status)
+ if (unlikely (status))
return status;
offset = 1;
encode_index_offset (buf, offset_size, offset);
status = _cairo_array_append_multiple (output, buf, offset_size);
- if (status)
+ if (unlikely (status))
return status;
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)
+ if (unlikely (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)
+ if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cff_index_append (cairo_array_t *index, unsigned char *object , int length)
{
@@ -394,23 +395,23 @@ cff_index_append_copy (cairo_array_t *in
unsigned int length)
{
cff_index_element_t element;
cairo_status_t status;
element.length = length;
element.is_copy = TRUE;
element.data = malloc (element.length);
- if (element.data == NULL)
+ if (unlikely (element.data == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
memcpy (element.data, object, element.length);
status = _cairo_array_append (index, &element);
- if (status) {
+ if (unlikely (status)) {
free (element.data);
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static void
@@ -435,50 +436,50 @@ static cairo_bool_t
return op_a->operator == op_b->operator;
}
static cairo_status_t
cff_dict_init (cairo_hash_table_t **dict)
{
*dict = _cairo_hash_table_create (_cairo_cff_dict_equal);
- if (*dict == NULL)
- return CAIRO_STATUS_NO_MEMORY;
+ if (unlikely (*dict == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
static void
_cairo_dict_init_key (cff_dict_operator_t *key, int operator)
{
key->base.hash = (unsigned long) operator;
key->operator = operator;
}
static cairo_status_t
cff_dict_create_operator (int operator,
unsigned char *operand,
- int operand_length,
+ int size,
cff_dict_operator_t **out)
{
cff_dict_operator_t *op;
op = malloc (sizeof (cff_dict_operator_t));
- if (op == NULL)
+ if (unlikely (op == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_dict_init_key (op, operator);
- op->operand = malloc (operand_length);
- if (op->operand == NULL) {
+ op->operand = malloc (size);
+ if (unlikely (op->operand == NULL)) {
free (op);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
- memcpy (op->operand, operand, operand_length);
- op->operand_length = operand_length;
+ memcpy (op->operand, operand, size);
+ op->operand_length = size;
op->operand_offset = -1;
*out = op;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cff_dict_read (cairo_hash_table_t *dict, unsigned char *p, int dict_size)
@@ -491,31 +492,31 @@ cff_dict_read (cairo_hash_table_t *dict,
int size;
end = p + dict_size;
_cairo_array_init (&operands, 1);
while (p < end) {
size = operand_length (p);
if (size != 0) {
status = _cairo_array_append_multiple (&operands, p, size);
- if (status)
+ if (unlikely (status))
goto fail;
p += size;
} else {
p = decode_operator (p, &operator);
status = cff_dict_create_operator (operator,
_cairo_array_index (&operands, 0),
_cairo_array_num_elements (&operands),
&op);
- if (status)
+ if (unlikely (status))
goto fail;
status = _cairo_hash_table_insert (dict, &op->base);
- if (status)
+ if (unlikely (status))
goto fail;
_cairo_array_truncate (&operands, 0);
}
}
fail:
_cairo_array_fini (&operands);
@@ -524,36 +525,34 @@ fail:
}
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))
- {
+ op = _cairo_hash_table_lookup (dict, &key.base);
+ if (op != NULL) {
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);
- if (_cairo_hash_table_lookup (dict, &key.base,
- (cairo_hash_entry_t **) &op))
- {
+ op = _cairo_hash_table_lookup (dict, &key.base);
+ if (op != NULL) {
*size = op->operand_length;
return op->operand;
}
return NULL;
}
static cairo_status_t
@@ -561,52 +560,50 @@ cff_dict_set_operands (cairo_hash_table_
unsigned short operator,
unsigned char *operand,
int size)
{
cff_dict_operator_t key, *op;
cairo_status_t status;
_cairo_dict_init_key (&key, operator);
- if (_cairo_hash_table_lookup (dict, &key.base,
- (cairo_hash_entry_t **) &op))
- {
+ op = _cairo_hash_table_lookup (dict, &key.base);
+ if (op != NULL) {
free (op->operand);
op->operand = malloc (size);
- if (op->operand == NULL)
+ if (unlikely (op->operand == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
memcpy (op->operand, operand, size);
op->operand_length = size;
}
else
{
status = cff_dict_create_operator (operator, operand, size, &op);
- if (status)
+ if (unlikely (status))
return status;
status = _cairo_hash_table_insert (dict, &op->base);
- if (status)
+ if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static int
cff_dict_get_location (cairo_hash_table_t *dict,
unsigned short operator,
int *size)
{
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))
- {
+ op = _cairo_hash_table_lookup (dict, &key.base);
+ if (op != NULL) {
*size = op->operand_length;
return op->operand_offset;
}
return -1;
}
typedef struct _dict_write_info {
@@ -655,38 +652,39 @@ cff_dict_write (cairo_hash_table_t *dict
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))
+ op = _cairo_hash_table_lookup (dict, &key.base);
+ if (op != NULL)
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_entry_pluck (void *_entry, void *dict)
+{
+ cff_dict_operator_t *entry = _entry;
+
+ _cairo_hash_table_remove (dict, &entry->base);
+ free (entry->operand);
+ free (entry);
+}
+
+static void
cff_dict_fini (cairo_hash_table_t *dict)
{
- cff_dict_operator_t *entry;
-
- while (1) {
- entry = _cairo_hash_table_random_entry (dict, NULL);
- if (entry == NULL)
- break;
- free (entry->operand);
- _cairo_hash_table_remove (dict, (cairo_hash_entry_t *) entry);
- free (entry);
- }
+ _cairo_hash_table_foreach (dict, _cff_dict_entry_pluck, dict);
_cairo_hash_table_destroy (dict);
}
static cairo_int_status_t
cairo_cff_font_read_header (cairo_cff_font_t *font)
{
if (font->data_length < sizeof (cff_header_t))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -723,44 +721,44 @@ cairo_cff_font_read_private_dict (cairo_
unsigned char buf[10];
unsigned char *end_buf;
int offset;
int i;
unsigned char *operand;
unsigned char *p;
status = cff_dict_read (private_dict, ptr, size);
- if (status)
+ if (unlikely (status))
return status;
operand = cff_dict_get_operands (private_dict, LOCAL_SUB_OP, &i);
if (operand) {
decode_integer (operand, &offset);
p = ptr + offset;
status = cff_index_read (local_sub_index, &p, font->data_end);
- if (status)
+ if (unlikely (status))
return status;
/* Use maximum sized encoding to reserve space for later modification. */
end_buf = encode_integer_max (buf, 0);
status = cff_dict_set_operands (private_dict, LOCAL_SUB_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
return status;
}
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)
+ if (unlikely (font->fdselect == NULL))
return _cairo_error (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) {
@@ -792,75 +790,75 @@ cairo_cff_font_read_cid_fontdict (cairo_
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)
+ if (unlikely (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) {
+ if (unlikely (font->fd_dict == NULL)) {
status = _cairo_error (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) {
+ if (unlikely (font->fd_private_dict == NULL)) {
status = _cairo_error (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) {
+ if (unlikely (font->fd_local_sub_index == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail;
}
for (i = 0; i < font->num_fontdicts; i++) {
status = cff_dict_init (&font->fd_dict[i]);
- if (status)
+ if (unlikely (status))
goto fail;
element = _cairo_array_index (&index, i);
status = cff_dict_read (font->fd_dict[i], element->data, element->length);
- if (status)
+ if (unlikely (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);
status = cff_dict_init (&font->fd_private_dict[i]);
- if (status)
+ if (unlikely (status))
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)
+ if (unlikely (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)
+ if (unlikely (status))
goto fail;
}
return CAIRO_STATUS_SUCCESS;
fail:
cff_index_fini (&index);
@@ -877,82 +875,82 @@ cairo_cff_font_read_top_dict (cairo_cff_
unsigned char *operand;
cairo_int_status_t status;
unsigned char *p;
int size;
int offset;
cff_index_init (&index);
status = cff_index_read (&index, &font->current_ptr, font->data_end);
- if (status)
+ if (unlikely (status))
goto fail;
element = _cairo_array_index (&index, 0);
status = cff_dict_read (font->top_dict, element->data, element->length);
- if (status)
+ if (unlikely (status))
goto fail;
if (cff_dict_get_operands (font->top_dict, ROS_OP, &size) != NULL)
font->is_cid = TRUE;
else
font->is_cid = FALSE;
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)
+ if (unlikely (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);
status = cairo_cff_font_read_fdselect (font, font->data + offset);
- if (status)
+ if (unlikely (status))
goto fail;
operand = cff_dict_get_operands (font->top_dict, FDARRAY_OP, &size);
decode_integer (operand, &offset);
status = cairo_cff_font_read_cid_fontdict (font, font->data + offset);
- if (status)
+ if (unlikely (status))
goto fail;
} else {
operand = cff_dict_get_operands (font->top_dict, PRIVATE_OP, &size);
operand = decode_integer (operand, &size);
decode_integer (operand, &offset);
status = cairo_cff_font_read_private_dict (font,
font->private_dict,
&font->local_sub_index,
font->data + offset,
size);
- if (status)
+ if (unlikely (status))
goto fail;
}
/* Use maximum sized encoding to reserve space for later modification. */
end_buf = encode_integer_max (buf, 0);
status = cff_dict_set_operands (font->top_dict,
CHARSTRINGS_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
goto fail;
status = cff_dict_set_operands (font->top_dict,
FDSELECT_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
goto fail;
status = cff_dict_set_operands (font->top_dict,
FDARRAY_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
goto fail;
status = cff_dict_set_operands (font->top_dict,
CHARSET_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
goto fail;
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);
@@ -990,17 +988,17 @@ static const font_read_t font_read_funcs
static cairo_int_status_t
cairo_cff_font_read_font (cairo_cff_font_t *font)
{
cairo_int_status_t status;
unsigned int i;
for (i = 0; i < ARRAY_LENGTH (font_read_funcs); i++) {
status = font_read_funcs[i] (font);
- if (status)
+ if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_set_ros_strings (cairo_cff_font_t *font)
@@ -1011,36 +1009,36 @@ cairo_cff_font_set_ros_strings (cairo_cf
int sid1, sid2;
const char *registry = "Adobe";
const char *ordering = "Identity";
sid1 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
status = cff_index_append_copy (&font->strings_subset_index,
(unsigned char *)registry,
strlen(registry));
- if (status)
+ if (unlikely (status))
return status;
sid2 = NUM_STD_STRINGS + _cairo_array_num_elements (&font->strings_subset_index);
status = cff_index_append_copy (&font->strings_subset_index,
(unsigned char *)ordering,
strlen(ordering));
- if (status)
+ if (unlikely (status))
return status;
p = encode_integer (buf, sid1);
p = encode_integer (p, sid2);
p = encode_integer (p, 0);
status = cff_dict_set_operands (font->top_dict, ROS_OP, buf, p - buf);
- if (status)
+ if (unlikely (status))
return status;
p = encode_integer (buf, font->scaled_font_subset->num_glyphs);
status = cff_dict_set_operands (font->top_dict, CIDCOUNT_OP, buf, p - buf);
- if (status)
+ if (unlikely (status))
return status;
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_subset_dict_string(cairo_cff_font_t *font,
cairo_hash_table_t *dict,
@@ -1059,22 +1057,22 @@ cairo_cff_font_subset_dict_string(cairo_
decode_integer (p, &sid);
if (sid < NUM_STD_STRINGS)
return CAIRO_STATUS_SUCCESS;
element = _cairo_array_index (&font->strings_index, sid - NUM_STD_STRINGS);
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)
+ if (unlikely (status))
return status;
p = encode_integer (buf, sid);
status = cff_dict_set_operands (dict, operator, buf, p - buf);
- if (status)
+ if (unlikely (status))
return status;
return CAIRO_STATUS_SUCCESS;
}
static const int dict_strings[] = {
VERSION_OP,
NOTICE_OP,
@@ -1091,17 +1089,17 @@ static cairo_status_t
cairo_cff_font_subset_dict_strings (cairo_cff_font_t *font,
cairo_hash_table_t *dict)
{
cairo_status_t status;
unsigned int i;
for (i = 0; i < ARRAY_LENGTH (dict_strings); i++) {
status = cairo_cff_font_subset_dict_string (font, dict, dict_strings[i]);
- if (status)
+ if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_subset_charstrings (cairo_cff_font_t *font)
@@ -1111,45 +1109,45 @@ cairo_cff_font_subset_charstrings (cairo
cairo_status_t 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)
+ if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
cairo_cff_font_subset_fontdict (cairo_cff_font_t *font)
{
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)
+ if (unlikely (font->fdselect_subset == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->fd_subset_map = calloc (font->num_fontdicts, sizeof (int));
- if (font->fd_subset_map == NULL)
+ if (unlikely (font->fd_subset_map == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->private_dict_offset = calloc (font->num_fontdicts, sizeof (int));
- if (font->private_dict_offset == NULL)
+ if (unlikely (font->private_dict_offset == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
reverse_map = calloc (font->num_fontdicts, sizeof (int));
- if (reverse_map == NULL)
+ if (unlikely (reverse_map == NULL))
return _cairo_error (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]];
@@ -1169,97 +1167,97 @@ static cairo_status_t
cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font)
{
unsigned char buf[100];
unsigned char *end_buf;
cairo_status_t status;
font->num_fontdicts = 1;
font->fd_dict = malloc (sizeof (cairo_hash_table_t *));
- if (font->fd_dict == NULL)
+ if (unlikely (font->fd_dict == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
if (cff_dict_init (&font->fd_dict[0])) {
free (font->fd_dict);
font->fd_dict = NULL;
font->num_fontdicts = 0;
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
font->fd_subset_map = malloc (sizeof (int));
- if (font->fd_subset_map == NULL)
+ if (unlikely (font->fd_subset_map == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->private_dict_offset = malloc (sizeof (int));
- if (font->private_dict_offset == NULL)
+ if (unlikely (font->private_dict_offset == NULL))
return _cairo_error (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);
status = cff_dict_set_operands (font->fd_dict[0], PRIVATE_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (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;
unsigned int i;
status = cairo_cff_font_subset_dict_strings (font, font->top_dict);
- if (status)
+ if (unlikely (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)
+ if (unlikely (status))
return status;
status = cairo_cff_font_subset_dict_strings (font, font->fd_private_dict[font->fd_subset_map[i]]);
- if (status)
+ if (unlikely (status))
return status;
}
} else {
status = cairo_cff_font_subset_dict_strings (font, font->private_dict);
}
return status;
}
static cairo_status_t
cairo_cff_font_subset_font (cairo_cff_font_t *font)
{
cairo_status_t status;
status = cairo_cff_font_set_ros_strings (font);
- if (status)
+ if (unlikely (status))
return status;
status = cairo_cff_font_subset_charstrings (font);
- if (status)
+ if (unlikely (status))
return status;
if (font->is_cid)
status = cairo_cff_font_subset_fontdict (font);
else
status = cairo_cff_font_create_cid_fontdict (font);
- if (status)
+ if (unlikely (status))
return status;
status = cairo_cff_font_subset_strings (font);
- if (status)
+ if (unlikely (status))
return status;
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
@@ -1297,21 +1295,21 @@ cairo_cff_font_write_name (cairo_cff_fon
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_array_t index;
cff_index_init (&index);
status = cff_index_append_copy (&index,
(unsigned char *) font->subset_font_name,
strlen(font->subset_font_name));
- if (status)
+ if (unlikely (status))
goto FAIL;
status = cff_index_write (&index, &font->output);
- if (status)
+ if (unlikely (status))
goto FAIL;
FAIL:
cff_index_fini (&index);
return status;
}
@@ -1325,37 +1323,37 @@ cairo_cff_font_write_top_dict (cairo_cff
int dict_start, dict_size;
int offset_size = 4;
cairo_status_t status;
/* Write an index containing the top dict */
count = cpu_to_be16 (1);
status = _cairo_array_append_multiple (&font->output, &count, 2);
- if (status)
+ if (unlikely (status))
return status;
buf[0] = offset_size;
status = _cairo_array_append (&font->output, buf);
- if (status)
+ if (unlikely (status))
return status;
encode_index_offset (buf, offset_size, 1);
status = _cairo_array_append_multiple (&font->output, buf, offset_size);
- if (status)
+ if (unlikely (status))
return status;
/* Reserve space for last element of offset array and update after
* dict is written */
offset_index = _cairo_array_num_elements (&font->output);
status = _cairo_array_append_multiple (&font->output, buf, offset_size);
- if (status)
+ if (unlikely (status))
return status;
dict_start = _cairo_array_num_elements (&font->output);
status = cff_dict_write (font->top_dict, &font->output);
- if (status)
+ if (unlikely (status))
return status;
dict_size = _cairo_array_num_elements (&font->output) - dict_start;
encode_index_offset (buf, offset_size, dict_size + 1);
p = _cairo_array_index (&font->output, offset_index);
memcpy (p, buf, offset_size);
return CAIRO_STATUS_SUCCESS;
@@ -1380,31 +1378,31 @@ cairo_cff_font_write_fdselect (cairo_cff
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)
+ if (unlikely (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)
+ if (unlikely (status))
return status;
}
} else {
unsigned char byte;
uint16_t word;
status = _cairo_array_grow_by (&font->output, 9);
- if (status)
+ if (unlikely (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);
@@ -1430,17 +1428,17 @@ static cairo_status_t
cairo_cff_font_write_charset (cairo_cff_font_t *font)
{
unsigned char byte;
uint16_t word;
cairo_status_t status;
cairo_cff_font_set_topdict_operator_to_cur_pos (font, CHARSET_OP);
status = _cairo_array_grow_by (&font->output, 5);
- if (status)
+ if (unlikely (status))
return status;
byte = 2;
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);
@@ -1469,32 +1467,32 @@ cairo_cff_font_write_cid_fontdict (cairo
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)
+ if (unlikely (status))
return status;
status = _cairo_array_append (&font->output, &offset_size);
- if (status)
+ if (unlikely (status))
return status;
status = _cairo_array_allocate (&font->output,
(font->num_subset_fontdicts + 1)*offset_size,
(void **) &offset_array);
- if (status)
+ if (unlikely (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)
+ if (unlikely (status))
return status;
*offset_array++ = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@@ -1508,17 +1506,17 @@ cairo_cff_font_write_private_dict (cairo
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);
- if (status)
+ if (unlikely (status))
return status;
size = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
/* 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);
assert (offset > 0);
@@ -1547,17 +1545,17 @@ cairo_cff_font_write_local_sub (cairo_cf
* private dict */
offset = _cairo_array_num_elements (&font->output) - font->private_dict_offset[dict_num];
buf_end = encode_integer_max (buf, offset);
offset = cff_dict_get_location (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);
- if (status)
+ if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
@@ -1568,42 +1566,42 @@ cairo_cff_font_write_cid_private_dict_an
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)
+ if (unlikely (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)
+ if (unlikely (status))
return status;
}
} else {
status = cairo_cff_font_write_private_dict (font,
0,
font->fd_dict[0],
font->private_dict);
- if (status)
+ if (unlikely (status))
return status;
status = cairo_cff_font_write_local_sub (font,
0,
font->private_dict,
&font->local_sub_index);
- if (status)
+ if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
}
typedef cairo_status_t
(*font_write_t) (cairo_cff_font_t *font);
@@ -1624,40 +1622,40 @@ static const font_write_t font_write_fun
static cairo_status_t
cairo_cff_font_write_subset (cairo_cff_font_t *font)
{
cairo_int_status_t status;
unsigned int i;
for (i = 0; i < ARRAY_LENGTH (font_write_funcs); i++) {
status = font_write_funcs[i] (font);
- if (status)
+ if (unlikely (status))
return status;
}
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
cairo_cff_font_generate (cairo_cff_font_t *font,
const char **data,
unsigned long *length)
{
cairo_int_status_t status;
status = cairo_cff_font_read_font (font);
- if (status)
+ if (unlikely (status))
return status;
status = cairo_cff_font_subset_font (font);
- if (status)
+ if (unlikely (status))
return status;
status = cairo_cff_font_write_subset (font);
- if (status)
+ if (unlikely (status))
return status;
*data = _cairo_array_index (&font->output, 0);
*length = _cairo_array_num_elements (&font->output);
return CAIRO_STATUS_SUCCESS;
}
@@ -1673,39 +1671,39 @@ cairo_cff_font_create_set_widths (cairo_
unsigned char buf[10];
int glyph_index;
cairo_int_status_t status;
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)
+ if (unlikely (status))
return status;
num_hmetrics = be16_to_cpu (hhea.num_hmetrics);
for (i = 1; 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);
- if (status)
+ if (unlikely (status))
return status;
}
else
{
status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
(num_hmetrics - 1) * long_entry_size,
buf, &short_entry_size);
- if (status)
+ if (unlikely (status))
return status;
}
font->widths[i] = be16_to_cpu (*((int16_t*)buf));
}
return CAIRO_STATUS_SUCCESS;
}
@@ -1714,210 +1712,169 @@ static cairo_int_status_t
cairo_cff_font_t **font_return,
const char *subset_name)
{
const cairo_scaled_font_backend_t *backend;
cairo_status_t status;
cairo_cff_font_t *font;
tt_head_t head;
tt_hhea_t hhea;
- tt_name_t *name;
- tt_name_record_t *record;
unsigned long size, data_length;
- int i, j;
backend = scaled_font_subset->scaled_font->backend;
if (!backend->load_truetype_table)
return CAIRO_INT_STATUS_UNSUPPORTED;
data_length = 0;
status = backend->load_truetype_table( scaled_font_subset->scaled_font,
TT_TAG_CFF, 0, NULL, &data_length);
- if (status)
+ if (unlikely (status))
return status;
size = sizeof (tt_head_t);
status = backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_head, 0,
(unsigned char *) &head, &size);
- if (status)
+ if (unlikely (status))
return status;
size = sizeof (tt_hhea_t);
status = backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_hhea, 0,
(unsigned char *) &hhea, &size);
- if (status)
+ if (unlikely (status))
return status;
size = 0;
status = backend->load_truetype_table (scaled_font_subset->scaled_font,
TT_TAG_hmtx, 0, NULL, &size);
- if (status)
- return status;
-
- size = 0;
- status = backend->load_truetype_table (scaled_font_subset->scaled_font,
- TT_TAG_name, 0, NULL, &size);
- if (status)
+ if (unlikely (status))
return status;
- name = malloc (size);
- if (name == NULL)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- status = backend->load_truetype_table (scaled_font_subset->scaled_font,
- TT_TAG_name, 0,
- (unsigned char *) name, &size);
- if (status)
- goto fail1;
-
font = malloc (sizeof (cairo_cff_font_t));
- if (font == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto fail1;
- }
+ if (unlikely (font == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font->backend = backend;
font->scaled_font_subset = scaled_font_subset;
_cairo_array_init (&font->output, sizeof (char));
status = _cairo_array_grow_by (&font->output, 4096);
- if (status)
+ if (unlikely (status))
goto fail2;
font->subset_font_name = strdup (subset_name);
- if (font->subset_font_name == NULL) {
+ if (unlikely (font->subset_font_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
font->x_min = (int16_t) be16_to_cpu (head.x_min);
font->y_min = (int16_t) be16_to_cpu (head.y_min);
font->x_max = (int16_t) be16_to_cpu (head.x_max);
font->y_max = (int16_t) be16_to_cpu (head.y_max);
font->ascent = (int16_t) be16_to_cpu (hhea.ascender);
font->descent = (int16_t) be16_to_cpu (hhea.descender);
- /* Extract the font name from the name table. At present this
- * just looks for the Mac platform/Roman encoded font name. It
- * should be extended to use any suitable font name in the
- * name table. If the mac/roman font name is not found a
- * CairoFont-x-y name is created.
- */
font->font_name = NULL;
- for (i = 0; i < be16_to_cpu(name->num_records); i++) {
- record = &(name->records[i]);
- if ((be16_to_cpu (record->platform) == 1) &&
- (be16_to_cpu (record->encoding) == 0) &&
- (be16_to_cpu (record->name) == 4)) {
- font->font_name = malloc (be16_to_cpu(record->length) + 1);
- if (font->font_name) {
- strncpy(font->font_name,
- ((char*)name) + be16_to_cpu (name->strings_offset) + be16_to_cpu (record->offset),
- be16_to_cpu (record->length));
- font->font_name[be16_to_cpu (record->length)] = 0;
- }
- break;
- }
- }
+ status = _cairo_truetype_read_font_name (scaled_font_subset->scaled_font,
+ &font->ps_name,
+ &font->font_name);
+ if (_cairo_status_is_error (status))
+ goto fail3;
- if (font->font_name == NULL) {
- font->font_name = malloc (30);
- if (font->font_name == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ /* If the PS name is not found, create a CairoFont-x-y name. */
+ if (font->ps_name == NULL) {
+ font->ps_name = malloc (30);
+ if (unlikely (font->ps_name == NULL)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
- }
- snprintf(font->font_name, 30, "CairoFont-%u-%u",
+ }
+
+ snprintf(font->ps_name, 30, "CairoFont-%u-%u",
scaled_font_subset->font_id,
scaled_font_subset->subset_id);
}
- for (i = 0, j = 0; font->font_name[j]; j++) {
- if (font->font_name[j] == ' ')
- continue;
- font->font_name[i++] = font->font_name[j];
- }
- font->font_name[i] = '\0';
-
font->widths = calloc (font->scaled_font_subset->num_glyphs, sizeof (int));
- if (font->widths == NULL) {
+ if (unlikely (font->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
}
status = cairo_cff_font_create_set_widths (font);
- if (status)
+ if (unlikely (status))
goto fail5;
font->data_length = data_length;
font->data = malloc (data_length);
- if (font->data == NULL) {
+ if (unlikely (font->data == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail5;
}
status = font->backend->load_truetype_table ( font->scaled_font_subset->scaled_font,
TT_TAG_CFF, 0, font->data,
&font->data_length);
- if (status)
+ if (unlikely (status))
goto fail6;
font->data_end = font->data + font->data_length;
status = cff_dict_init (&font->top_dict);
- if (status)
+ if (unlikely (status))
goto fail6;
status = cff_dict_init (&font->private_dict);
- if (status)
+ if (unlikely (status))
goto fail7;
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;
- free (name);
*font_return = font;
return CAIRO_STATUS_SUCCESS;
fail7:
_cairo_hash_table_destroy (font->top_dict);
fail6:
free (font->data);
fail5:
free (font->widths);
fail4:
- free (font->font_name);
+ if (font->font_name)
+ free (font->font_name);
fail3:
free (font->subset_font_name);
fail2:
_cairo_array_fini (&font->output);
free (font);
-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);
+ if (font->font_name)
+ free (font->font_name);
+ free (font->ps_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);
@@ -1970,130 +1927,146 @@ cairo_status_t
{
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;
status = _cairo_cff_font_create (font_subset, &font, subset_name);
- if (status)
+ if (unlikely (status))
return status;
status = cairo_cff_font_generate (font, &data, &length);
- if (status)
+ if (unlikely (status))
goto fail1;
- cff_subset->base_font = strdup (font->font_name);
- if (cff_subset->base_font == NULL) {
+ cff_subset->ps_name = strdup (font->ps_name);
+ if (unlikely (cff_subset->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
}
+ if (font->font_name) {
+ cff_subset->font_name = strdup (font->font_name);
+ if (cff_subset->font_name == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto fail2;
+ }
+ } else {
+ cff_subset->font_name = NULL;
+ }
+
cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
- if (cff_subset->widths == NULL) {
+ if (unlikely (cff_subset->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto fail2;
+ goto fail3;
}
for (i = 0; i < font->scaled_font_subset->num_glyphs; i++)
cff_subset->widths[i] = font->widths[i];
cff_subset->x_min = font->x_min;
cff_subset->y_min = font->y_min;
cff_subset->x_max = font->x_max;
cff_subset->y_max = font->y_max;
cff_subset->ascent = font->ascent;
cff_subset->descent = font->descent;
cff_subset->data = malloc (length);
- if (cff_subset->data == NULL) {
+ if (unlikely (cff_subset->data == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto fail3;
+ goto fail4;
}
memcpy (cff_subset->data, data, length);
cff_subset->data_length = length;
cairo_cff_font_destroy (font);
return CAIRO_STATUS_SUCCESS;
- fail3:
+ fail4:
free (cff_subset->widths);
+ fail3:
+ if (cff_subset->font_name)
+ free (cff_subset->font_name);
fail2:
- free (cff_subset->base_font);
+ free (cff_subset->ps_name);
fail1:
cairo_cff_font_destroy (font);
return status;
}
void
_cairo_cff_subset_fini (cairo_cff_subset_t *subset)
{
- free (subset->base_font);
+ free (subset->ps_name);
+ if (subset->font_name)
+ free (subset->font_name);
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)
+ if (unlikely (font == NULL))
return _cairo_error (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)
+ if (unlikely (status))
goto fail1;
font->subset_font_name = strdup (subset_name);
- if (font->subset_font_name == NULL) {
+ if (unlikely (font->subset_font_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail1;
}
- font->font_name = strdup (subset_name);
- if (font->subset_font_name == NULL) {
+ font->ps_name = strdup (subset_name);
+ if (unlikely (font->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
+ font->font_name = NULL;
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) {
+ if (unlikely (font->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
font->data_length = 0;
font->data = NULL;
font->data_end = NULL;
status = cff_dict_init (&font->top_dict);
- if (status)
+ if (unlikely (status))
goto fail4;
status = cff_dict_init (&font->private_dict);
- if (status)
+ if (unlikely (status))
goto fail5;
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);
@@ -2109,17 +2082,19 @@ static cairo_int_status_t
return CAIRO_STATUS_SUCCESS;
fail5:
_cairo_hash_table_destroy (font->top_dict);
fail4:
free (font->widths);
fail3:
- free (font->font_name);
+ if (font->font_name)
+ free (font->font_name);
+ free (font->ps_name);
fail2:
free (font->subset_font_name);
fail1:
_cairo_array_fini (&font->output);
free (font);
return status;
}
@@ -2146,63 +2121,63 @@ cairo_cff_font_fallback_generate (cairo_
/* 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);
status = cff_dict_set_operands (font->top_dict,
FONTBBOX_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
return status;
end_buf = encode_integer_max (buf, 0);
status = cff_dict_set_operands (font->top_dict,
CHARSTRINGS_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
return status;
status = cff_dict_set_operands (font->top_dict,
FDSELECT_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
return status;
status = cff_dict_set_operands (font->top_dict,
FDARRAY_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
return status;
status = cff_dict_set_operands (font->top_dict,
CHARSET_OP, buf, end_buf - buf);
- if (status)
+ if (unlikely (status))
return status;
status = cairo_cff_font_set_ros_strings (font);
- if (status)
+ if (unlikely (status))
return status;
/* Create CID FD dictionary */
status = cairo_cff_font_create_cid_fontdict (font);
- if (status)
+ if (unlikely (status))
return status;
/* 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)
+ if (unlikely (status))
return status;
}
status = cairo_cff_font_write_subset (font);
- if (status)
+ if (unlikely (status))
return status;
*data = _cairo_array_index (&font->output, 0);
*length = _cairo_array_num_elements (&font->output);
return CAIRO_STATUS_SUCCESS;
}
@@ -2214,76 +2189,78 @@ cairo_status_t
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)
+ if (unlikely (status))
return status;
status = _cairo_type2_charstrings_init (&type2_subset, font_subset);
- if (status)
+ if (unlikely (status))
goto fail1;
status = cairo_cff_font_fallback_generate (font, &type2_subset, &data, &length);
- if (status)
+ if (unlikely (status))
goto fail2;
- cff_subset->base_font = strdup (font->font_name);
- if (cff_subset->base_font == NULL) {
+ cff_subset->font_name = NULL;
+ cff_subset->ps_name = strdup (font->ps_name);
+ if (unlikely (cff_subset->ps_name == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail2;
}
cff_subset->widths = calloc (sizeof (int), font->scaled_font_subset->num_glyphs);
- if (cff_subset->widths == NULL) {
+ if (unlikely (cff_subset->widths == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail3;
}
+
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;
cff_subset->data = malloc (length);
- if (cff_subset->data == NULL) {
+ if (unlikely (cff_subset->data == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail4;
}
memcpy (cff_subset->data, data, length);
cff_subset->data_length = length;
cff_subset->data_length = length;
_cairo_type2_charstrings_fini (&type2_subset);
cairo_cff_font_destroy (font);
return CAIRO_STATUS_SUCCESS;
fail4:
free (cff_subset->widths);
fail3:
- free (cff_subset->base_font);
+ free (cff_subset->ps_name);
fail2:
_cairo_type2_charstrings_fini (&type2_subset);
fail1:
cairo_cff_font_destroy (font);
return status;
}
void
_cairo_cff_fallback_fini (cairo_cff_subset_t *subset)
{
- free (subset->base_font);
+ free (subset->ps_name);
free (subset->widths);
free (subset->data);
}
#endif /* CAIRO_HAS_FONT_SUBSET */
--- a/gfx/cairo/cairo/src/cairo-clip.c
+++ b/gfx/cairo/cairo/src/cairo-clip.c
@@ -44,17 +44,17 @@ static cairo_clip_path_t *
_cairo_clip_path_reference (cairo_clip_path_t *clip_path);
static void
_cairo_clip_path_destroy (cairo_clip_path_t *clip_path);
void
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
{
- if (target)
+ if (target && target->backend)
clip->mode = _cairo_surface_get_clip_mode (target);
else
clip->mode = CAIRO_CLIP_MODE_MASK;
clip->all_clipped = FALSE;
clip->surface = NULL;
clip->surface_rect.x = 0;
@@ -83,17 +83,17 @@ cairo_status_t
clip->serial = other->serial;
_cairo_region_init (&clip->region);
if (other->has_region) {
cairo_status_t status;
status = _cairo_region_copy (&clip->region, &other->region);
- if (status) {
+ if (unlikely (status)) {
_cairo_region_fini (&clip->region);
cairo_surface_destroy (clip->surface);
return status;
}
clip->has_region = TRUE;
} else {
clip->has_region = FALSE;
}
@@ -138,88 +138,62 @@ static void
}
static cairo_status_t
_cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
cairo_rectangle_int_t *rectangle)
{
while (clip_path) {
- cairo_status_t status;
- cairo_traps_t traps;
- cairo_box_t extents;
- cairo_rectangle_int_t extents_rect;
-
- _cairo_box_from_rectangle (&extents, rectangle);
-
- _cairo_traps_init (&traps);
- _cairo_traps_limit (&traps, &extents);
+ cairo_rectangle_int_t extents;
- status = _cairo_path_fixed_fill_to_traps (&clip_path->path,
- clip_path->fill_rule,
- clip_path->tolerance,
- &traps);
- if (status) {
- _cairo_traps_fini (&traps);
- return status;
- }
+ _cairo_path_fixed_approximate_clip_extents (&clip_path->path, &extents);
- _cairo_traps_extents (&traps, &extents);
- _cairo_traps_fini (&traps);
-
- _cairo_box_round_to_rectangle (&extents, &extents_rect);
- _cairo_rectangle_intersect (rectangle, &extents_rect);
+ if (! _cairo_rectangle_intersect (rectangle, &extents))
+ return CAIRO_STATUS_SUCCESS;
clip_path = clip_path->prev;
}
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
cairo_rectangle_int_t *rectangle)
{
+ cairo_status_t status;
+ cairo_bool_t is_empty;
+
if (!clip)
return CAIRO_STATUS_SUCCESS;
if (clip->all_clipped) {
*rectangle = clip->surface_rect;
return CAIRO_STATUS_SUCCESS;
}
if (clip->path) {
- cairo_status_t status;
-
status = _cairo_clip_path_intersect_to_rectangle (clip->path,
rectangle);
- if (status)
+ if (unlikely (status))
return status;
}
if (clip->has_region) {
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_region_t intersection;
-
- _cairo_region_init_rect (&intersection, rectangle);
-
- status = _cairo_region_intersect (&intersection, &clip->region,
- &intersection);
+ cairo_rectangle_int_t extents;
- if (!status)
- _cairo_region_get_extents (&intersection, rectangle);
-
- _cairo_region_fini (&intersection);
-
- if (status)
- return status;
+ _cairo_region_get_extents (&clip->region, &extents);
+ is_empty = _cairo_rectangle_intersect (rectangle, &extents);
+ if (is_empty)
+ return CAIRO_STATUS_SUCCESS;
}
if (clip->surface)
- _cairo_rectangle_intersect (rectangle, &clip->surface_rect);
+ is_empty = _cairo_rectangle_intersect (rectangle, &clip->surface_rect);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
cairo_region_t *region)
{
@@ -241,30 +215,30 @@ cairo_status_t
}
if (clip->path) {
/* Intersect clip path into region. */
}
if (clip->has_region) {
status = _cairo_region_intersect (region, &clip->region, region);
- if (status)
+ if (unlikely (status))
return status;
}
if (clip->surface) {
cairo_region_t clip_rect;
_cairo_region_init_rect (&clip_rect, &clip->surface_rect);
status = _cairo_region_intersect (region, &clip_rect, region);
_cairo_region_fini (&clip_rect);
- if (status)
+ if (unlikely (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,
@@ -311,21 +285,21 @@ static cairo_status_t
{
cairo_clip_path_t *clip_path;
cairo_status_t status;
if (clip->mode != CAIRO_CLIP_MODE_PATH)
return CAIRO_INT_STATUS_UNSUPPORTED;
clip_path = malloc (sizeof (cairo_clip_path_t));
- if (clip_path == NULL)
+ if (unlikely (clip_path == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_path_fixed_init_copy (&clip_path->path, path);
- if (status) {
+ if (unlikely (status)) {
free (clip_path);
return status;
}
CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1);
clip_path->fill_rule = fill_rule;
clip_path->tolerance = tolerance;
clip_path->antialias = antialias;
@@ -375,17 +349,16 @@ static cairo_int_status_t
if (clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
if (clip->mode != CAIRO_CLIP_MODE_REGION)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_traps_extract_region (traps, ®ion);
-
if (status)
return status;
if (!clip->has_region) {
status = _cairo_region_copy (&clip->region, ®ion);
if (status == CAIRO_STATUS_SUCCESS)
clip->has_region = TRUE;
} else {
@@ -416,45 +389,44 @@ static cairo_status_t
_cairo_clip_intersect_mask (cairo_clip_t *clip,
cairo_traps_t *traps,
cairo_antialias_t antialias,
cairo_surface_t *target)
{
cairo_pattern_union_t pattern;
cairo_box_t extents;
cairo_rectangle_int_t surface_rect, target_rect;
- cairo_surface_t *surface;
- cairo_status_t status;
+ cairo_surface_t *surface = NULL;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
if (clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
/* Represent the clip as a mask surface. We create a new surface
* the size of the intersection of the old mask surface and the
* extents of the new clip path. */
_cairo_traps_extents (traps, &extents);
_cairo_box_round_to_rectangle (&extents, &surface_rect);
- if (clip->surface != NULL)
- _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect);
+ if (clip->surface != NULL) {
+ if (! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
+ goto DONE;
+ }
/* Intersect with the target surface rectangle so we don't use
* more memory and time than we need to. */
status = _cairo_surface_get_extents (target, &target_rect);
- if (status == CAIRO_STATUS_SUCCESS)
- _cairo_rectangle_intersect (&surface_rect, &target_rect);
+ if (status == CAIRO_STATUS_SUCCESS) {
+ if (! _cairo_rectangle_intersect (&surface_rect, &target_rect))
+ goto DONE;
+ }
- if (surface_rect.width == 0 || surface_rect.height == 0) {
- surface = NULL;
- status = CAIRO_STATUS_SUCCESS;
- if (clip->surface != NULL)
- cairo_surface_destroy (clip->surface);
+ if (surface_rect.width == 0 || surface_rect.height == 0)
goto DONE;
- }
_cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
CAIRO_CONTENT_COLOR);
/* The clipping operation should ideally be something like the following to
* avoid having to do as many passes over the data
if (clip->surface != NULL) {
_cairo_pattern_init_for_surface (&pattern.surface, clip->surface);
@@ -473,19 +445,20 @@ static cairo_status_t
traps->traps,
traps->num_traps);
However this operation is not accelerated by pixman
I believe the best possible operation would probably an unbounded SRC
operator. Using SRC we could potentially avoid having to initialize
the surface which would be ideal from an efficiency point of view.
- However, _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_SOURCE) is
- bounded by the mask.
-
+ However, CAIRO_OPERATOR_SOURCE is bounded by the trapezoid mask and
+ _cairo_surface_composite_trapezoids (CAIRO_OPERATOR_SOURCE) will assert
+ because it assumes CAIRO_OPERATOR_SOURCE has been converted into other
+ operations.
*/
surface = _cairo_surface_create_similar_solid (target,
CAIRO_CONTENT_ALPHA,
surface_rect.width,
surface_rect.height,
CAIRO_COLOR_TRANSPARENT);
if (surface->status) {
@@ -505,17 +478,17 @@ static cairo_status_t
0, 0,
surface_rect.width,
surface_rect.height,
traps->traps,
traps->num_traps);
_cairo_pattern_fini (&pattern.base);
- if (status) {
+ if (unlikely (status)) {
cairo_surface_destroy (surface);
return status;
}
/* If there was a clip surface already, combine it with the new
* mask surface using the IN operator, so we get the intersection
* of the old and new clipping paths. */
@@ -530,46 +503,174 @@ static cairo_status_t
surface_rect.y - clip->surface_rect.y,
0, 0,
0, 0,
surface_rect.width,
surface_rect.height);
_cairo_pattern_fini (&pattern.base);
- if (status) {
+ if (unlikely (status)) {
cairo_surface_destroy (surface);
return status;
}
-
- cairo_surface_destroy (clip->surface);
}
DONE:
+ cairo_surface_destroy (clip->surface);
clip->surface = surface;
clip->surface_rect = surface_rect;
clip->serial = _cairo_surface_allocate_clip_serial (target);
if (surface_rect.width == 0 || surface_rect.height == 0)
_cairo_clip_set_all_clipped (clip, target);
return status;
}
+static cairo_status_t
+_cairo_clip_intersect_mask_using_spans (cairo_clip_t *clip,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias,
+ cairo_surface_t *target)
+{
+ cairo_span_renderer_t *renderer = NULL;
+ cairo_pattern_union_t pattern;
+ cairo_rectangle_int_t surface_rect;
+ cairo_surface_t *surface = NULL;
+ cairo_status_t status;
+ cairo_operator_t op;
+ cairo_composite_rectangles_t rects;
+
+ if (clip->all_clipped)
+ return CAIRO_STATUS_SUCCESS;
+
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
+ CAIRO_CONTENT_COLOR);
+
+ /* If we have a clip surface we're going to use IN to combine our
+ * new clip with the old clip. The ADD is done to a transparent
+ * surface, as that's a fast way of doing it currently. We should
+ * really be using SOURCE instead, but _cairo_surface_composite()
+ * checks that it's not called with SOURCE or DEST. */
+ op = clip->surface ? CAIRO_OPERATOR_IN : CAIRO_OPERATOR_ADD;
+
+ /* Test if the target can composite spans. We're going to assume
+ * this is a good indicator of whether a similar surface is going
+ * to be able to composite spans too. */
+ if ( !_cairo_surface_check_span_renderer (op,
+ &pattern.base,
+ target,
+ antialias,
+ NULL))
+ {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto BAIL;
+ }
+
+ status = _cairo_surface_get_extents (target, &surface_rect);
+ if (status)
+ goto BAIL;
+
+ /* We'll create a new surface the size of the intersection of the
+ * old mask surface and the extents of the new clip path. */
+ {
+ cairo_rectangle_int_t extents;
+
+ _cairo_path_fixed_approximate_clip_extents (path, &extents);
+ if (! _cairo_rectangle_intersect (&surface_rect, &extents))
+ goto SUCCESS;
+
+ if (clip->surface != NULL &&
+ ! _cairo_rectangle_intersect (&surface_rect, &clip->surface_rect))
+ goto SUCCESS;
+ }
+
+ /* Make the new mask surface and optionally initialise it from the
+ * previous clip if we have one. */
+ surface = _cairo_surface_create_similar_solid (target,
+ CAIRO_CONTENT_ALPHA,
+ surface_rect.width,
+ surface_rect.height,
+ CAIRO_COLOR_TRANSPARENT);
+ if (surface->status) {
+ _cairo_pattern_fini (&pattern.base);
+ return surface->status;
+ }
+
+ if (clip->surface) {
+ cairo_surface_pattern_t old_clip;
+ _cairo_pattern_init_for_surface (&old_clip, clip->surface);
+ status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
+ &old_clip.base,
+ NULL,
+ surface,
+ surface_rect.x - clip->surface_rect.x,
+ surface_rect.y - clip->surface_rect.y,
+ 0, 0,
+ 0, 0,
+ surface_rect.width,
+ surface_rect.height);
+ _cairo_pattern_fini (&old_clip.base);
+ if (status)
+ goto BAIL;
+ }
+
+ _cairo_composite_rectangles_init (&rects,
+ surface_rect.x,
+ surface_rect.y,
+ surface_rect.width,
+ surface_rect.height);
+ rects.dst.x = 0;
+ rects.dst.y = 0;
+
+ /* Render the new clipping path into the new mask surface. We've
+ * chosen op to either combine the new clip path with the existing
+ * clip mask (if there is one) or just render it. */
+ status =_cairo_path_fixed_fill_using_spans (op, &pattern.base,
+ path, surface,
+ fill_rule, tolerance,
+ antialias, &rects);
+ if (status)
+ goto BAIL;
+
+ SUCCESS:
+ if (clip->surface != NULL)
+ cairo_surface_destroy (clip->surface);
+ clip->surface = surface;
+ clip->surface_rect = surface_rect;
+ clip->serial = _cairo_surface_allocate_clip_serial (target);
+ surface = NULL;
+
+ if (surface_rect.width == 0 || surface_rect.height == 0)
+ _cairo_clip_set_all_clipped (clip, target);
+
+ BAIL:
+ if (renderer)
+ renderer->destroy(renderer);
+ if (surface)
+ cairo_surface_destroy (surface);
+ _cairo_pattern_fini (&pattern.base);
+ return status;
+}
+
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,
cairo_surface_t *target)
{
cairo_status_t status;
cairo_rectangle_int_t rectangle;
cairo_traps_t traps;
+ cairo_box_t ignored_box;
if (clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
/* catch the empty clip path */
if (! path->has_current_point) {
_cairo_clip_set_all_clipped (clip, target);
return CAIRO_STATUS_SUCCESS;
@@ -579,33 +680,45 @@ cairo_status_t
path, fill_rule, tolerance,
antialias);
if (status == CAIRO_STATUS_SUCCESS)
clip->serial = _cairo_surface_allocate_clip_serial (target);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
return status;
+ /* TODO: allow ANTIALIAS_NONE when we have a mono scan converter
+ * again. */
+ if (antialias != CAIRO_ANTIALIAS_NONE &&
+ !_cairo_path_fixed_is_box (path, &ignored_box) &&
+ !_cairo_path_fixed_is_region (path))
+ {
+ status = _cairo_clip_intersect_mask_using_spans (
+ clip, path, fill_rule, tolerance, antialias, target);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+ }
+
_cairo_traps_init (&traps);
/* Limit the traps to the target surface
* - so we don't add more traps than needed. */
status = _cairo_surface_get_extents (target, &rectangle);
if (status == CAIRO_STATUS_SUCCESS) {
cairo_box_t box;
_cairo_box_from_rectangle (&box, &rectangle);
_cairo_traps_limit (&traps, &box);
}
status = _cairo_path_fixed_fill_to_traps (path,
fill_rule,
tolerance,
&traps);
- if (status)
+ if (unlikely (status))
goto bail;
status = _cairo_clip_intersect_region (clip, &traps, target);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto bail;
status = _cairo_clip_intersect_mask (clip, &traps, antialias, target);
@@ -652,17 +765,17 @@ void
static cairo_status_t
_cairo_clip_path_reapply_clip_path (cairo_clip_t *clip,
cairo_clip_path_t *clip_path)
{
cairo_status_t status;
if (clip_path->prev) {
status = _cairo_clip_path_reapply_clip_path (clip, clip_path->prev);
- if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ if (_cairo_status_is_error (status))
return status;
}
return _cairo_clip_intersect_path (clip,
&clip_path->path,
clip_path->fill_rule,
clip_path->tolerance,
clip_path->antialias);
@@ -678,44 +791,44 @@ cairo_status_t
_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) {
status = _cairo_region_copy (&clip->region, &other->region);
- if (status)
+ if (unlikely (status))
goto BAIL;
clip->has_region = TRUE;
}
if (other->surface) {
int dx, dy;
status = _cairo_surface_clone_similar (target, other->surface,
0,
0,
other->surface_rect.width,
other->surface_rect.height,
&dx, &dy,
&clip->surface);
- if (status)
+ if (unlikely (status))
goto BAIL;
clip->surface_rect = other->surface_rect;
/* src offset was 0, so we expect an exact replica of the surface */
assert (dx == 0);
assert (dy == 0);
}
if (other->path) {
status = _cairo_clip_path_reapply_clip_path (clip, other->path);
- if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
+ if (_cairo_status_is_error (status))
goto BAIL;
}
}
return CAIRO_STATUS_SUCCESS;
BAIL:
if (clip->has_region)
@@ -735,20 +848,22 @@ static cairo_bool_t
_cairo_clip_int_rect_to_user (cairo_gstate_t *gstate,
cairo_rectangle_int_t *clip_rect,
cairo_rectangle_t *user_rect)
{
cairo_bool_t is_tight;
double x1 = clip_rect->x;
double y1 = clip_rect->y;
- double x2 = clip_rect->x + clip_rect->width;
- double y2 = clip_rect->y + clip_rect->height;
+ double x2 = clip_rect->x + (int) clip_rect->width;
+ double y2 = clip_rect->y + (int) clip_rect->height;
- _cairo_gstate_backend_to_user_rectangle (gstate, &x1, &y1, &x2, &y2, &is_tight);
+ _cairo_gstate_backend_to_user_rectangle (gstate,
+ &x1, &y1, &x2, &y2,
+ &is_tight);
user_rect->x = x1;
user_rect->y = y1;
user_rect->width = x2 - x1;
user_rect->height = y2 - y1;
return is_tight;
}
@@ -764,71 +879,68 @@ cairo_rectangle_list_t *
goto DONE;
if (clip->path || clip->surface) {
_cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
}
if (clip->has_region) {
- cairo_box_int_t *boxes;
int i;
- if (_cairo_region_get_boxes (&clip->region, &n_boxes, &boxes))
- return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
+ n_boxes = _cairo_region_num_boxes (&clip->region);
if (n_boxes) {
rectangles = _cairo_malloc_ab (n_boxes, sizeof (cairo_rectangle_t));
- if (rectangles == NULL) {
- _cairo_region_boxes_fini (&clip->region, boxes);
+ if (unlikely (rectangles == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
}
for (i = 0; i < n_boxes; ++i) {
- cairo_rectangle_int_t clip_rect;
+ cairo_box_int_t box;
+ cairo_rectangle_int_t clip_rect;
+
+ _cairo_region_get_box (&clip->region, i, &box);
- clip_rect.x = boxes[i].p1.x;
- clip_rect.y = boxes[i].p1.y;
- clip_rect.width = boxes[i].p2.x - boxes[i].p1.x;
- clip_rect.height = boxes[i].p2.y - boxes[i].p1.y;
-
+ clip_rect.x = box.p1.x;
+ clip_rect.y = box.p1.y;
+ clip_rect.width = box.p2.x - box.p1.x;
+ clip_rect.height = box.p2.y - box.p1.y;
+
if (!_cairo_clip_int_rect_to_user(gstate, &clip_rect, &rectangles[i])) {
_cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
- _cairo_region_boxes_fini (&clip->region, boxes);
free (rectangles);
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
}
}
}
-
- _cairo_region_boxes_fini (&clip->region, boxes);
} else {
cairo_rectangle_int_t extents;
n_boxes = 1;
rectangles = malloc(sizeof (cairo_rectangle_t));
- if (rectangles == NULL) {
+ if (unlikely (rectangles == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
}
if (_cairo_surface_get_extents (_cairo_gstate_get_target (gstate), &extents) ||
!_cairo_clip_int_rect_to_user(gstate, &extents, rectangles))
{
_cairo_error_throw (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
free (rectangles);
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
}
}
DONE:
list = malloc (sizeof (cairo_rectangle_list_t));
- if (list == NULL) {
+ if (unlikely (list == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
free (rectangles);
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
}
list->status = CAIRO_STATUS_SUCCESS;
list->rectangles = rectangles;
list->num_rectangles = n_boxes;
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-combsort-private.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Chris Wilson
+ *
+ * Contributor(s):
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ */
+
+/* This fragment implements a comb sort (specifically combsort11) */
+#ifndef _HAVE_CAIRO_COMBSORT_NEWGAP
+#define _HAVE_CAIRO_COMBSORT_NEWGAP
+static inline unsigned int
+_cairo_combsort_newgap (unsigned int gap)
+{
+ gap = 10 * gap / 13;
+ if (gap == 9 || gap == 10)
+ gap = 11;
+ if (gap < 1)
+ gap = 1;
+ return gap;
+}
+#endif
+
+#define CAIRO_COMBSORT_DECLARE(NAME, TYPE, CMP) \
+static void \
+NAME (TYPE *base, unsigned int nmemb) \
+{ \
+ unsigned int gap = nmemb; \
+ unsigned int i, j; \
+ int swapped; \
+ do { \
+ gap = _cairo_combsort_newgap (gap); \
+ swapped = 0; \
+ for (i = 0; i < nmemb-gap ; i++) { \
+ j = i + gap; \
+ if (CMP (base[i], base[j]) > 0 ) { \
+ TYPE tmp; \
+ tmp = base[i]; \
+ base[i] = base[j]; \
+ base[j] = tmp; \
+ swapped = 1; \
+ } \
+ } \
+ } while (gap > 1 || swapped); \
+}
--- a/gfx/cairo/cairo/src/cairo-compiler-private.h
+++ b/gfx/cairo/cairo/src/cairo-compiler-private.h
@@ -134,29 +134,71 @@
#if __GNUC__ >= 3
#define cairo_pure __attribute__((pure))
#define cairo_const __attribute__((const))
#else
#define cairo_pure
#define cairo_const
#endif
+#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
+#define _CAIRO_BOOLEAN_EXPR(expr) \
+ __extension__ ({ \
+ int _cairo_boolean_var_; \
+ if (expr) \
+ _cairo_boolean_var_ = 1; \
+ else \
+ _cairo_boolean_var_ = 0; \
+ _cairo_boolean_var_; \
+})
+#define likely(expr) (__builtin_expect (_CAIRO_BOOLEAN_EXPR(expr), 1))
+#define unlikely(expr) (__builtin_expect (_CAIRO_BOOLEAN_EXPR(expr), 0))
+#else
+#define likely(expr) (expr)
+#define unlikely(expr) (expr)
+#endif
+
#ifndef __GNUC__
#undef __attribute__
#define __attribute__(x)
#endif
#if (defined(__WIN32__) && !defined(__WINE__)) || defined(_MSC_VER)
#define snprintf _snprintf
#define popen _popen
+#define pclose _pclose
#endif
#ifdef _MSC_VER
#undef inline
#define inline __inline
#endif
+#ifdef _MSC_VER
+/* When compiling with /Gy and /OPT:ICF identical functions will be folded in together.
+ The CAIRO_ENSURE_UNIQUE macro ensures that a function is always unique and
+ will never be folded into another one. Something like this might eventually
+ be needed for GCC but it seems fine for now. */
+#define CAIRO_ENSURE_UNIQUE \
+ do { \
+ char func[] = __FUNCTION__; \
+ char file[] = __FILE__; \
+ __asm { \
+ __asm jmp __internal_skip_line_no \
+ __asm _emit (__LINE__ & 0xff) \
+ __asm _emit ((__LINE__>>8) & 0xff) \
+ __asm _emit ((__LINE__>>16) & 0xff) \
+ __asm _emit ((__LINE__>>24) & 0xff) \
+ __asm lea eax, func \
+ __asm lea eax, file \
+ __asm __internal_skip_line_no: \
+ }; \
+ } while (0)
+#else
+#define CAIRO_ENSURE_UNIQUE do { } while (0)
+#endif
+
#ifdef __STRICT_ANSI__
#undef inline
#define inline __inline__
#endif
#endif
--- a/gfx/cairo/cairo/src/cairo-debug.c
+++ b/gfx/cairo/cairo/src/cairo-debug.c
@@ -56,20 +56,24 @@
* 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)
{
CAIRO_MUTEX_INITIALIZE ();
- _cairo_font_face_reset_static_data ();
+ _cairo_scaled_font_map_destroy ();
+
+ _cairo_toy_font_face_reset_static_data ();
#if CAIRO_HAS_FT_FONT
_cairo_ft_font_reset_static_data ();
#endif
+ _cairo_intern_string_reset_static_data ();
+
_cairo_scaled_font_reset_static_data ();
_cairo_pattern_reset_static_data ();
CAIRO_MUTEX_FINALIZE ();
}
--- a/gfx/cairo/cairo/src/cairo-deflate-stream.c
+++ b/gfx/cairo/cairo/src/cairo-deflate-stream.c
@@ -116,23 +116,24 @@ cairo_output_stream_t *
_cairo_deflate_stream_create (cairo_output_stream_t *output)
{
cairo_deflate_stream_t *stream;
if (output->status)
return _cairo_output_stream_create_in_error (output->status);
stream = malloc (sizeof (cairo_deflate_stream_t));
- if (stream == NULL) {
+ if (unlikely (stream == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_output_stream_t *) &_cairo_output_stream_nil;
}
_cairo_output_stream_init (&stream->base,
_cairo_deflate_stream_write,
+ NULL,
_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) {
--- a/gfx/cairo/cairo/src/cairo-directfb-surface.c
+++ b/gfx/cairo/cairo/src/cairo-directfb-surface.c
@@ -450,17 +450,17 @@ static cairo_surface_t *
"%s( src=%p, content=0x%x, width=%d, height=%d).\n",
__FUNCTION__, source, content, width, height);
width = (width <= 0) ? 1 : width;
height = (height<= 0) ? 1 : height;
format = _cairo_format_from_content (content);
surface = calloc (1, sizeof (cairo_directfb_surface_t));
- if (surface == NULL)
+ if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
surface->dfb = source->dfb;
if (width < 8 || height < 8) {
IDirectFBSurface *tmp;
DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height };
@@ -544,16 +544,17 @@ static cairo_status_t
NULL, image_extra, DSLF_READ);
}
static void
_cairo_directfb_surface_release_source_image (void *abstract_surface,
cairo_image_surface_t *image,
void *image_extra)
{
+ cairo_directfb_surface_t *surface = abstract_surface;
IDirectFBSurface *buffer = image_extra;
D_DEBUG_AT (CairoDFB_Acquire,
"%s( surface=%p ).\n", __FUNCTION__, surface);
buffer->Unlock (buffer);
cairo_surface_destroy (&image->base);
@@ -697,18 +698,18 @@ static cairo_status_t
}
return CAIRO_INT_STATUS_UNSUPPORTED;
}
#if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS
static cairo_int_status_t
_directfb_prepare_composite (cairo_directfb_surface_t *dst,
- cairo_pattern_t *src_pattern,
- cairo_pattern_t *mask_pattern,
+ const cairo_pattern_t *src_pattern,
+ const cairo_pattern_t *mask_pattern,
cairo_operator_t op,
int *src_x, int *src_y,
int *mask_x, int *mask_y,
unsigned int width,
unsigned int height,
cairo_directfb_surface_t **ret_src,
cairo_surface_attributes_t *ret_src_attr)
{
@@ -727,17 +728,17 @@ static cairo_int_status_t
if (! _directfb_get_operator (op, &sblend, &dblend))
return CAIRO_INT_STATUS_UNSUPPORTED;
if (mask_pattern) {
cairo_solid_pattern_t *pattern;
return CAIRO_INT_STATUS_UNSUPPORTED;
if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
- cairo_pattern_t *tmp;
+ const cairo_pattern_t *tmp;
int tmp_x, tmp_y;
if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID ||
sblend == DSBF_INVDESTALPHA) /* Doesn't work correctly */
return CAIRO_INT_STATUS_UNSUPPORTED;
D_DEBUG_AT (CairoDFB_Render, "Replacing src pattern by mask pattern.\n");
@@ -756,21 +757,16 @@ static cairo_int_status_t
}
}
color = &((cairo_solid_pattern_t *) mask_pattern)->color;
} else {
color = _cairo_stock_color (CAIRO_STOCK_WHITE);
}
- /* XXX DirectFB currently does not support filtering, so force NEAREST
- * in order to hit optimisations inside core.
- */
- src_pattern->filter = CAIRO_FILTER_NEAREST;
-
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
*src_x, *src_y, width, height,
(cairo_surface_t **) &src,
&src_attr);
if (status)
return status;
if (src->base.backend != &_cairo_directfb_surface_backend ||
@@ -837,17 +833,17 @@ static cairo_int_status_t
*ret_src = src;
*ret_src_attr = src_attr;
return CAIRO_STATUS_SUCCESS;
}
static void
_directfb_finish_composite (cairo_directfb_surface_t *dst,
- cairo_pattern_t *src_pattern,
+ const cairo_pattern_t *src_pattern,
cairo_surface_t *src,
cairo_surface_attributes_t *src_attr)
{
_cairo_pattern_release_surface (src_pattern, src, src_attr);
}
#endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */
#if DFB_COMPOSITE
@@ -887,18 +883,18 @@ static DFBAccelerationMask
case CAIRO_EXTEND_REFLECT:
case CAIRO_EXTEND_PAD:
return DFXL_NONE;
}
}
static cairo_int_status_t
_cairo_directfb_surface_composite (cairo_operator_t op,
- cairo_pattern_t *src_pattern,
- cairo_pattern_t *mask_pattern,
+ const cairo_pattern_t *src_pattern,
+ const cairo_pattern_t *mask_pattern,
void *abstract_dst,
int src_x, int src_y,
int mask_x, int mask_y,
int dst_x, int dst_y,
unsigned int width,
unsigned int height)
{
cairo_directfb_surface_t *dst = abstract_dst;
@@ -1155,17 +1151,17 @@ static cairo_int_status_t
return CAIRO_STATUS_SUCCESS;
}
#endif
#if DFB_COMPOSITE_TRAPEZOIDS
static cairo_int_status_t
_cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
- cairo_pattern_t *pattern,
+ const cairo_pattern_t *pattern,
void *abstract_dst,
cairo_antialias_t antialias,
int src_x, int src_y,
int dst_x, int dst_y,
unsigned int width,
unsigned int height,
cairo_trapezoid_t *traps,
int num_traps)
@@ -1298,51 +1294,50 @@ static cairo_int_status_t
{
cairo_directfb_surface_t *surface = abstract_surface;
D_DEBUG_AT (CairoDFB_Clip,
"%s( surface=%p, region=%p ).\n",
__FUNCTION__, surface, region);
if (region) {
- cairo_box_int_t *boxes;
int n_boxes;
cairo_status_t status;
int i;
surface->has_clip = TRUE;
- status = _cairo_region_get_boxes (region, &n_boxes, &boxes);
+ n_boxes = _cairo_region_num_boxes (region);
+
if (n_boxes == 0)
return CAIRO_STATUS_SUCCESS;
- if (status)
- return status;
if (surface->n_clips != n_boxes) {
if (surface->clips)
free (surface->clips);
surface->clips = _cairo_malloc_ab (n_boxes, sizeof (DFBRegion));
if (!surface->clips) {
surface->n_clips = 0;
- _cairo_region_boxes_fini (region, boxes);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
surface->n_clips = n_boxes;
}
for (i = 0; i < n_boxes; i++) {
- surface->clips[i].x1 = boxes[i].p1.x;
- surface->clips[i].y1 = boxes[i].p1.y;
- surface->clips[i].x2 = boxes[i].p2.x - 1;
- surface->clips[i].y2 = boxes[i].p2.y - 1;
+ cairo_box_int_t box;
+
+ _cairo_region_get_box (region, i, &box);
+
+ surface->clips[i].x1 = box.p1.x;
+ surface->clips[i].y1 = box.p1.y;
+ surface->clips[i].x2 = box.p2.x - 1;
+ surface->clips[i].y2 = box.p2.y - 1;
}
-
- _cairo_region_boxes_fini (region, boxes);
} else {
surface->has_clip = FALSE;
if (surface->clips) {
free (surface->clips);
surface->clips = NULL;
surface->n_clips = 0;
}
}
@@ -1427,17 +1422,17 @@ static cairo_status_t
int x = 0;
int y = 0;
int w = 8;
int h = 8;
int i;
D_DEBUG_AT (CairoDFB_Font, "%s( %p [%d] )\n", __FUNCTION__, glyphs, num_glyphs );
- _cairo_cache_freeze (scaled_font->glyphs);
+ _cairo_scaled_font_freeze_cache (scaled_font);
if (scaled_font->surface_private) {
cache = scaled_font->surface_private;
x = cache->x;
y = cache->y;
}
for (i = 0; i < num_glyphs; i++) {
@@ -1445,30 +1440,30 @@ static cairo_status_t
cairo_image_surface_t *img;
D_DEBUG_AT (CairoDFB_Font, " -> [%2d] = %4lu\n", i, glyphs[i].index );
status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
if (status) {
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
return status;
}
img = scaled_glyph->surface;
switch (img->format) {
case CAIRO_FORMAT_A1:
case CAIRO_FORMAT_A8:
case CAIRO_FORMAT_ARGB32:
break;
default:
D_DEBUG_AT (CairoDFB_Font,
" -> Unsupported font format %d!\n", img->format);
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
points[n].x = _cairo_lround (glyphs[i].x - img->base.device_transform.x0);
points[n].y = _cairo_lround (glyphs[i].y - img->base.device_transform.y0);
// D_DEBUG_AT (CairoDFB_Font, " (%4d,%4d) [%2d]\n", points[n].x, points[n].y, n );
@@ -1496,17 +1491,17 @@ static cairo_status_t
x += img->width;
h = MAX (h, img->height);
w = MAX (w, x);
/* Remember glyph location */
rect = malloc (sizeof (DFBRectangle));
if (rect == NULL) {
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
*rect = rects[n];
scaled_glyph->surface_private = rect;
chars[num_chars++] = scaled_glyph;
D_DEBUG_AT (CairoDFB_Font, " -> loading at %4d,%2d <- rect %p, img %p, entry %p\n",
@@ -1516,74 +1511,74 @@ static cairo_status_t
D_DEBUG_AT (CairoDFB_Font, " -> exists at %4d,%2d\n", rects[n].x, rects[n].y);
}
n++;
}
if (n == 0) {
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
h += y;
w = MAX (w, 8);
h = MAX (h, 8);
/* XXX query maximum surface size */
if (w > 2048 || h > 2048) {
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (cache) {
if (cache->width < w || cache->height < h) {
cairo_directfb_font_cache_t *new_cache;
w = MAX (w, cache->width);
h = MAX (h, cache->height);
D_DEBUG_AT (CairoDFB_Font, " -> Reallocating font cache (%dx%d).\n", w, h);
status = _directfb_allocate_font_cache (surface->dfb,
w, h,
&new_cache);
if (status) {
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
return status;
}
new_cache->dfbsurface->Blit (new_cache->dfbsurface,
cache->dfbsurface, NULL, 0, 0);
_directfb_destroy_font_cache (cache);
scaled_font->surface_private = cache = new_cache;
}
} else {
D_DEBUG_AT (CairoDFB_Font, " -> Allocating font cache (%dx%d).\n", w, h);
status = _directfb_allocate_font_cache (surface->dfb, w, h, &cache);
if (status) {
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
return status;
}
scaled_font->surface_backend = &_cairo_directfb_surface_backend;
scaled_font->surface_private = cache;
}
if (num_chars) {
unsigned char *data;
int pitch;
if (cache->dfbsurface->Lock (cache->dfbsurface,
DSLF_WRITE, (void *)&data, &pitch))
{
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
D_DEBUG_AT (CairoDFB_Font, " => %d chars to load, cache %dx%d\n", num_chars, cache->width, cache->height);
for (i = 0; i < num_chars; i++) {
cairo_image_surface_t *img = chars[i]->surface;
DFBRectangle *rect = chars[i]->surface_private;
@@ -1639,17 +1634,17 @@ static cairo_status_t
src += img->stride;
}
}
}
cache->dfbsurface->Unlock (cache->dfbsurface);
}
- _cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_scaled_font_thaw_cache (scaled_font);
cache->x = x;
cache->y = y;
D_DEBUG_AT (CairoDFB_Font, " => cache %d,%d, %p [%d]\n", x, y, cache, n);
*ret_cache = cache;
*ret_num = n;
@@ -1681,23 +1676,24 @@ static void
if (scaled_glyph->surface_private != NULL) {
free (scaled_glyph->surface_private);
scaled_glyph->surface_private = NULL;
}
}
static cairo_int_status_t
-_cairo_directfb_surface_show_glyphs (void *abstract_dst,
- cairo_operator_t op,
- cairo_pattern_t *pattern,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- int *remaining_glyphs)
+_cairo_directfb_surface_show_glyphs (void *abstract_dst,
+ cairo_operator_t op,
+ const cairo_pattern_t *pattern,
+ cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font,
+ int *remaining_glyphs,
+ cairo_rectangle_int_t *extents)
{
cairo_directfb_surface_t *dst = abstract_dst;
cairo_directfb_font_cache_t *cache;
cairo_status_t status;
DFBSurfaceBlittingFlags flags;
DFBSurfaceBlendFunction sblend;
DFBSurfaceBlendFunction dblend;
DFBRectangle rects[num_glyphs];
@@ -1812,16 +1808,18 @@ static cairo_surface_backend_t
#else
NULL,/*fill_rectangles*/
#endif
#if DFB_COMPOSITE_TRAPEZOIDS
_cairo_directfb_surface_composite_trapezoids,/*composite_trapezoids*/
#else
NULL,/*composite_trapezoids*/
#endif
+ NULL, /* create_span_renderer */
+ NULL, /* check_span_renderer */
NULL, /* copy_page */
NULL, /* show_page */
_cairo_directfb_surface_set_clip_region,/* set_clip_region */
NULL, /* intersect_clip_path */
_cairo_directfb_abstract_surface_get_extents,/* get_extents */
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
--- a/gfx/cairo/cairo/src/cairo-font-face-twin-data.c
+++ b/gfx/cairo/cairo/src/cairo-font-face-twin-data.c
@@ -1,49 +1,55 @@
/* See cairo-font-face-twin.c for copyright info */
#include "cairoint.h"
const int8_t _cairo_twin_outlines[] = {
/* 0x0 '\0' offset 0 */
- 0, 24, 42, 0, 2, 4,
+ 0, 24, 42, 0, 2, 2,
0, 24, /* snap_x */
- -42, -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, 0,
'l', 0, -42,
'l', 24, -42,
'l', 24, 0,
'l', 0, 0,
'e',
+ 'X', 'X',
/* 0x20 ' ' offset 28 */
- 0, 4, 0, 0, 2, 3,
- -128, 0, /* snap_x */
- -21, -15, 0, /* snap_y */
+ 0, 4, 0, 0, 0, 0,
+ /* snap_x */
+ /* snap_y */
'e',
+ 'X', 'X', 'X',
+ 'X', 'X',
/* 0x21 '!' offset 40 */
- 0, 4, 42, 0, 3, 3,
- 0, 2, 4, /* snap_x */
- -21, -15, 0, /* snap_y */
- 'm', 2, -42,
- 'l', 2, -14,
- 'm', 2, -4,
- 'c', 1, -4, 0, -3, 0, -2,
- 'c', 0, -1, 1, 0, 2, 0,
- 'c', 3, 0, 4, -1, 4, -2,
- 'c', 4, -3, 3, -4, 2, -4,
+ 0, 0, 42, 0, 1, 3,
+ 0, /* snap_x */
+ -42, -14, 0, /* snap_y */
+ 'm', 0, -42,
+ 'l', 0, -14,
+ 'm', 0, 0,
+ 'l', 0, 0,
'e',
+ 'X', 'X', 'X', 'X', 'X', 'X',
+ 'X', 'X', 'X', 'X', 'X', 'X',
+ 'X', 'X', 'X', 'X', 'X', 'X',
+ 'X', 'X', 'X', 'X', 'X', 'X',
+ 'X', 'X', 'X',
/* 0x22 '"' offset 90 */
- 0, 16, 42, -28, 2, 3,
+ 0, 16, 42, -28, 2, 2,
0, 16, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, -28, /* snap_y */
'm', 0, -42,
'l', 0, -28,
'm', 16, -42,
'l', 16, -28,
'e',
+ 'X',
/* 0x23 '#' offset 114 */
0, 30, 50, 14, 2, 5,
0, 30, /* snap_x */
-24, -21, -15, -12, 0, /* snap_y */
'm', 16, -50,
'l', 2, 14,
'm', 28, -50,
'l', 14, 14,
@@ -97,37 +103,40 @@ const int8_t _cairo_twin_outlines[] = {
'c', 29, -28, 32, 0, 12, 0,
'c', 0, 0, 0, -8, 0, -10,
'c', 0, -24, 22, -20, 22, -34,
'c', 22, -45, 10, -45, 10, -34,
'c', 10, -27, 25, 0, 36, 0,
'c', 39, 0, 40, -1, 40, -4,
'e',
/* 0x27 ''' offset 390 */
- 0, 4, 42, -30, 2, 3,
+ 0, 4, 42, -30, 2, 2,
0, 4, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, -28, /* snap_y */
'm', 2, -38,
'c', -1, -38, -1, -42, 2, -42,
'c', 6, -42, 5, -33, 0, -30,
'e',
+ 'X',
/* 0x28 '(' offset 419 */
- 0, 14, 50, 14, 2, 3,
+ 0, 14, 50, 14, 2, 2,
0, 14, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -50, 14, /* snap_y */
'm', 14, -50,
'c', -5, -32, -5, -5, 14, 14,
'e',
+ 'X',
/* 0x29 ')' offset 441 */
- 0, 14, 50, 14, 2, 3,
+ 0, 14, 50, 14, 2, 2,
0, 14, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -15, 14, /* snap_y */
'm', 0, -50,
'c', 19, -34, 19, -2, 0, 14,
'e',
+ 'X',
/* 0x2a '*' offset 463 */
0, 20, 30, -6, 3, 3,
0, 10, 20, /* snap_x */
-21, -15, 0, /* snap_y */
'm', 10, -30,
'l', 10, -6,
'm', 0, -24,
'l', 20, -12,
@@ -182,17 +191,17 @@ const int8_t _cairo_twin_outlines[] = {
'c', 9, -42, 0, -42, 0, -21,
'c', 0, 0, 9, 0, 14, 0,
'c', 19, 0, 28, 0, 28, -21,
'c', 28, -42, 19, -42, 14, -42,
'E',
/* 0x31 '1' offset 666 */
0, 28, 42, 0, 2, 3,
0, 17, 28 /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, -34, 0, /* snap_y */
'm', 7, -34,
'c', 11, -35, 15, -38, 17, -42,
'l', 17, 0,
'e',
/* 0x32 '2' offset 691 */
0, 28, 42, 0, 4, 4,
0, 2, 26, 28, /* snap_x */
-42, -21, -15, 0, /* snap_y */
@@ -210,25 +219,26 @@ const int8_t _cairo_twin_outlines[] = {
'm', 4, -42,
'l', 26, -42,
'l', 14, -26,
'c', 21, -26, 28, -26, 28, -14,
'c', 28, 0, 17, 0, 13, 0,
'c', 8, 0, 3, -1, 0, -8,
'e',
/* 0x34 '4' offset 780 */
- 0, 28, 42, 0, 3, 4,
+ 0, 28, 42, 0, 3, 3,
0, 20, 30, /* snap_x */
- -21, -15, -14, 0, /* snap_y */
+ -42, -14, 0, /* snap_y */
'm', 20, 0,
'l', 20, -42,
'l', 0, -14,
'l', 30, -14,
'e',
'X', 'X', 'X',
+ 'X',
/* 0x35 '5' offset 809 */
0, 28, 42, 0, 2, 5,
0, 28, /* snap_x */
-42, -28, -21, -15, 0, /* snap_y */
'm', 24, -42,
'l', 4, -42,
'l', 2, -24,
'c', 5, -27, 10, -28, 13, -28,
@@ -302,51 +312,55 @@ const int8_t _cairo_twin_outlines[] = {
'm', 4, -2,
'c', 4, 1, 0, 1, 0, -2,
'c', 0, -5, 4, -5, 4, -2,
'c', 4, 3, 2, 6, 0, 8,
'e',
/* 0x3c '<' offset 1162 */
0, 32, 36, 0, 2, 3,
0, 32, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -36, -18, 0, /* snap_y */
'm', 32, -36,
'l', 0, -18,
'l', 32, 0,
'e',
/* 0x3d '=' offset 1183 */
- 0, 36, 24, -12, 2, 5,
+ 0, 36, 24, -12, 2, 2,
0, 36, /* snap_x */
- -24, -21, -15, -12, 0, /* snap_y */
+ -24, -15, /* snap_y */
'm', 0, -24,
'l', 36, -24,
'm', 0, -12,
'l', 36, -12,
'e',
+ 'X', 'X', 'X',
/* 0x3e '>' offset 1209 */
0, 32, 36, 0, 2, 3,
0, 32, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -36, -18, 0, /* snap_y */
'm', 0, -36,
'l', 32, -18,
'l', 0, 0,
'e',
/* 0x3f '?' offset 1230 */
0, 24, 42, 0, 3, 4,
0, 12, 24, /* snap_x */
-42, -21, -15, 0, /* snap_y */
'm', 0, -32,
'c', 0, -34, 0, -42, 12, -42,
'c', 24, -42, 24, -34, 24, -32,
'c', 24, -29, 24, -24, 12, -20,
'l', 12, -14,
- 'm', 12, -4,
- 'c', 9, -4, 9, 0, 12, 0,
- 'c', 15, 0, 15, -4, 12, -4,
+ 'm', 12, 0,
+ 'l', 12, 0,
'e',
+ 'X', 'X', 'X',
+ 'X', 'X', 'X',
+ 'X', 'X', 'X',
+ 'X', 'X',
/* 0x40 '@' offset 1288 */
0, 42, 42, 0, 1, 6,
30, /* snap_x */
-42, -32, -21, -15, -10, 0, /* snap_y */
'm', 30, -26,
'c', 28, -31, 24, -32, 21, -32,
'c', 10, -32, 10, -23, 10, -19,
'c', 10, -13, 11, -10, 19, -10,
@@ -354,168 +368,178 @@ const int8_t _cairo_twin_outlines[] = {
'c', 27, -10, 30, -10, 34, -10,
'c', 41, -10, 42, -19, 42, -22,
'c', 42, -34, 34, -42, 21, -42,
'c', 9, -42, 0, -34, 0, -21,
'c', 0, -9, 8, 0, 21, 0,
'c', 30, 0, 34, -3, 36, -6,
'e',
/* 0x41 'A' offset 1375 */
- 0, 32, 42, 0, 2, 4,
+ 0, 32, 42, 0, 2, 3,
0, 32, /* snap_x */
- -21, -15, -14, 0, /* snap_y */
+ -42, -14, 0, /* snap_y */
'm', 0, 0,
'l', 16, -42,
'l', 32, 0,
'm', 6, -14,
'l', 26, -14,
'e',
'X', 'X', 'X',
+ 'X',
/* 0x42 'B' offset 1406 */
- 0, 28, 42, 0, 2, 5,
+ 0, 28, 42, 0, 2, 3,
0, 28, /* snap_x */
- -42, -22, -21, -15, 0, /* snap_y */
+ -42, -22, 0, /* snap_y */
'm', 0, 0,
'l', 0, -42,
'l', 18, -42,
'c', 32, -42, 32, -22, 18, -22,
'l', 0, -22,
'l', 18, -22,
'c', 32, -22, 32, 0, 18, 0,
'E',
'X', 'X', 'X',
'X', 'X', 'X',
+ 'X', 'X',
/* 0x43 'C' offset 1455 */
0, 30, 42, 0, 2, 4,
0, 30, /* snap_x */
-42, -21, -15, 0, /* snap_y */
'm', 30, -32,
'c', 26, -42, 21, -42, 16, -42,
'c', 2, -42, 0, -29, 0, -21,
'c', 0, -13, 2, 0, 16, 0,
'c', 21, 0, 26, 0, 30, -10,
'e',
/* 0x44 'D' offset 1499 */
- 0, 28, 42, 0, 2, 4,
+ 0, 28, 42, 0, 2, 2,
0, 28, /* snap_x */
- -42, -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, 0,
'l', 0, -42,
'l', 14, -42,
'c', 33, -42, 33, 0, 14, 0,
'E',
'X', 'X', 'X',
'X', 'X', 'X',
+ 'X', 'X',
/* 0x45 'E' offset 1534 */
- 0, 26, 42, 0, 2, 5,
+ 0, 26, 42, 0, 2, 3,
0, 26, /* snap_x */
- -42, -22, -21, -15, 0, /* snap_y */
+ -42, -22, 0, /* snap_y */
'm', 26, -42,
'l', 0, -42,
'l', 0, 0,
'l', 26, 0,
'm', 0, -22,
'l', 16, -22,
'e',
'X', 'X', 'X',
'X', 'X', 'X',
+ 'X', 'X',
/* 0x46 'F' offset 1572 */
- 0, 26, 42, 0, 2, 5,
+ 0, 26, 42, 0, 2, 3,
0, 26, /* snap_x */
- -42, -22, -21, -15, 0, /* snap_y */
+ -42, -22, 0, /* snap_y */
'm', 0, 0,
'l', 0, -42,
'l', 26, -42,
'm', 0, -22,
'l', 16, -22,
'e',
'X', 'X', 'X',
+ 'X', 'X',
/* 0x47 'G' offset 1604 */
0, 30, 42, 0, 2, 5,
0, 30, /* snap_x */
-42, -21, -16, -15, 0, /* snap_y */
'm', 30, -32,
'c', 26, -42, 21, -42, 16, -42,
'c', 2, -42, 0, -29, 0, -21,
'c', 0, -13, 2, 0, 16, 0,
'c', 28, 0, 30, -7, 30, -16,
'l', 20, -16,
'e',
'X', 'X', 'X',
/* 0x48 'H' offset 1655 */
- 0, 28, 42, 0, 2, 4,
+ 0, 28, 42, 0, 2, 3,
0, 28, /* snap_x */
- -22, -21, -15, 0, /* snap_y */
+ -42, -22, 0, /* snap_y */
'm', 0, -42,
'l', 0, 0,
'm', 28, -42,
'l', 28, 0,
'm', 0, -22,
'l', 28, -22,
'e',
+ 'X',
/* 0x49 'I' offset 1686 */
- 0, 0, 42, 0, 1, 3,
+ 0, 0, 42, 0, 1, 2,
0, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, -42,
'l', 0, 0,
'e',
+ 'X',
/* 0x4a 'J' offset 1703 */
0, 20, 42, 0, 2, 3,
0, 20, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, -15, 0, /* snap_y */
'm', 20, -42,
'l', 20, -10,
'c', 20, 3, 0, 3, 0, -10,
'l', 0, -14,
'e',
/* 0x4b 'K' offset 1731 */
0, 28, 42, 0, 2, 3,
0, 28, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, -15, 0, /* snap_y */
'm', 0, -42,
'l', 0, 0,
'm', 28, -42,
'l', 0, -14,
'm', 10, -24,
'l', 28, 0,
'e',
/* 0x4c 'L' offset 1761 */
- 0, 24, 42, 0, 2, 3,
+ 0, 24, 42, 0, 2, 2,
0, 24, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, -42,
'l', 0, 0,
'l', 24, 0,
'e',
'X', 'X', 'X',
+ 'X',
/* 0x4d 'M' offset 1785 */
- 0, 32, 42, 0, 2, 3,
+ 0, 32, 42, 0, 2, 2,
0, 32, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, 0,
'l', 0, -42,
'l', 16, 0,
'l', 32, -42,
'l', 32, 0,
'e',
'X', 'X', 'X',
'X', 'X', 'X',
'X', 'X', 'X',
+ 'X',
/* 0x4e 'N' offset 1821 */
- 0, 28, 42, 0, 2, 3,
+ 0, 28, 42, 0, 2, 2,
0, 28, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, 0,
'l', 0, -42,
'l', 28, 0,
'l', 28, -42,
'e',
'X', 'X', 'X',
'X', 'X', 'X',
+ 'X',
/* 0x4f 'O' offset 1851 */
0, 32, 42, 0, 2, 4,
0, 32, /* snap_x */
-42, -21, -15, 0, /* snap_y */
'm', 16, -42,
'c', 2, -42, 0, -29, 0, -21,
'c', 0, -13, 2, 0, 16, 0,
'c', 30, 0, 32, -13, 32, -21,
@@ -536,17 +560,17 @@ const int8_t _cairo_twin_outlines[] = {
0, 32, 42, 4, 2, 4,
0, 32, /* snap_x */
-42, -21, -15, 0, /* snap_y */
'm', 16, -42,
'c', 2, -42, 0, -29, 0, -21,
'c', 0, -13, 2, 0, 16, 0,
'c', 30, 0, 32, -13, 32, -21,
'c', 32, -29, 30, -42, 16, -42,
- 'm', 18, -8,
+ 'M', 18, -8,
'l', 30, 4,
'e',
/* 0x52 'R' offset 1981 */
0, 28, 42, 0, 2, 5,
0, 28, /* snap_x */
-42, -22, -21, -15, 0, /* snap_y */
'm', 0, 0,
'l', 0, -42,
@@ -573,59 +597,63 @@ const int8_t _cairo_twin_outlines[] = {
0, 14, 28, /* snap_x */
-42, -21, -15, 0, /* snap_y */
'm', 14, -42,
'l', 14, 0,
'm', 0, -42,
'l', 28, -42,
'e',
/* 0x55 'U' offset 2100 */
- 0, 28, 42, 0, 2, 3,
+ 0, 28, 42, 0, 2, 2,
0, 28, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, -42,
'l', 0, -12,
'c', 0, 4, 28, 4, 28, -12,
'l', 28, -42,
'e',
+ 'X',
/* 0x56 'V' offset 2128 */
- 0, 32, 42, 0, 2, 3,
+ 0, 32, 42, 0, 2, 2,
0, 32, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, -42,
'l', 16, 0,
'l', 32, -42,
'e',
'X', 'X', 'X',
+ 'X',
/* 0x57 'W' offset 2152 */
- 0, 40, 42, 0, 2, 3,
+ 0, 40, 42, 0, 2, 2,
0, 40, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, -42,
'l', 10, 0,
'l', 20, -42,
'l', 30, 0,
'l', 40, -42,
'e',
'X', 'X', 'X',
'X', 'X', 'X',
'X', 'X', 'X',
+ 'X',
/* 0x58 'X' offset 2188 */
- 0, 28, 42, 0, 2, 3,
+ 0, 28, 42, 0, 2, 2,
0, 28, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, -42,
'l', 28, 0,
'm', 28, -42,
'l', 0, 0,
'e',
+ 'X',
/* 0x59 'Y' offset 2212 */
0, 32, 42, 0, 3, 3,
0, 16, 32, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, -21, 0, /* snap_y */
'm', 0, -42,
'l', 16, -22,
'l', 16, 0,
'm', 32, -42,
'l', 16, -22,
'e',
/* 0x5a 'Z' offset 2240 */
0, 28, 42, 0, 2, 4,
@@ -668,47 +696,49 @@ const int8_t _cairo_twin_outlines[] = {
0, 32, /* snap_x */
-21, -15, 0, /* snap_y */
'm', 0, -18,
'l', 16, -46,
'l', 32, -18,
'e',
'X', 'X', 'X',
/* 0x5f '_' offset 2363 */
- 0, 36, 0, 0, 2, 3,
+ 0, 36, 0, 0, 2, 1,
0, 36, /* snap_x */
- -21, -15, 0, /* snap_y */
+ 0, /* snap_y */
'm', 0, 0,
'l', 36, 0,
'e',
+ 'X', 'X',
/* 0x60 '`' offset 2381 */
- 0, 4, 42, -30, 2, 3,
+ 0, 4, 42, -30, 2, 2,
0, 4, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 4, -42,
'c', 2, -40, 0, -39, 0, -32,
'c', 0, -31, 1, -30, 2, -30,
'c', 5, -30, 5, -34, 2, -34,
'e',
+ 'X',
/* 0x61 'a' offset 2417 */
0, 24, 28, 0, 2, 4,
0, 24, /* snap_x */
-28, -21, -15, 0, /* snap_y */
'm', 24, -28,
'l', 24, 0,
'm', 24, -22,
'c', 21, -27, 18, -28, 13, -28,
'c', 2, -28, 0, -19, 0, -14,
'c', 0, -9, 2, 0, 13, 0,
'c', 18, 0, 21, -1, 24, -6,
'e',
/* 0x62 'b' offset 2467 */
0, 24, 42, 0, 2, 4,
0, 24, /* snap_x */
- -28, -21, -15, 0, /* snap_y */
+ -42, -28, -15, 0, /* snap_y */
'm', 0, -42,
'l', 0, 0,
'm', 0, -22,
'c', 3, -26, 6, -28, 11, -28,
'c', 22, -28, 24, -19, 24, -14,
'c', 24, -9, 22, 0, 11, 0,
'c', 6, 0, 3, -2, 0, -6,
'e',
@@ -720,17 +750,17 @@ const int8_t _cairo_twin_outlines[] = {
'c', 21, -26, 18, -28, 13, -28,
'c', 2, -28, 0, -19, 0, -14,
'c', 0, -9, 2, 0, 13, 0,
'c', 18, 0, 21, -2, 24, -6,
'e',
/* 0x64 'd' offset 2561 */
0, 24, 42, 0, 2, 4,
0, 24, /* snap_x */
- -28, -21, -15, 0, /* snap_y */
+ -42, -28, -15, 0, /* snap_y */
'm', 24, -42,
'l', 24, 0,
'm', 24, -22,
'c', 21, -26, 18, -28, 13, -28,
'c', 2, -28, 0, -19, 0, -14,
'c', 0, -9, 2, 0, 13, 0,
'c', 18, 0, 21, -2, 24, -6,
'e',
@@ -767,111 +797,121 @@ const int8_t _cairo_twin_outlines[] = {
'c', 21, -26, 18, -28, 13, -28,
'c', 2, -28, 0, -19, 0, -14,
'c', 0, -9, 2, 0, 13, 0,
'c', 18, 0, 21, -2, 24, -6,
'e',
/* 0x68 'h' offset 2758 */
0, 22, 42, 0, 2, 4,
0, 22, /* snap_x */
- -28, -21, -15, 0, /* snap_y */
+ -42, -28, -15, 0, /* snap_y */
'm', 0, -42,
'l', 0, 0,
'm', 0, -20,
'c', 8, -32, 22, -31, 22, -20,
'l', 22, 0,
'e',
/* 0x69 'i' offset 2790 */
- 0, 4, 44, 0, 3, 3,
- 0, 2, 4, /* snap_x */
- -21, -15, 0, /* snap_y */
+ 0, 0, 44, 0, 1, 3,
+ 0, /* snap_x */
+ -42, -28, 0, /* snap_y */
'm', 0, -42,
- 'c', 0, -39, 4, -39, 4, -42,
- 'c', 4, -45, 0, -45, 0, -42,
- 'm', 2, -28,
- 'l', 2, 0,
+ 'l', 0, -42,
+ 'm', 0, -28,
+ 'l', 0, 0,
'e',
+ 'X', 'X', 'X',
+ 'X', 'X', 'X',
+ 'X', 'X', 'X',
+ 'X', 'X',
+ 'X', 'X',
/* 0x6a 'j' offset 2826 */
- -8, 4, 44, 14, 3, 4,
- 0, 2, 4, /* snap_x */
- -21, -15, 0, 14, /* snap_y */
- 'm', 0, -42,
- 'c', 0, -39, 4, -39, 4, -42,
- 'c', 4, -45, 0, -45, 0, -42,
+ -8, 4, 44, 14, 3, 5,
+ -8, 2, 4, /* snap_x */
+ -42, -21, -15, 0, 14, /* snap_y */
+ 'm', 2, -42,
+ 'l', 2, -42,
'm', 2, -28,
'l', 2, 6,
'c', 2, 13, -1, 14, -8, 14,
'e',
+ 'X', 'X', 'X',
+ 'X', 'X', 'X',
+ 'X', 'X', 'X',
+ 'X',
/* 0x6b 'k' offset 2870 */
0, 22, 42, 0, 2, 3,
0, 22, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, -28, 0, /* snap_y */
'm', 0, -42,
'l', 0, 0,
'm', 20, -28,
'l', 0, -8,
'm', 8, -16,
'l', 22, 0,
'e',
/* 0x6c 'l' offset 2900 */
- 0, 0, 42, 0, 1, 3,
+ 0, 0, 42, 0, 1, 2,
0, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -42, 0, /* snap_y */
'm', 0, -42,
'l', 0, 0,
'e',
+ 'X',
/* 0x6d 'm' offset 2917 */
- 0, 44, 28, 0, 3, 4,
+ 0, 44, 28, 0, 3, 3,
0, 22, 44, /* snap_x */
- -28, -21, -15, 0, /* snap_y */
+ -28, -21, 0, /* snap_y */
'm', 0, -28,
'l', 0, 0,
'm', 0, -20,
'c', 5, -29, 22, -33, 22, -20,
'l', 22, 0,
'm', 22, -20,
'c', 27, -29, 44, -33, 44, -20,
'l', 44, 0,
'e',
+ 'X',
/* 0x6e 'n' offset 2963 */
- 0, 22, 28, 0, 2, 4,
+ 0, 22, 28, 0, 2, 3,
0, 22, /* snap_x */
- -28, -21, -15, 0, /* snap_y */
+ -28, -21, 0, /* snap_y */
'm', 0, -28,
'l', 0, 0,
'm', 0, -20,
'c', 4, -28, 22, -34, 22, -20,
'l', 22, 0,
'e',
+ 'X',
/* 0x6f 'o' offset 2995 */
0, 26, 28, 0, 2, 4,
0, 26, /* snap_x */
-28, -21, -15, 0, /* snap_y */
'm', 13, -28,
'c', 2, -28, 0, -19, 0, -14,
'c', 0, -9, 2, 0, 13, 0,
'c', 24, 0, 26, -9, 26, -14,
'c', 26, -19, 24, -28, 13, -28,
- 'e',
+ 'E',
/* 0x70 'p' offset 3039 */
0, 24, 28, 14, 2, 4,
0, 24, /* snap_x */
- -28, -21, -15, 0, /* snap_y */
+ -28, -21, 0, 14, /* snap_y */
'm', 0, -28,
'l', 0, 14,
'm', 0, -22,
'c', 3, -26, 6, -28, 11, -28,
'c', 22, -28, 24, -19, 24, -14,
'c', 24, -9, 22, 0, 11, 0,
'c', 6, 0, 3, -2, 0, -6,
'e',
/* 0x71 'q' offset 3089 */
0, 24, 28, 14, 2, 4,
0, 24, /* snap_x */
- -28, -21, -15, 0, /* snap_y */
+ -28, -21, 0, 14, /* snap_y */
'm', 24, -28,
'l', 24, 14,
'm', 24, -22,
'c', 21, -26, 18, -28, 13, -28,
'c', 2, -28, 0, -19, 0, -14,
'c', 0, -9, 2, 0, 13, 0,
'c', 18, 0, 21, -2, 24, -6,
'e',
@@ -893,68 +933,69 @@ const int8_t _cairo_twin_outlines[] = {
'c', 4, -28, 0, -26, 0, -22,
'c', 0, -11, 22, -20, 22, -7,
'c', 22, 0, 17, 0, 11, 0,
'c', 6, 0, 0, -1, 0, -6,
'e',
/* 0x74 't' offset 3219 */
0, 16, 42, 0, 3, 4,
0, 6, 16, /* snap_x */
- -28, -21, -15, 0, /* snap_y */
+ -42, -28, -21, 0, /* snap_y */
'm', 6, -42,
'l', 6, -8,
'c', 6, -2, 8, 0, 16, 0,
'm', 0, -28,
'l', 14, -28,
'e',
/* 0x75 'u' offset 3252 */
0, 22, 28, 0, 2, 3,
0, 22, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -28, -15, 0, /* snap_y */
'm', 0, -28,
'l', 0, -8,
'c', 0, 6, 18, 0, 22, -8,
'm', 22, -28,
'l', 22, 0,
'e',
/* 0x76 'v' offset 3283 */
0, 24, 28, 0, 2, 3,
0, 24, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -28, -15, 0, /* snap_y */
'm', 0, -28,
'l', 12, 0,
'l', 24, -28,
'e',
'X', 'X', 'X',
/* 0x77 'w' offset 3307 */
0, 32, 28, 0, 2, 3,
0, 32, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -28, -15, 0, /* snap_y */
'm', 0, -28,
'l', 8, 0,
'l', 16, -28,
'l', 24, 0,
'l', 32, -28,
'e',
'X', 'X', 'X',
'X', 'X', 'X',
'X', 'X', 'X',
/* 0x78 'x' offset 3343 */
- 0, 22, 28, 0, 2, 3,
+ 0, 22, 28, 0, 2, 2,
0, 22, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -28, 0, /* snap_y */
'm', 0, -28,
'l', 22, 0,
'm', 22, -28,
'l', 0, 0,
'e',
+ 'X',
/* 0x79 'y' offset 3367 */
-2, 24, 28, 14, 2, 4,
0, 24, /* snap_x */
- -21, -15, 0, 14, /* snap_y */
+ -28, -15, 0, 14, /* snap_y */
'm', 0, -28,
'l', 12, 0,
'm', 24, -28,
'l', 12, 0,
'c', 6, 13, 0, 14, -2, 14,
'e',
/* 0x7a 'z' offset 3399 */
0, 22, 28, 0, 2, 4,
@@ -975,22 +1016,23 @@ const int8_t _cairo_twin_outlines[] = {
'c', 10, -44, 6, -42, 6, -36,
'l', 6, -24,
'l', 0, -24,
'l', 6, -24,
'l', 6, -8,
'c', 6, -2, 10, 0, 16, 0,
'e',
/* 0x7c '|' offset 3474 */
- 0, 0, 50, 14, 1, 3,
+ 0, 0, 50, 14, 1, 2,
0, /* snap_x */
- -21, -15, 0, /* snap_y */
+ -50, 14, /* snap_y */
'm', 0, -50,
'l', 0, 14,
'e',
+ 'X',
/* 0x7d '}' offset 3491 */
0, 16, 44, 0, 3, 5,
0, 10, 16, /* snap_x */
-44, -24, -21, -15, 0, /* snap_y */
'm', 0, -44,
'c', 6, -44, 10, -42, 10, -36,
'l', 10, -24,
'l', 16, -24,
--- a/gfx/cairo/cairo/src/cairo-font-face-twin.c
+++ b/gfx/cairo/cairo/src/cairo-font-face-twin.c
@@ -31,179 +31,687 @@
*
* Contributor(s):
* Keith Packard <keithp@keithp.com>
* Behdad Esfahbod <behdad@behdad.org>
*/
#include "cairoint.h"
+#include <math.h>
+
/*
- * This file implements a user-font rendering the decendant of the Hershey
+ * This file implements a user-font rendering the descendant of the Hershey
* font coded by Keith Packard for use in the Twin window system.
* The actual font data is in cairo-font-face-twin-data.c
*
- * Ported to cairo user font by Behdad Esfahbod.
+ * Ported to cairo user font and extended by Behdad Esfahbod.
+ */
+
+
+
+static cairo_user_data_key_t twin_properties_key;
+
+
+/*
+ * Face properties
*/
+/* We synthesize multiple faces from the twin data. Here is the parameters. */
+
+/* The following tables and matching code are copied from Pango */
+
+/* CSS weight */
+typedef enum {
+ TWIN_WEIGHT_THIN = 100,
+ TWIN_WEIGHT_ULTRALIGHT = 200,
+ TWIN_WEIGHT_LIGHT = 300,
+ TWIN_WEIGHT_BOOK = 380,
+ TWIN_WEIGHT_NORMAL = 400,
+ TWIN_WEIGHT_MEDIUM = 500,
+ TWIN_WEIGHT_SEMIBOLD = 600,
+ TWIN_WEIGHT_BOLD = 700,
+ TWIN_WEIGHT_ULTRABOLD = 800,
+ TWIN_WEIGHT_HEAVY = 900,
+ TWIN_WEIGHT_ULTRAHEAVY = 1000
+} twin_face_weight_t;
+
+/* CSS stretch */
+typedef enum {
+ TWIN_STRETCH_ULTRA_CONDENSED,
+ TWIN_STRETCH_EXTRA_CONDENSED,
+ TWIN_STRETCH_CONDENSED,
+ TWIN_STRETCH_SEMI_CONDENSED,
+ TWIN_STRETCH_NORMAL,
+ TWIN_STRETCH_SEMI_EXPANDED,
+ TWIN_STRETCH_EXPANDED,
+ TWIN_STRETCH_EXTRA_EXPANDED,
+ TWIN_STRETCH_ULTRA_EXPANDED
+} twin_face_stretch_t;
+
+typedef struct
+{
+ int value;
+ const char str[16];
+} FieldMap;
+
+static const FieldMap slant_map[] = {
+ { CAIRO_FONT_SLANT_NORMAL, "" },
+ { CAIRO_FONT_SLANT_NORMAL, "Roman" },
+ { CAIRO_FONT_SLANT_OBLIQUE, "Oblique" },
+ { CAIRO_FONT_SLANT_ITALIC, "Italic" }
+};
+
+static const FieldMap smallcaps_map[] = {
+ { FALSE, "" },
+ { TRUE, "Small-Caps" }
+};
+
+static const FieldMap weight_map[] = {
+ { TWIN_WEIGHT_THIN, "Thin" },
+ { TWIN_WEIGHT_ULTRALIGHT, "Ultra-Light" },
+ { TWIN_WEIGHT_ULTRALIGHT, "Extra-Light" },
+ { TWIN_WEIGHT_LIGHT, "Light" },
+ { TWIN_WEIGHT_BOOK, "Book" },
+ { TWIN_WEIGHT_NORMAL, "" },
+ { TWIN_WEIGHT_NORMAL, "Regular" },
+ { TWIN_WEIGHT_MEDIUM, "Medium" },
+ { TWIN_WEIGHT_SEMIBOLD, "Semi-Bold" },
+ { TWIN_WEIGHT_SEMIBOLD, "Demi-Bold" },
+ { TWIN_WEIGHT_BOLD, "Bold" },
+ { TWIN_WEIGHT_ULTRABOLD, "Ultra-Bold" },
+ { TWIN_WEIGHT_ULTRABOLD, "Extra-Bold" },
+ { TWIN_WEIGHT_HEAVY, "Heavy" },
+ { TWIN_WEIGHT_HEAVY, "Black" },
+ { TWIN_WEIGHT_ULTRAHEAVY, "Ultra-Heavy" },
+ { TWIN_WEIGHT_ULTRAHEAVY, "Extra-Heavy" },
+ { TWIN_WEIGHT_ULTRAHEAVY, "Ultra-Black" },
+ { TWIN_WEIGHT_ULTRAHEAVY, "Extra-Black" }
+};
+
+static const FieldMap stretch_map[] = {
+ { TWIN_STRETCH_ULTRA_CONDENSED, "Ultra-Condensed" },
+ { TWIN_STRETCH_EXTRA_CONDENSED, "Extra-Condensed" },
+ { TWIN_STRETCH_CONDENSED, "Condensed" },
+ { TWIN_STRETCH_SEMI_CONDENSED, "Semi-Condensed" },
+ { TWIN_STRETCH_NORMAL, "" },
+ { TWIN_STRETCH_SEMI_EXPANDED, "Semi-Expanded" },
+ { TWIN_STRETCH_EXPANDED, "Expanded" },
+ { TWIN_STRETCH_EXTRA_EXPANDED, "Extra-Expanded" },
+ { TWIN_STRETCH_ULTRA_EXPANDED, "Ultra-Expanded" }
+};
+
+static const FieldMap monospace_map[] = {
+ { FALSE, "" },
+ { TRUE, "Mono" },
+ { TRUE, "Monospace" }
+};
+
+
+typedef struct _twin_face_properties {
+ cairo_font_slant_t slant;
+ twin_face_weight_t weight;
+ twin_face_stretch_t stretch;
+
+ /* lets have some fun */
+ cairo_bool_t monospace;
+ cairo_bool_t smallcaps;
+} twin_face_properties_t;
+
+static cairo_bool_t
+field_matches (const char *s1,
+ const char *s2,
+ int len)
+{
+ int c1, c2;
+
+ while (len && *s1 && *s2)
+ {
+#define TOLOWER(c) \
+ (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+
+ c1 = TOLOWER (*s1);
+ c2 = TOLOWER (*s2);
+ if (c1 != c2) {
+ if (c1 == '-') {
+ s1++;
+ continue;
+ }
+ return FALSE;
+ }
+ s1++; s2++;
+ len--;
+ }
+
+ return len == 0 && *s1 == '\0';
+}
+
+static cairo_bool_t
+parse_int (const char *word,
+ size_t wordlen,
+ int *out)
+{
+ char *end;
+ long val = strtol (word, &end, 10);
+ int i = val;
+
+ if (end != word && (end == word + wordlen) && val >= 0 && val == i)
+ {
+ if (out)
+ *out = i;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static cairo_bool_t
+find_field (const char *what,
+ const FieldMap *map,
+ int n_elements,
+ const char *str,
+ int len,
+ int *val)
+{
+ int i;
+ cairo_bool_t had_prefix = FALSE;
+
+ if (what)
+ {
+ i = strlen (what);
+ if (len > i && 0 == strncmp (what, str, i) && str[i] == '=')
+ {
+ str += i + 1;
+ len -= i + 1;
+ had_prefix = TRUE;
+ }
+ }
+
+ for (i=0; i<n_elements; i++)
+ {
+ if (map[i].str[0] && field_matches (map[i].str, str, len))
+ {
+ if (val)
+ *val = map[i].value;
+ return TRUE;
+ }
+ }
+
+ if (!what || had_prefix)
+ return parse_int (str, len, val);
+
+ return FALSE;
+}
+
+static void
+parse_field (twin_face_properties_t *props,
+ const char *str,
+ int len)
+{
+ if (field_matches ("Normal", str, len))
+ return;
+
+#define FIELD(NAME) \
+ if (find_field (STRINGIFY (NAME), NAME##_map, ARRAY_LENGTH (NAME##_map), str, len, \
+ (int *)(void *)&props->NAME)) \
+ return; \
+
+ FIELD (weight);
+ FIELD (slant);
+ FIELD (stretch);
+ FIELD (smallcaps);
+ FIELD (monospace);
+
+#undef FIELD
+}
+
+static void
+face_props_parse (twin_face_properties_t *props,
+ const char *s)
+{
+ const char *start, *end;
+
+ for (start = end = s; *end; end++) {
+ if (*end != ' ' && *end != ':')
+ continue;
+
+ if (start < end)
+ parse_field (props, start, end - start);
+ start = end + 1;
+ }
+ if (start < end)
+ parse_field (props, start, end - start);
+}
+
+static cairo_status_t
+twin_font_face_set_properties_from_toy (cairo_font_face_t *twin_face,
+ cairo_toy_font_face_t *toy_face)
+{
+ cairo_status_t status;
+ twin_face_properties_t *props;
+
+ props = malloc (sizeof (twin_face_properties_t));
+ if (unlikely (props == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ props->stretch = TWIN_STRETCH_NORMAL;
+ props->monospace = FALSE;
+ props->smallcaps = FALSE;
+
+ props->slant = toy_face->slant;
+ props->weight = toy_face->weight == CAIRO_FONT_WEIGHT_NORMAL ?
+ TWIN_WEIGHT_NORMAL : TWIN_WEIGHT_BOLD;
+ face_props_parse (props, toy_face->family);
+
+ status = cairo_font_face_set_user_data (twin_face,
+ &twin_properties_key,
+ props, free);
+ if (unlikely (status))
+ goto FREE_PROPS;
+
+ return CAIRO_STATUS_SUCCESS;
+
+FREE_PROPS:
+ free (props);
+ return status;
+}
+
+
+/*
+ * Scaled properties
+ */
+
+typedef struct _twin_scaled_properties {
+ twin_face_properties_t *face_props;
+
+ cairo_bool_t snap; /* hint outlines */
+
+ double weight; /* unhinted pen width */
+ double penx, peny; /* hinted pen width */
+ double marginl, marginr; /* hinted side margins */
+
+ double stretch; /* stretch factor */
+} twin_scaled_properties_t;
+
+static void
+compute_hinting_scale (cairo_t *cr,
+ double x, double y,
+ double *scale, double *inv)
+{
+ cairo_user_to_device_distance (cr, &x, &y);
+ *scale = x == 0 ? y : y == 0 ? x :sqrt (x*x + y*y);
+ *inv = 1 / *scale;
+}
+
+static void
+compute_hinting_scales (cairo_t *cr,
+ double *x_scale, double *x_scale_inv,
+ double *y_scale, double *y_scale_inv)
+{
+ double x, y;
+
+ x = 1; y = 0;
+ compute_hinting_scale (cr, x, y, x_scale, x_scale_inv);
+
+ x = 0; y = 1;
+ compute_hinting_scale (cr, x, y, y_scale, y_scale_inv);
+}
+
+#define SNAPXI(p) (_cairo_round ((p) * x_scale) * x_scale_inv)
+#define SNAPYI(p) (_cairo_round ((p) * y_scale) * y_scale_inv)
+
+/* This controls the global font size */
+#define F(g) ((g) / 72.)
+
+static void
+twin_hint_pen_and_margins(cairo_t *cr,
+ double *penx, double *peny,
+ double *marginl, double *marginr)
+{
+ double x_scale, x_scale_inv;
+ double y_scale, y_scale_inv;
+ double margin;
+
+ compute_hinting_scales (cr,
+ &x_scale, &x_scale_inv,
+ &y_scale, &y_scale_inv);
+
+ *penx = SNAPXI (*penx);
+ if (*penx < x_scale_inv)
+ *penx = x_scale_inv;
+
+ *peny = SNAPYI (*peny);
+ if (*peny < y_scale_inv)
+ *peny = y_scale_inv;
+
+ margin = *marginl + *marginr;
+ *marginl = SNAPXI (*marginl);
+ if (*marginl < x_scale_inv)
+ *marginl = x_scale_inv;
+
+ *marginr = margin - *marginl;
+ if (*marginr < 0)
+ *marginr = 0;
+ *marginr = SNAPXI (*marginr);
+}
+
+static cairo_status_t
+twin_scaled_font_compute_properties (cairo_scaled_font_t *scaled_font,
+ cairo_t *cr)
+{
+ cairo_status_t status;
+ twin_scaled_properties_t *props;
+
+ props = malloc (sizeof (twin_scaled_properties_t));
+ if (unlikely (props == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+
+ props->face_props = cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
+ &twin_properties_key);
+
+ props->snap = scaled_font->options.hint_style > CAIRO_HINT_STYLE_NONE;
+
+ /* weight */
+ props->weight = props->face_props->weight * (F (4) / TWIN_WEIGHT_NORMAL);
+
+ /* pen & margins */
+ props->penx = props->peny = props->weight;
+ props->marginl = props->marginr = F (4);
+ if (scaled_font->options.hint_style > CAIRO_HINT_STYLE_SLIGHT)
+ twin_hint_pen_and_margins(cr,
+ &props->penx, &props->peny,
+ &props->marginl, &props->marginr);
+
+ /* stretch */
+ props->stretch = 1 + .1 * ((int) props->face_props->stretch - (int) TWIN_STRETCH_NORMAL);
+
+
+ /* Save it */
+ status = cairo_scaled_font_set_user_data (scaled_font,
+ &twin_properties_key,
+ props, free);
+ if (unlikely (status))
+ goto FREE_PROPS;
+
+ return CAIRO_STATUS_SUCCESS;
+
+FREE_PROPS:
+ free (props);
+ return status;
+}
+
+
+/*
+ * User-font implementation
+ */
+
+static cairo_status_t
+twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
+ cairo_t *cr,
+ cairo_font_extents_t *metrics)
+{
+ metrics->ascent = F (54);
+ metrics->descent = 1 - metrics->ascent;
+
+ return twin_scaled_font_compute_properties (scaled_font, cr);
+}
+
+#define TWIN_GLYPH_MAX_SNAP_X 4
+#define TWIN_GLYPH_MAX_SNAP_Y 7
+
+typedef struct {
+ int n_snap_x;
+ int8_t snap_x[TWIN_GLYPH_MAX_SNAP_X];
+ double snapped_x[TWIN_GLYPH_MAX_SNAP_X];
+ int n_snap_y;
+ int8_t snap_y[TWIN_GLYPH_MAX_SNAP_Y];
+ double snapped_y[TWIN_GLYPH_MAX_SNAP_Y];
+} twin_snap_info_t;
#define twin_glyph_left(g) ((g)[0])
#define twin_glyph_right(g) ((g)[1])
#define twin_glyph_ascent(g) ((g)[2])
#define twin_glyph_descent(g) ((g)[3])
#define twin_glyph_n_snap_x(g) ((g)[4])
#define twin_glyph_n_snap_y(g) ((g)[5])
#define twin_glyph_snap_x(g) (&g[6])
#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))
#define twin_glyph_draw(g) (twin_glyph_snap_y(g) + twin_glyph_n_snap_y(g))
-#define SNAPI(p) (p)
-#define SNAPH(p) (p)
+static void
+twin_compute_snap (cairo_t *cr,
+ twin_snap_info_t *info,
+ const signed char *b)
+{
+ int s, n;
+ const signed char *snap;
+ double x_scale, x_scale_inv;
+ double y_scale, y_scale_inv;
+
+ compute_hinting_scales (cr,
+ &x_scale, &x_scale_inv,
+ &y_scale, &y_scale_inv);
+
+ snap = twin_glyph_snap_x (b);
+ n = twin_glyph_n_snap_x (b);
+ info->n_snap_x = n;
+ assert (n <= TWIN_GLYPH_MAX_SNAP_X);
+ for (s = 0; s < n; s++) {
+ info->snap_x[s] = snap[s];
+ info->snapped_x[s] = SNAPXI (F (snap[s]));
+ }
+
+ snap = twin_glyph_snap_y (b);
+ n = twin_glyph_n_snap_y (b);
+ info->n_snap_y = n;
+ assert (n <= TWIN_GLYPH_MAX_SNAP_Y);
+ for (s = 0; s < n; s++) {
+ info->snap_y[s] = snap[s];
+ info->snapped_y[s] = SNAPYI (F (snap[s]));
+ }
+}
-#define FX(g) ((g) / 64.)
-#define FY(g) ((g) / 64.)
+static double
+twin_snap (int8_t v, int n, int8_t *snap, double *snapped)
+{
+ int s;
+
+ if (!n)
+ return F(v);
+
+ if (snap[0] == v)
+ return snapped[0];
+
+ for (s = 0; s < n - 1; s++)
+ {
+ if (snap[s+1] == v)
+ return snapped[s+1];
+ if (snap[s] <= v && v <= snap[s+1])
+ {
+ int before = snap[s];
+ int after = snap[s+1];
+ int dist = after - before;
+ double snap_before = snapped[s];
+ double snap_after = snapped[s+1];
+ double dist_before = v - before;
+ return snap_before + (snap_after - snap_before) * dist_before / dist;
+ }
+ }
+ return F(v);
+}
+
+#define SNAPX(p) twin_snap (p, info.n_snap_x, info.snap_x, info.snapped_x)
+#define SNAPY(p) twin_snap (p, info.n_snap_y, info.snap_y, info.snapped_y)
static cairo_status_t
-twin_scaled_font_init (cairo_scaled_font_t *scaled_font,
- cairo_t *cr,
- cairo_font_extents_t *metrics)
+twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
+ unsigned long glyph,
+ cairo_t *cr,
+ cairo_text_extents_t *metrics)
{
- metrics->ascent = FY (50);
- metrics->descent = FY (14);
- return CAIRO_STATUS_SUCCESS;
+ double x1, y1, x2, y2, x3, y3;
+ double marginl;
+ twin_scaled_properties_t *props;
+ twin_snap_info_t info;
+ const int8_t *b;
+ const int8_t *g;
+ int8_t w;
+ double gw;
+
+ props = cairo_scaled_font_get_user_data (scaled_font, &twin_properties_key);
+
+ /* Save glyph space, we need it when stroking */
+ cairo_save (cr);
+
+ /* center the pen */
+ cairo_translate (cr, props->penx * .5, -props->peny * .5);
+
+ /* small-caps */
+ if (props->face_props->smallcaps && glyph >= 'a' && glyph <= 'z') {
+ glyph += 'A' - 'a';
+ /* 28 and 42 are small and capital letter heights of the glyph data */
+ cairo_scale (cr, 1, 28. / 42);
+ }
+
+ /* slant */
+ if (props->face_props->slant != CAIRO_FONT_SLANT_NORMAL) {
+ cairo_matrix_t shear = { 1, 0, -.2, 1, 0, 0};
+ cairo_transform (cr, &shear);
+ }
+
+ b = _cairo_twin_outlines +
+ _cairo_twin_charmap[unlikely (glyph >= ARRAY_LENGTH (_cairo_twin_charmap)) ? 0 : glyph];
+ g = twin_glyph_draw(b);
+ w = twin_glyph_right(b);
+ gw = F(w);
+
+ marginl = props->marginl;
+
+ /* monospace */
+ if (props->face_props->monospace) {
+ double monow = F(24);
+ double extra = props->penx + props->marginl + props->marginr;
+ cairo_scale (cr, (monow + extra) / (gw + extra), 1);
+ gw = monow;
+
+ /* resnap margin for new transform */
+ {
+ double x, y, x_scale, x_scale_inv;
+ x = 1; y = 0;
+ compute_hinting_scale (cr, x, y, &x_scale, &x_scale_inv);
+ marginl = SNAPXI (marginl);
+ }
+ }
+
+ cairo_translate (cr, marginl, 0);
+
+ /* stretch */
+ cairo_scale (cr, props->stretch, 1);
+
+ if (props->snap)
+ twin_compute_snap (cr, &info, b);
+ else
+ info.n_snap_x = info.n_snap_y = 0;
+
+ /* advance width */
+ metrics->x_advance = gw * props->stretch + props->penx + props->marginl + props->marginr;
+
+ /* glyph shape */
+ for (;;) {
+ switch (*g++) {
+ case 'M':
+ cairo_close_path (cr);
+ /* fall through */
+ case 'm':
+ x1 = SNAPX(*g++);
+ y1 = SNAPY(*g++);
+ cairo_move_to (cr, x1, y1);
+ continue;
+ case 'L':
+ cairo_close_path (cr);
+ /* fall through */
+ case 'l':
+ x1 = SNAPX(*g++);
+ y1 = SNAPY(*g++);
+ cairo_line_to (cr, x1, y1);
+ continue;
+ case 'C':
+ cairo_close_path (cr);
+ /* fall through */
+ case 'c':
+ x1 = SNAPX(*g++);
+ y1 = SNAPY(*g++);
+ x2 = SNAPX(*g++);
+ y2 = SNAPY(*g++);
+ x3 = SNAPX(*g++);
+ y3 = SNAPY(*g++);
+ cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
+ continue;
+ case 'E':
+ cairo_close_path (cr);
+ /* fall through */
+ case 'e':
+ cairo_restore (cr); /* restore glyph space */
+ cairo_set_tolerance (cr, 0.01);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_line_width (cr, 1);
+ cairo_scale (cr, props->penx, props->peny);
+ cairo_stroke (cr);
+ break;
+ case 'X':
+ /* filler */
+ continue;
+ }
+ break;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
unsigned long unicode,
unsigned long *glyph)
{
/* We use an identity charmap. Which means we could live
* with no unicode_to_glyph method too. But we define this
* to map all unknown chars to a single unknown glyph to
* reduce pressure on cache. */
- if (unicode < ARRAY_LENGTH (_cairo_twin_charmap))
+ if (likely (unicode < ARRAY_LENGTH (_cairo_twin_charmap)))
*glyph = unicode;
else
*glyph = 0;
return CAIRO_STATUS_SUCCESS;
}
-#define SNAPX(p) _twin_snap (p, info.snap_x, info.n_snap_x)
-#define SNAPY(p) _twin_snap (p, info.snap_y, info.n_snap_y)
-static double
-_twin_snap (double v, int a, int b)
-{
- return v; /* XXX */
-}
-
-static cairo_status_t
-twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
- unsigned long glyph,
- cairo_t *cr,
- cairo_text_extents_t *metrics)
-{
- double x1, y1, x2, y2, x3, y3;
- const int8_t *b = _cairo_twin_outlines +
- _cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph];
- const int8_t *g = twin_glyph_draw(b);
-
- struct {
- cairo_bool_t snap;
- int snap_x;
- int snap_y;
- int n_snap_x;
- int n_snap_y;
- } info = {FALSE};
-
- cairo_set_line_width (cr, 0.06);
- cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
- cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+/*
+ * Face constructor
+ */
- for (;;) {
- switch (*g++) {
- case 'M':
- cairo_close_path (cr);
- /* fall through */
- case 'm':
- x1 = FX(*g++);
- y1 = FY(*g++);
- if (info.snap)
- {
- x1 = SNAPX (x1);
- y1 = SNAPY (y1);
- }
- cairo_move_to (cr, x1, y1);
- continue;
- case 'L':
- cairo_close_path (cr);
- /* fall through */
- case 'l':
- x1 = FX(*g++);
- y1 = FY(*g++);
- if (info.snap)
- {
- x1 = SNAPX (x1);
- y1 = SNAPY (y1);
- }
- cairo_line_to (cr, x1, y1);
- continue;
- case 'C':
- cairo_close_path (cr);
- /* fall through */
- case 'c':
- x1 = FX(*g++);
- y1 = FY(*g++);
- x2 = FX(*g++);
- y2 = FY(*g++);
- x3 = FX(*g++);
- y3 = FY(*g++);
- if (info.snap)
- {
- x1 = SNAPX (x1);
- y1 = SNAPY (y1);
- x2 = SNAPX (x2);
- y2 = SNAPY (y2);
- x3 = SNAPX (x3);
- y3 = SNAPY (y3);
- }
- cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
- continue;
- case 'E':
- cairo_close_path (cr);
- /* fall through */
- case 'e':
- cairo_stroke (cr);
- break;
- case 'X':
- /* filler */
- continue;
- }
- break;
- }
-
- metrics->x_advance = FX(twin_glyph_right(b)) + cairo_get_line_width (cr);
- metrics->x_advance += cairo_get_line_width (cr)/* XXX 2*x.margin */;
- if (info.snap)
- metrics->x_advance = SNAPI (SNAPX (metrics->x_advance));
-
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_font_face_t *
-_cairo_font_face_twin_create (cairo_font_slant_t slant,
- cairo_font_weight_t weight)
+cairo_status_t
+_cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t *toy_face,
+ cairo_font_face_t **font_face)
{
+ cairo_status_t status;
cairo_font_face_t *twin_font_face;
twin_font_face = cairo_user_font_face_create ();
cairo_user_font_face_set_init_func (twin_font_face, twin_scaled_font_init);
cairo_user_font_face_set_render_glyph_func (twin_font_face, twin_scaled_font_render_glyph);
cairo_user_font_face_set_unicode_to_glyph_func (twin_font_face, twin_scaled_font_unicode_to_glyph);
+ status = twin_font_face_set_properties_from_toy (twin_font_face, toy_face);
+ if (status) {
+ cairo_font_face_destroy (twin_font_face);
+ return status;
+ }
- return twin_font_face;
+ *font_face = twin_font_face;
+
+ return CAIRO_STATUS_SUCCESS;
}
--- a/gfx/cairo/cairo/src/cairo-font-face.c
+++ b/gfx/cairo/cairo/src/cairo-font-face.c
@@ -33,91 +33,26 @@
* California.
*
* Contributor(s):
* Carl D. Worth <cworth@cworth.org>
* Graydon Hoare <graydon@redhat.com>
* Owen Taylor <otaylor@redhat.com>
*/
-#define _BSD_SOURCE /* for strdup() */
#include "cairoint.h"
-static const cairo_font_face_backend_t _cairo_toy_font_face_backend;
-
/* #cairo_font_face_t */
-const cairo_toy_font_face_t _cairo_font_face_nil = {
- {
+const cairo_font_face_t _cairo_font_face_nil = {
{ 0 }, /* hash_entry */
CAIRO_STATUS_NO_MEMORY, /* status */
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
{ 0, 0, 0, NULL }, /* user_data */
- &_cairo_toy_font_face_backend
- },
- CAIRO_FONT_FAMILY_DEFAULT, /* family */
- TRUE, /* owns_family */
- CAIRO_FONT_SLANT_DEFAULT, /* slant */
- CAIRO_FONT_WEIGHT_DEFAULT /* weight */
-};
-
-static const cairo_toy_font_face_t _cairo_font_face_null_pointer = {
- {
- { 0 }, /* hash_entry */
- CAIRO_STATUS_NULL_POINTER, /* status */
- CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
- { 0, 0, 0, NULL }, /* user_data */
- &_cairo_toy_font_face_backend
- },
- CAIRO_FONT_FAMILY_DEFAULT, /* family */
- TRUE, /* owns_family */
- CAIRO_FONT_SLANT_DEFAULT, /* slant */
- CAIRO_FONT_WEIGHT_DEFAULT /* weight */
-};
-
-static const cairo_toy_font_face_t _cairo_font_face_invalid_string = {
- {
- { 0 }, /* hash_entry */
- CAIRO_STATUS_INVALID_STRING, /* status */
- CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
- { 0, 0, 0, NULL }, /* user_data */
- &_cairo_toy_font_face_backend
- },
- CAIRO_FONT_FAMILY_DEFAULT, /* family */
- TRUE, /* owns_family */
- CAIRO_FONT_SLANT_DEFAULT, /* slant */
- CAIRO_FONT_WEIGHT_DEFAULT /* weight */
-};
-
-static const cairo_toy_font_face_t _cairo_font_face_invalid_slant = {
- {
- { 0 }, /* hash_entry */
- CAIRO_STATUS_INVALID_SLANT, /* status */
- CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
- { 0, 0, 0, NULL }, /* user_data */
- &_cairo_toy_font_face_backend
- },
- CAIRO_FONT_FAMILY_DEFAULT, /* family */
- TRUE, /* owns_family */
- CAIRO_FONT_SLANT_DEFAULT, /* slant */
- CAIRO_FONT_WEIGHT_DEFAULT /* weight */
-};
-
-static const cairo_toy_font_face_t _cairo_font_face_invalid_weight = {
- {
- { 0 }, /* hash_entry */
- CAIRO_STATUS_INVALID_WEIGHT, /* status */
- CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
- { 0, 0, 0, NULL }, /* user_data */
- &_cairo_toy_font_face_backend
- },
- CAIRO_FONT_FAMILY_DEFAULT, /* family */
- TRUE, /* owns_family */
- CAIRO_FONT_SLANT_DEFAULT, /* slant */
- CAIRO_FONT_WEIGHT_DEFAULT /* weight */
+ NULL
};
cairo_status_t
_cairo_font_face_set_error (cairo_font_face_t *font_face,
cairo_status_t status)
{
if (status == CAIRO_STATUS_SUCCESS)
return status;
@@ -218,16 +153,19 @@ slim_hidden_def (cairo_font_face_destroy
*
* 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)
{
+ if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
+ return CAIRO_FONT_TYPE_TOY;
+
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.
@@ -309,426 +247,16 @@ cairo_font_face_set_user_data (cairo_fon
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return font_face->status;
return _cairo_user_data_array_set_data (&font_face->user_data,
key, user_data, destroy);
}
slim_hidden_def (cairo_font_face_set_user_data);
-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;
-
- assert (hash != 0);
- 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_error (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.
- *
- * If @family is the zero-length string "", the platform-specific default
- * family is assumed. The default family then can be queried using
- * cairo_toy_font_face_get_family().
- *
- * The cairo_select_font_face() function uses this to create font faces.
- * See that function for limitations of toy font faces.
- *
- * Return value: a newly created #cairo_font_face_t. Free with
- * cairo_font_face_destroy() when you are done using it.
- *
- * Since: 1.8
- **/
-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;
-
- if (family == NULL)
- return (cairo_font_face_t*) &_cairo_font_face_null_pointer;
-
- /* Make sure we've got valid UTF-8 for the family */
- status = _cairo_utf8_to_ucs4 (family, -1, NULL, NULL);
- if (status == CAIRO_STATUS_INVALID_STRING)
- return (cairo_font_face_t*) &_cairo_font_face_invalid_string;
- else if (status)
- return (cairo_font_face_t*) &_cairo_font_face_nil;
-
- switch (slant) {
- case CAIRO_FONT_SLANT_NORMAL:
- case CAIRO_FONT_SLANT_ITALIC:
- case CAIRO_FONT_SLANT_OBLIQUE:
- break;
- default:
- return (cairo_font_face_t*) &_cairo_font_face_invalid_slant;
- }
-
- switch (weight) {
- case CAIRO_FONT_WEIGHT_NORMAL:
- case CAIRO_FONT_WEIGHT_BOLD:
- break;
- default:
- return (cairo_font_face_t*) &_cairo_font_face_invalid_weight;
- }
-
- if (*family == '\0')
- family = CAIRO_FONT_FAMILY_DEFAULT;
-
- 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))
- {
- if (! font_face->base.status) {
- /* We increment the reference count here manually to avoid
- double-locking. */
- _cairo_reference_count_inc (&font_face->base.ref_count);
- _cairo_toy_font_face_hash_table_unlock ();
- return &font_face->base;
- }
-
- /* remove the bad font from the hash table */
- _cairo_hash_table_remove (hash_table, &key.base.hash_entry);
- font_face->base.hash_entry.hash = 0;
- }
-
- /* Otherwise create it and insert into hash table. */
- font_face = malloc (sizeof (cairo_toy_font_face_t));
- if (font_face == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- 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:
- _cairo_toy_font_face_fini (font_face);
- 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;
-}
-slim_hidden_def (cairo_toy_font_face_create);
-
-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 ||
- CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->base.ref_count))
- 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);
-
- if (font_face->base.hash_entry.hash != 0)
- _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_get_implementation (void *abstract_font_face,
- cairo_font_face_t **font_face_out)
-{
- cairo_toy_font_face_t *font_face = abstract_font_face;
- cairo_status_t status;
-
- if (font_face->base.status)
- return font_face->base.status;
-
- if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
- {
- const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
-
- if (backend->get_implementation == NULL) {
- *font_face_out = &font_face->base;
- return CAIRO_STATUS_SUCCESS;
- }
-
- status = backend->get_implementation (font_face,
- font_face_out);
-
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return _cairo_font_face_set_error (&font_face->base, status);
- }
-
- status = _cairo_user_scaled_font_backend.get_implementation (font_face,
- font_face_out);
-
- return _cairo_font_face_set_error (&font_face->base, status);
-}
-
-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;
- cairo_status_t status;
-
- if (font_face->base.status)
- return font_face->base.status;
-
- status = cairo_font_options_status ((cairo_font_options_t *) options);
- if (status)
- return status;
-
- if (CAIRO_SCALED_FONT_BACKEND_DEFAULT != &_cairo_user_scaled_font_backend)
- {
- const cairo_scaled_font_backend_t * backend = CAIRO_SCALED_FONT_BACKEND_DEFAULT;
-
- *scaled_font = NULL;
- status = backend->create_toy (font_face,
- font_matrix,
- ctm,
- options,
- scaled_font);
-
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return _cairo_font_face_set_error (&font_face->base, status);
-
- if (*scaled_font)
- cairo_scaled_font_destroy (*scaled_font);
- }
-
- status = _cairo_user_scaled_font_backend.create_toy (font_face,
- font_matrix,
- ctm,
- options,
- scaled_font);
-
- return _cairo_font_face_set_error (&font_face->base, status);
-}
-
-static cairo_bool_t
-_cairo_font_face_is_toy (cairo_font_face_t *font_face)
-{
- return font_face->backend == &_cairo_toy_font_face_backend;
-}
-
-/**
- * cairo_toy_font_face_get_family:
- * @font_face: A toy font face
- *
- * Gets the familly name of a toy font.
- *
- * Return value: The family name. This string is owned by the font face
- * and remains valid as long as the font face is alive (referenced).
- *
- * Since: 1.8
- **/
-const char *
-cairo_toy_font_face_get_family (cairo_font_face_t *font_face)
-{
- cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face;
- if (! _cairo_font_face_is_toy (font_face)) {
- if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
- return CAIRO_FONT_FAMILY_DEFAULT;
- }
- assert (toy_font_face->owns_family);
- return toy_font_face->family;
-}
-
-/**
- * cairo_toy_font_face_get_slant:
- * @font_face: A toy font face
- *
- * Gets the slant a toy font.
- *
- * Return value: The slant value
- *
- * Since: 1.8
- **/
-cairo_font_slant_t
-cairo_toy_font_face_get_slant (cairo_font_face_t *font_face)
-{
- cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face;
- if (! _cairo_font_face_is_toy (font_face)) {
- if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
- return CAIRO_FONT_SLANT_DEFAULT;
- }
- return toy_font_face->slant;
-}
-slim_hidden_def (cairo_toy_font_face_get_slant);
-
-/**
- * cairo_toy_font_face_get_weight:
- * @font_face: A toy font face
- *
- * Gets the weight a toy font.
- *
- * Return value: The weight value
- *
- * Since: 1.8
- **/
-cairo_font_weight_t
-cairo_toy_font_face_get_weight (cairo_font_face_t *font_face)
-{
- cairo_toy_font_face_t *toy_font_face = (cairo_toy_font_face_t *) font_face;
- if (! _cairo_font_face_is_toy (font_face)) {
- if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
- return CAIRO_FONT_WEIGHT_DEFAULT;
- }
- return toy_font_face->weight;
-}
-slim_hidden_def (cairo_toy_font_face_get_weight);
-
-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_get_implementation,
- _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)
{
CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1);
unscaled_font->backend = backend;
}
@@ -755,22 +283,8 @@ void
if (! _cairo_reference_count_dec_and_test (&unscaled_font->ref_count))
return;
unscaled_font->backend->destroy (unscaled_font);
free (unscaled_font);
}
-
-void
-_cairo_font_face_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-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -40,17 +40,17 @@
#define _BSD_SOURCE /* for strdup() */
#include "cairoint.h"
#include "cairo-ft-private.h"
#include <float.h>
-#ifndef CAIRO_DISABLE_FONTCONFIG
+#if CAIRO_HAS_FC_FONT
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
#endif
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_IMAGE_H
@@ -118,42 +118,56 @@ struct _cairo_ft_unscaled_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);
-#ifndef CAIRO_DISABLE_FONTCONFIG
-static cairo_status_t
-_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
- FcPattern *pattern);
-#endif
-
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;
+
+#if CAIRO_HAS_FC_FONT
+ FcPattern *pattern; /* if pattern is set, the above fields will be NULL */
+#endif
};
static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
+#if CAIRO_HAS_FC_FONT
+static cairo_status_t
+_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
+ FcPattern *pattern);
+
+static cairo_status_t
+_cairo_ft_resolve_pattern (FcPattern *pattern,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_ft_unscaled_font_t **unscaled,
+ cairo_ft_options_t *ft_options);
+
+#endif
+
/*
* 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).
*/
@@ -174,109 +188,99 @@ static void
FT_Done_Face (unscaled->face);
unscaled->face = NULL;
unscaled->have_scale = FALSE;
font_map->num_open_faces--;
}
}
-static void
+static cairo_status_t
_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) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- goto FAIL;
- }
+ if (unlikely (font_map == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
font_map->hash_table =
_cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);
- if (font_map->hash_table == NULL)
+ if (unlikely (font_map->hash_table == NULL))
goto FAIL;
- if (FT_Init_FreeType (&font_map->ft_library))
+ if (unlikely (FT_Init_FreeType (&font_map->ft_library)))
goto FAIL;
font_map->num_open_faces = 0;
cairo_ft_unscaled_font_map = font_map;
- return;
+ return CAIRO_STATUS_SUCCESS;
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;
+ if (font_map->hash_table)
+ _cairo_hash_table_destroy (font_map->hash_table);
+ free (font_map);
+
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+}
+
+
+static void
+_cairo_ft_unscaled_font_map_pluck_entry (void *entry, void *closure)
+{
+ cairo_ft_unscaled_font_t *unscaled = entry;
+ cairo_ft_unscaled_font_map_t *font_map = closure;
+
+ _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);
}
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);
- }
-
+ font_map = cairo_ft_unscaled_font_map;
+ cairo_ft_unscaled_font_map = NULL;
+ CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
+
+ if (font_map != NULL) {
+ _cairo_hash_table_foreach (font_map->hash_table,
+ _cairo_ft_unscaled_font_map_pluck_entry,
+ font_map);
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) {
+ if (unlikely (cairo_ft_unscaled_font_map == NULL)) {
+ if (unlikely (_cairo_ft_unscaled_font_map_create ())) {
CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return NULL;
}
}
return cairo_ft_unscaled_font_map;
}
static void
@@ -343,18 +347,19 @@ static cairo_status_t
_cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, face);
} else {
char *filename_copy;
unscaled->from_face = FALSE;
unscaled->face = NULL;
filename_copy = strdup (filename);
- if (filename_copy == NULL)
+ if (unlikely (filename_copy == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
_cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL);
}
unscaled->have_scale = FALSE;
CAIRO_MUTEX_INIT (unscaled->mutex);
unscaled->lock_count = 0;
unscaled->faces = NULL;
@@ -419,83 +424,83 @@ static cairo_ft_unscaled_font_t *
int id,
FT_Face font_face)
{
cairo_ft_unscaled_font_t key, *unscaled;
cairo_ft_unscaled_font_map_t *font_map;
cairo_status_t status;
font_map = _cairo_ft_unscaled_font_map_lock ();
- if (font_map == NULL)
+ if (unlikely (font_map == NULL))
goto UNWIND;
_cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face);
/* 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))
- {
+ unscaled = _cairo_hash_table_lookup (font_map->hash_table,
+ &key.base.hash_entry);
+ if (unscaled != NULL) {
_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) {
+ if (unlikely (unscaled == NULL)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
goto UNWIND_FONT_MAP_LOCK;
}
status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face);
- if (status)
+ if (unlikely (status))
goto UNWIND_UNSCALED_MALLOC;
+ assert (unscaled->base.hash_entry.hash == key.base.hash_entry.hash);
status = _cairo_hash_table_insert (font_map->hash_table,
&unscaled->base.hash_entry);
- if (status)
+ if (unlikely (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;
}
-#ifndef CAIRO_DISABLE_FONTCONFIG
+
+#if CAIRO_HAS_FC_FONT
static cairo_ft_unscaled_font_t *
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
{
FT_Face font_face = NULL;
char *filename = NULL;
int id = 0;
- if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) != FcResultMatch) {
- FcChar8 *fc_filename = NULL;
-
- 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;
+ if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) == FcResultMatch)
+ goto DONE;
+
+ if (FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &filename) == FcResultMatch) {
+ /* If FC_INDEX is not set, we just use 0 */
+ FcPatternGetInteger (pattern, FC_INDEX, 0, &id);
+ goto DONE;
}
+ return NULL;
+
+DONE:
return _cairo_ft_unscaled_font_create_internal (font_face != NULL, filename, id, font_face);
-
-UNWIND:
- return NULL;
}
#endif
static cairo_ft_unscaled_font_t *
_cairo_ft_unscaled_font_create_from_face (FT_Face face)
{
return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face);
}
@@ -508,16 +513,22 @@ static void
if (unscaled == NULL)
return;
font_map = _cairo_ft_unscaled_font_map_lock ();
/* All created objects must have been mapped in the font map. */
assert (font_map != NULL);
+ if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled->base.ref_count)) {
+ /* somebody recreated the font whilst we waited for the lock */
+ _cairo_ft_unscaled_font_map_unlock ();
+ return;
+ }
+
_cairo_hash_table_remove (font_map->hash_table,
&unscaled->base.hash_entry);
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)
@@ -528,22 +539,21 @@ static void
unscaled->face = NULL;
_cairo_ft_unscaled_font_map_unlock ();
_cairo_ft_unscaled_font_fini (unscaled);
}
static cairo_bool_t
-_has_unlocked_face (void *entry)
+_has_unlocked_face (const void *entry)
{
- cairo_ft_unscaled_font_t *unscaled = entry;
-
- return (unscaled->lock_count == 0 &&
- unscaled->face && !unscaled->from_face);
+ const cairo_ft_unscaled_font_t *unscaled = entry;
+
+ return (!unscaled->from_face && 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.
*/
@@ -626,17 +636,17 @@ static cairo_status_t
* chooses hints, as well as selecting different bitmaps in
* hand-rendered fonts. We also copy the normalized matrix to
* freetype's transformation.
*/
status = _cairo_matrix_compute_basis_scale_factors (scale,
&x_scale, &y_scale,
1);
- if (status)
+ if (unlikely (status))
return status;
/* FreeType docs say this about x_scale and y_scale:
* "A character width or height smaller than 1pt is set to 1pt;"
* So, we cap them from below at 1.0 and let the FT transform
* take care of sub-1.0 scaling. */
if (x_scale < 1.0)
x_scale = 1.0;
@@ -676,17 +686,17 @@ static cairo_status_t
scale->xy == unscaled->current_scale.xy &&
scale->yy == unscaled->current_scale.yy)
return CAIRO_STATUS_SUCCESS;
unscaled->have_scale = TRUE;
unscaled->current_scale = *scale;
status = _compute_transform (&sf, scale);
- if (status)
+ if (unlikely (status))
return status;
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]);
@@ -881,17 +891,17 @@ 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 (stride_rgba, height);
- if (data_rgba == NULL) {
+ if (unlikely (data_rgba == NULL)) {
if (own_buffer)
free (bitmap->buffer);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
os = 1;
switch (font_options->subpixel_order) {
case CAIRO_SUBPIXEL_ORDER_VRGB:
@@ -1080,28 +1090,28 @@ static cairo_status_t
bitmap.num_grays = 256;
stride = (width * hmul + 3) & -4;
}
bitmap.pitch = stride;
bitmap.width = width * hmul;
bitmap.rows = height * vmul;
bitmap.buffer = calloc (stride, bitmap.rows);
- if (bitmap.buffer == NULL)
+ if (unlikely (bitmap.buffer == NULL))
return _cairo_error (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);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
- if (status)
+ if (unlikely (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. Moreover, device
* offsets are position of glyph origin relative to top left while xMin
* and yMax are offsets of top left relative to origin. Another negation.
@@ -1132,17 +1142,17 @@ static cairo_status_t
*/
error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
/* XXX ignoring all other errors for now. They are not fatal, typically
* just a glyph-not-found. */
if (error == FT_Err_Out_Of_Memory)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
- if (status)
+ if (unlikely (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. Moreover, device
* offsets are position of glyph origin relative to top left while
* bitmap_left and bitmap_top are offsets of top left relative to origin.
* Another negation.
@@ -1219,32 +1229,32 @@ static cairo_status_t
/* 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)
+ if (unlikely (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)
+ if (unlikely (image->status))
return image->status;
/* Initialize it to empty
*/
status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
0, 0,
width, height);
- if (status) {
+ if (unlikely (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);
@@ -1252,17 +1262,17 @@ static cairo_status_t
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) {
+ if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
}
/* Now update the cache entry for the new bitmap, recomputing
* the origin based on the final transform.
*/
cairo_matrix_transform_point (&original_to_transformed,
@@ -1288,19 +1298,19 @@ static const cairo_unscaled_font_backend
/* #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;
-
-#ifndef CAIRO_DISABLE_FONTCONFIG
+static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
+
+#if CAIRO_HAS_FC_FONT
/* 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;
@@ -1426,17 +1436,17 @@ static void
FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
embolden = FcFalse;
if (embolden)
ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
*ret = ft_options;
}
-#endif /* CAIRO_DISABLE_FONTCONFIG */
+#endif
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;
@@ -1517,47 +1527,47 @@ static cairo_status_t
{
cairo_ft_scaled_font_t *scaled_font;
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)
+ if (unlikely (face == NULL)) /* backend error */
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
scaled_font = malloc (sizeof(cairo_ft_scaled_font_t));
- if (scaled_font == NULL) {
+ if (unlikely (scaled_font == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FAIL;
}
_cairo_unscaled_font_reference (&unscaled->base);
scaled_font->unscaled = unscaled;
_cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
_cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
status = _cairo_scaled_font_init (&scaled_font->base,
font_face,
font_matrix, ctm, options,
&_cairo_ft_scaled_font_backend);
- if (status) {
- _cairo_unscaled_font_destroy (&unscaled->base);
- free (scaled_font);
- goto FAIL;
- }
+ if (unlikely (status))
+ goto CLEANUP_SCALED_FONT;
status = _cairo_ft_unscaled_font_set_scale (unscaled,
&scaled_font->base.scale);
- if (status) {
+ if (unlikely (status)) {
+ /* This can only fail if we encounter an error with the underlying
+ * font, so propagate the error back to the font-face. */
+ _cairo_ft_unscaled_font_unlock_face (unscaled);
_cairo_unscaled_font_destroy (&unscaled->base);
free (scaled_font);
- goto FAIL;
+ return status;
}
metrics = &face->size->metrics;
/*
* Get to unscaled metrics so that the upper level can get back to
* user space
@@ -1601,150 +1611,39 @@ static cairo_status_t
fs_metrics.max_y_advance = 0;
} else {
fs_metrics.max_x_advance = 0;
fs_metrics.max_y_advance = face->max_advance_height / scale;
}
}
status = _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
+ if (unlikely (status))
+ goto CLEANUP_SCALED_FONT;
+
+ _cairo_ft_unscaled_font_unlock_face (unscaled);
*font_out = &scaled_font->base;
-
- FAIL:
+ return CAIRO_STATUS_SUCCESS;
+
+ CLEANUP_SCALED_FONT:
+ _cairo_unscaled_font_destroy (&unscaled->base);
+ free (scaled_font);
+ FAIL:
_cairo_ft_unscaled_font_unlock_face (unscaled);
-
- return status;
+ *font_out = _cairo_scaled_font_create_in_error (status);
+ return CAIRO_STATUS_SUCCESS; /* non-backend error */
}
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)
-{
-#ifndef CAIRO_DISABLE_FONTCONFIG
- FcPattern *pattern, *resolved;
- cairo_ft_unscaled_font_t *unscaled;
- FcResult result;
- int fcslant;
- int fcweight;
- cairo_matrix_t scale;
- cairo_status_t status;
- cairo_ft_font_transform_t sf;
- cairo_ft_options_t ft_options;
-
- cairo_matrix_multiply (&scale, font_matrix, ctm);
- status = _compute_transform (&sf, &scale);
- if (status)
- return status;
-
- pattern = FcPatternCreate ();
- if (!pattern)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- if (!FcPatternAddString (pattern,
- FC_FAMILY, (unsigned char *) toy_face->family))
- {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FREE_PATTERN;
- }
-
- 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 (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FREE_PATTERN;
- }
-
- 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;
- }
-
- if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FREE_PATTERN;
- }
-
- if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FREE_PATTERN;
- }
-
- if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FREE_PATTERN;
- }
-
- status = _cairo_ft_font_options_substitute (font_options, pattern);
- if (status)
- goto FREE_PATTERN;
-
- FcDefaultSubstitute (pattern);
-
- resolved = FcFontMatch (NULL, pattern, &result);
- if (!resolved) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FREE_PATTERN;
- }
-
- unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved);
- if (!unscaled) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FREE_RESOLVED;
- }
-
- _get_pattern_ft_options (resolved, &ft_options);
-
- status = _cairo_ft_scaled_font_create (unscaled,
- &toy_face->base,
- font_matrix, ctm,
- font_options, ft_options,
- font);
-
- _cairo_unscaled_font_destroy (&unscaled->base);
-
- FREE_RESOLVED:
- FcPatternDestroy (resolved);
-
- FREE_PATTERN:
- FcPatternDestroy (pattern);
-
- return status;
-#else
- return CAIRO_INT_STATUS_UNSUPPORTED;
-#endif /* CAIRO_DISABLE_FONTCONFIG */
-}
-
static void
_cairo_ft_scaled_font_fini (void *abstract_font)
{
cairo_ft_scaled_font_t *scaled_font = abstract_font;
if (scaled_font == NULL)
return;
@@ -1876,17 +1775,17 @@ static cairo_status_t
/* 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);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
status = _cairo_path_fixed_close_path (path);
- if (status) {
+ if (unlikely (status)) {
_cairo_path_fixed_destroy (path);
return status;
}
*pathp = path;
return CAIRO_STATUS_SUCCESS;
}
@@ -1931,17 +1830,17 @@ static cairo_int_status_t
cairo_status_t status;
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
&scaled_font->base.scale);
- if (status)
+ if (unlikely (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;
@@ -2079,24 +1978,26 @@ 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 (likely (status == CAIRO_STATUS_SUCCESS) &&
+ unscaled->have_shape)
+ {
status = _transform_glyph_bitmap (&unscaled->current_shape,
&surface);
- if (status)
+ if (unlikely (status))
cairo_surface_destroy (&surface->base);
}
}
- if (status)
+ if (unlikely (status))
goto FAIL;
_cairo_scaled_glyph_set_surface (scaled_glyph,
&scaled_font->base,
surface);
}
if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
@@ -2128,17 +2029,17 @@ static cairo_int_status_t
}
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)
+ if (unlikely (status))
goto FAIL;
_cairo_scaled_glyph_set_path (scaled_glyph,
&scaled_font->base,
path);
}
FAIL:
_cairo_ft_unscaled_font_unlock_face (unscaled);
@@ -2154,21 +2055,22 @@ static unsigned long
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;
-#ifdef CAIRO_DISABLE_FONTCONFIG
- index = FT_Get_Char_Index (face, ucs4);
+#if CAIRO_HAS_FC_FONT
+ index = FcFreeTypeCharIndex (face, ucs4);
#else
- index = FcFreeTypeCharIndex (face, ucs4);
+ index = FT_Get_Char_Index (face, ucs4);
#endif
+
_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,
@@ -2223,31 +2125,98 @@ static cairo_int_status_t
}
}
_cairo_ft_unscaled_font_unlock_face (unscaled);
return CAIRO_STATUS_SUCCESS;
}
-const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
+static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
CAIRO_FONT_TYPE_FT,
- NULL,
- _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_index_to_ucs4
};
/* #cairo_ft_font_face_t */
+#if CAIRO_HAS_FC_FONT
+static cairo_status_t
+_cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
+ cairo_font_face_t **out);
+
+static cairo_status_t
+_cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
+ cairo_font_face_t **font_face)
+{
+ FcPattern *pattern;
+ int fcslant;
+ int fcweight;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ pattern = FcPatternCreate ();
+ if (!pattern)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ if (!FcPatternAddString (pattern,
+ FC_FAMILY, (unsigned char *) toy_face->family))
+ {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FREE_PATTERN;
+ }
+
+ 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 (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FREE_PATTERN;
+ }
+
+ 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;
+ }
+
+ if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FREE_PATTERN;
+ }
+
+ status = _cairo_ft_font_face_create_for_pattern (pattern, font_face);
+
+ FREE_PATTERN:
+ FcPatternDestroy (pattern);
+
+ return status;
+}
+#endif
+
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;
@@ -2294,58 +2263,118 @@ static void
}
last_face = tmp_face;
}
_cairo_unscaled_font_destroy (&font_face->unscaled->base);
font_face->unscaled = NULL;
}
+
+#if CAIRO_HAS_FC_FONT
+ if (font_face->pattern)
+ FcPatternDestroy (font_face->pattern);
+#endif
}
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;
+ cairo_ft_font_face_t *font_face = abstract_face;
+ cairo_ft_unscaled_font_t *unscaled = NULL;
+ 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.
- *
- * XXX two points about the above comment:
- * 1. I don't see how the comment is relevant here,
- * 2. What if the face is coming from FC_FT_FACE of a pattern?
+ */
+
+#if CAIRO_HAS_FC_FONT
+ /* If we have an unresolved pattern, resolve it and create
+ * unscaled font. Otherwise, use the ones stored in font_face.
*/
-
- ft_options = font_face->ft_options;
-
- return _cairo_ft_scaled_font_create (font_face->unscaled,
+ if (font_face->pattern) {
+ cairo_status_t status;
+
+ status = _cairo_ft_resolve_pattern (font_face->pattern,
+ font_matrix,
+ ctm,
+ options,
+ &unscaled,
+ &ft_options);
+ if (unlikely (status)) {
+ /* XXX It is possible for a failure to generate the unscaled font
+ * here could indicate that the font_face itself is broken - for
+ * which we should propagate the error.
+ */
+ *scaled_font = _cairo_scaled_font_create_in_error (status);
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ } else
+#endif
+ {
+ unscaled = font_face->unscaled;
+ ft_options = font_face->ft_options;
+ }
+
+ return _cairo_ft_scaled_font_create (unscaled,
&font_face->base,
font_matrix, ctm,
options, ft_options,
scaled_font);
}
-static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
+const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
CAIRO_FONT_TYPE_FT,
+#if CAIRO_HAS_FC_FONT
+ _cairo_ft_font_face_create_for_toy,
+#else
+ NULL,
+#endif
_cairo_ft_font_face_destroy,
- NULL, /* direct implementation */
_cairo_ft_font_face_scaled_font_create
};
+#if CAIRO_HAS_FC_FONT
+static cairo_status_t
+_cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
+ cairo_font_face_t **out)
+{
+ cairo_ft_font_face_t *font_face;
+
+ font_face = malloc (sizeof (cairo_ft_font_face_t));
+ if (unlikely (font_face == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ font_face->unscaled = NULL;
+ font_face->next = NULL;
+
+ font_face->pattern = FcPatternDuplicate (pattern);
+ if (unlikely (pattern == NULL)) {
+ free (font_face);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
+
+ *out = &font_face->base;
+ return CAIRO_STATUS_SUCCESS;
+}
+#endif
+
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;
@@ -2362,37 +2391,41 @@ static cairo_font_face_t *
/* The font_face has been left in an error state, abandon it. */
*prev_font_face = font_face->next;
break;
}
}
/* No match found, create a new one */
font_face = malloc (sizeof (cairo_ft_font_face_t));
- if (!font_face) {
+ if (unlikely (!font_face)) {
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_font_face_t *)&_cairo_font_face_nil;
}
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;
+#if CAIRO_HAS_FC_FONT
+ font_face->pattern = NULL;
+#endif
+
_cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
return &font_face->base;
}
-#ifndef CAIRO_DISABLE_FONTCONFIG
/* implement the platform-specific interface */
+#if CAIRO_HAS_FC_FONT
static cairo_status_t
_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
FcPattern *pattern)
{
FcValue v;
if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
{
@@ -2500,43 +2533,109 @@ cairo_ft_font_options_substitute (const
FcPattern *pattern)
{
if (cairo_font_options_status ((cairo_font_options_t *) options))
return;
_cairo_ft_font_options_substitute (options, pattern);
}
+static cairo_status_t
+_cairo_ft_resolve_pattern (FcPattern *pattern,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *font_options,
+ cairo_ft_unscaled_font_t **unscaled,
+ cairo_ft_options_t *ft_options)
+{
+ cairo_status_t status;
+
+ cairo_matrix_t scale;
+ FcPattern *resolved;
+ cairo_ft_font_transform_t sf;
+ FcResult result;
+
+ scale = *ctm;
+ scale.x0 = scale.y0 = 0;
+ cairo_matrix_multiply (&scale,
+ font_matrix,
+ &scale);
+
+ status = _compute_transform (&sf, &scale);
+ if (status)
+ return status;
+
+ pattern = FcPatternDuplicate (pattern);
+
+ if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FREE_PATTERN;
+ }
+
+ if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FREE_PATTERN;
+ }
+
+ status = _cairo_ft_font_options_substitute (font_options, pattern);
+ if (status)
+ goto FREE_PATTERN;
+
+ FcDefaultSubstitute (pattern);
+
+ resolved = FcFontMatch (NULL, pattern, &result);
+ if (!resolved) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FREE_PATTERN;
+ }
+
+ *unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved);
+ if (!*unscaled) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FREE_RESOLVED;
+ }
+
+ _get_pattern_ft_options (resolved, ft_options);
+
+FREE_RESOLVED:
+ FcPatternDestroy (resolved);
+
+FREE_PATTERN:
+ FcPatternDestroy (pattern);
+
+ return status;
+}
+
/**
* 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.
+ * @pattern: A fontconfig pattern. Cairo makes a copy of the pattern
+ * if it needs to. You are free to modify or free @pattern after this call.
*
* 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_scaled_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().
*
* The pattern's FC_FT_FACE element is inspected first and if that is set,
* that will be the FreeType font face associated with the returned cairo
- * font face. Otherwise the FC_FILE and FC_INDEX elements of @pattern are
- * used to load a font face from file.
+ * font face. Otherwise the FC_FILE element is checked. If it's set,
+ * that and the value of the FC_INDEX element (defaults to zero) of @pattern
+ * are used to load a font face from file.
+ *
+ * If both steps from the previous paragraph fails, @pattern will be passed
+ * to FcConfigSubstitute, FcDefaultSubstitute, and finally FcFontMatch,
+ * and the resulting font pattern is used.
*
* If the FC_FT_FACE element of @pattern is set, the user is responsible
* for making sure that the referenced FT_Face remains valid for the life
* time of the returned #cairo_font_face_t. See
* cairo_ft_font_face_create_for_ft_face() for an exmaple of how to couple
* the life time of the FT_Face to that of the cairo font-face.
*
* Return value: a newly created #cairo_font_face_t. Free with
@@ -2545,28 +2644,35 @@ cairo_ft_font_options_substitute (const
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_throw (CAIRO_STATUS_NO_MEMORY);
- return (cairo_font_face_t *)&_cairo_font_face_nil;
+ if (unlikely (unscaled == NULL)) {
+ cairo_status_t status;
+ /* Store the pattern. We will resolve it and create unscaled
+ * font when creating scaled fonts */
+ status = _cairo_ft_font_face_create_for_pattern (pattern,
+ &font_face);
+ if (unlikely (status))
+ return (cairo_font_face_t *) &_cairo_font_face_nil;
+
+ return font_face;
}
_get_pattern_ft_options (pattern, &ft_options);
font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
_cairo_unscaled_font_destroy (&unscaled->base);
return font_face;
}
-#endif /* CAIRO_DISABLE_FONTCONFIG */
+#endif
/**
* 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
@@ -2613,17 +2719,17 @@ 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) {
+ if (unlikely (unscaled == NULL)) {
_cairo_error_throw (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);
@@ -2649,17 +2755,17 @@ cairo_ft_font_face_create_for_ft_face (F
* kept of the number of times cairo_ft_scaled_font_lock_face() is
* called. cairo_ft_scaled_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
+ * code that acquires an FT_Face object with this call must add its
* 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.
**/
@@ -2674,24 +2780,24 @@ cairo_ft_scaled_font_lock_face (cairo_sc
_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
return NULL;
}
if (scaled_font->base.status)
return NULL;
face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
- if (face == NULL) {
+ if (unlikely (face == NULL)) {
status = _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) {
+ if (unlikely (status)) {
_cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
status = _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
@@ -2755,13 +2861,25 @@ cairo_bool_t
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;
}
+unsigned int
+_cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font)
+{
+ cairo_ft_scaled_font_t *ft_scaled_font;
+
+ if (! _cairo_scaled_font_is_ft (scaled_font))
+ return 0;
+
+ ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
+ return ft_scaled_font->ft_options.load_flags;
+}
+
void
_cairo_ft_font_reset_static_data (void)
{
_cairo_ft_unscaled_font_map_destroy ();
}
--- a/gfx/cairo/cairo/src/cairo-ft-private.h
+++ b/gfx/cairo/cairo/src/cairo-ft-private.h
@@ -59,12 +59,15 @@ cairo_private FT_Face
_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled);
cairo_private void
_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);
cairo_private cairo_bool_t
_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font);
+cairo_private unsigned int
+_cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font);
+
CAIRO_END_DECLS
#endif /* CAIRO_HAS_FT_FONT */
#endif /* CAIRO_FT_PRIVATE_H */
--- a/gfx/cairo/cairo/src/cairo-ft.h
+++ b/gfx/cairo/cairo/src/cairo-ft.h
@@ -38,42 +38,45 @@
#define CAIRO_FT_H
#include "cairo.h"
#if CAIRO_HAS_FT_FONT
/* Fontconfig/Freetype platform-specific font interface */
-#ifndef CAIRO_DISABLE_FONTCONFIG
-#include <fontconfig/fontconfig.h>
-#endif
#include <ft2build.h>
#include FT_FREETYPE_H
-CAIRO_BEGIN_DECLS
+#if CAIRO_HAS_FC_FONT
+#include <fontconfig/fontconfig.h>
+#endif
-#ifndef CAIRO_DISABLE_FONTCONFIG
-cairo_public cairo_font_face_t *
-cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
-
-cairo_public void
-cairo_ft_font_options_substitute (const cairo_font_options_t *options,
- FcPattern *pattern);
-#endif
+CAIRO_BEGIN_DECLS
cairo_public cairo_font_face_t *
cairo_ft_font_face_create_for_ft_face (FT_Face face,
int load_flags);
cairo_public FT_Face
cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font);
cairo_public void
cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *scaled_font);
+#if CAIRO_HAS_FC_FONT
+
+cairo_public cairo_font_face_t *
+cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
+
+cairo_public void
+cairo_ft_font_options_substitute (const cairo_font_options_t *options,
+ FcPattern *pattern);
+
+#endif
+
CAIRO_END_DECLS
#else /* CAIRO_HAS_FT_FONT */
# error Cairo was not compiled with support for the freetype font backend
#endif /* CAIRO_HAS_FT_FONT */
#endif /* CAIRO_FT_H */
--- a/gfx/cairo/cairo/src/cairo-glitz-surface.c
+++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c
@@ -28,32 +28,32 @@
#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;
- cairo_region_t clip;
+
+ cairo_bool_t has_clip;
+ glitz_box_t *clip_boxes;
+ int num_clip_boxes;
} 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);
- _cairo_region_fini (&surface->clip);
- }
+ if (surface->clip_boxes)
+ free (surface->clip_boxes);
glitz_surface_destroy (surface->surface);
return CAIRO_STATUS_SUCCESS;
}
static glitz_format_name_t
_glitz_format_from_content (cairo_content_t content)
@@ -84,357 +84,202 @@ static cairo_surface_t *
glitz_format_t *gformat;
drawable = glitz_surface_get_drawable (src->surface);
gformat =
glitz_find_standard_format (drawable,
_glitz_format_from_content (content));
if (!gformat)
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+ return NULL;
surface = glitz_surface_create (drawable, gformat,
width <= 0 ? 1 : width,
height <= 0 ? 1 : height,
0, NULL);
if (surface == NULL)
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
crsurface = cairo_glitz_surface_create (surface);
glitz_surface_destroy (surface);
return crsurface;
}
-static cairo_bool_t
-_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format)
+static cairo_status_t
+_cairo_glitz_get_boxes_from_region (cairo_region_t *region,
+ glitz_box_t **boxes,
+ int *nboxes)
{
- switch (masks->bpp) {
- case 32:
- if (masks->alpha_mask == 0xff000000 &&
- masks->red_mask == 0x00ff0000 &&
- masks->green_mask == 0x0000ff00 &&
- masks->blue_mask == 0x000000ff)
- {
- *format = CAIRO_FORMAT_ARGB32;
- return TRUE;
- }
- if (masks->alpha_mask == 0x00000000 &&
- masks->red_mask == 0x00ff0000 &&
- masks->green_mask == 0x0000ff00 &&
- masks->blue_mask == 0x000000ff)
- {
- *format = CAIRO_FORMAT_RGB24;
- return TRUE;
- }
- break;
- case 8:
- if (masks->alpha_mask == 0xff)
- {
- *format = CAIRO_FORMAT_A8;
- return TRUE;
- }
- break;
- case 1:
- if (masks->alpha_mask == 0x1)
- {
- *format = CAIRO_FORMAT_A1;
- return TRUE;
- }
- break;
- }
- return FALSE;
-}
+ pixman_box32_t *pboxes;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
-static cairo_status_t
-_cairo_glitz_get_boxes_from_region (cairo_region_t *region, glitz_box_t **boxes, int *nboxes)
-{
- cairo_box_int_t *cboxes;
- cairo_status_t status;
int n, i;
- status = _cairo_region_get_boxes (region, &n, &cboxes);
- if (status)
- return status;
-
+ n = 0;
+ pboxes = pixman_region32_rectangles (®ion->rgn, &n);
if (n == 0) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto done;
+ *nboxes = 0;
+ return CAIRO_STATUS_SUCCESS;
}
- *boxes = _cairo_malloc_ab (n, sizeof(glitz_box_t));
- if (*boxes == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto done;
+ if (n > *nboxes) {
+ *boxes = _cairo_malloc_ab (n, sizeof (glitz_box_t));
+ if (*boxes == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto done;
+ }
}
for (i = 0; i < n; i++) {
- (*boxes)[i].x1 = cboxes[i].p1.x;
- (*boxes)[i].y1 = cboxes[i].p1.y;
- (*boxes)[i].x2 = cboxes[i].p2.x;
- (*boxes)[i].y2 = cboxes[i].p2.y;
+ (*boxes)[i].x1 = pboxes[i].x1;
+ (*boxes)[i].y1 = pboxes[i].y1;
+ (*boxes)[i].x2 = pboxes[i].x2;
+ (*boxes)[i].y2 = pboxes[i].y2;
}
*nboxes = n;
done:
- _cairo_region_boxes_fini (region, cboxes);
return status;
}
static cairo_status_t
_cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
cairo_rectangle_int_t *interest,
cairo_image_surface_t **image_out,
cairo_rectangle_int_t *rect_out)
{
cairo_image_surface_t *image;
- int x1, y1, x2, y2;
- int width, height;
- unsigned char *pixels;
+ cairo_rectangle_int_t extents;
+ cairo_format_t format;
cairo_format_masks_t masks;
glitz_buffer_t *buffer;
glitz_pixel_format_t pf;
- cairo_format_t format;
-
- x1 = 0;
- y1 = 0;
- x2 = glitz_surface_get_width (surface->surface);
- y2 = glitz_surface_get_height (surface->surface);
- if (interest)
- {
- if (interest->x > x1)
- x1 = interest->x;
- if (interest->y > y1)
- y1 = interest->y;
- if (interest->x + interest->width < x2)
- x2 = interest->x + interest->width;
- if (interest->y + interest->height < y2)
- y2 = interest->y + interest->height;
+ extents.x = 0;
+ extents.y = 0;
+ extents.width = glitz_surface_get_width (surface->surface);
+ extents.height = glitz_surface_get_height (surface->surface);
- if (x1 >= x2 || y1 >= y2)
- {
+ if (interest != NULL) {
+ if (! _cairo_rectangle_intersect (&extents, interest)) {
*image_out = NULL;
return CAIRO_STATUS_SUCCESS;
}
}
- width = x2 - x1;
- height = y2 - y1;
-
- if (rect_out)
- {
- rect_out->x = x1;
- rect_out->y = y1;
- rect_out->width = width;
- rect_out->height = height;
- }
+ if (rect_out != NULL)
+ *rect_out = extents;
if (surface->format->color.fourcc == GLITZ_FOURCC_RGB) {
if (surface->format->color.red_size > 0) {
- masks.bpp = 32;
-
if (surface->format->color.alpha_size > 0)
- masks.alpha_mask = 0xff000000;
+ format = CAIRO_FORMAT_ARGB32;
else
- masks.alpha_mask = 0x0;
-
- masks.red_mask = 0xff0000;
- masks.green_mask = 0xff00;
- masks.blue_mask = 0xff;
+ format = CAIRO_FORMAT_RGB24;
} else {
- masks.bpp = 8;
- masks.blue_mask = masks.green_mask = masks.red_mask = 0x0;
- masks.alpha_mask = 0xff;
+ format = CAIRO_FORMAT_A8;
}
- } else {
- masks.bpp = 32;
- masks.alpha_mask = 0xff000000;
- masks.red_mask = 0xff0000;
- masks.green_mask = 0xff00;
- masks.blue_mask = 0xff;
- }
+ } else
+ format = CAIRO_FORMAT_ARGB32;
+ image = (cairo_image_surface_t*)
+ cairo_image_surface_create (format, extents.width, extents.height);
+ if (image->base.status)
+ return image->base.status;
+
+ _pixman_format_to_masks (image->pixman_format, &masks);
pf.fourcc = GLITZ_FOURCC_RGB;
pf.masks.bpp = masks.bpp;
pf.masks.alpha_mask = masks.alpha_mask;
- pf.masks.red_mask = masks.red_mask;
+ pf.masks.red_mask = masks.red_mask;
pf.masks.green_mask = masks.green_mask;
- pf.masks.blue_mask = masks.blue_mask;
+ pf.masks.blue_mask = masks.blue_mask;
pf.xoffset = 0;
pf.skip_lines = 0;
/* XXX: we should eventually return images with negative stride,
need to verify that libpixman have no problem with this first. */
- pf.bytes_per_line = (((width * masks.bpp) / 8) + 3) & -4;
+ pf.bytes_per_line = image->stride;
pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;
- pixels = _cairo_malloc_ab (height, pf.bytes_per_line);
- if (!pixels)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- buffer = glitz_buffer_create_for_data (pixels);
- if (!buffer) {
- free (pixels);
+ buffer = glitz_buffer_create_for_data (image->data);
+ if (buffer == NULL) {
+ cairo_surface_destroy (&image->base);
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
/* clear out the glitz clip; the clip affects glitz_get_pixels */
if (surface->has_clip)
glitz_surface_set_clip_region (surface->surface,
0, 0, NULL, 0);
glitz_get_pixels (surface->surface,
- x1, y1,
- width, height,
+ extents.x, extents.y,
+ extents.width, extents.height,
&pf,
buffer);
glitz_buffer_destroy (buffer);
/* restore the clip, if any */
if (surface->has_clip) {
- glitz_box_t *box;
- cairo_status_t status;
- int n;
-
- status = _cairo_glitz_get_boxes_from_region (&surface->clip, &box, &n);
- if (status) {
- free (pixels);
- return status;
- }
-
- glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
-
- free (box);
+ glitz_surface_set_clip_region (surface->surface,
+ 0, 0,
+ surface->clip_boxes,
+ surface->num_clip_boxes);
}
- /*
- * Prefer to use a standard pixman format instead of the
- * general masks case.
- */
- if (_CAIRO_MASK_FORMAT (&masks, &format)) {
- image = (cairo_image_surface_t *)
- cairo_image_surface_create_for_data (pixels,
- format,
- x2 - x1,
- y2 - y1,
- pf.bytes_per_line);
- if (image->base.status)
- goto FAIL;
- } else {
- /*
- * XXX This can't work. We must convert the data to one of the
- * supported pixman formats. Pixman needs another function
- * which takes data in an arbitrary format and converts it
- * to something supported by that library.
- */
- image = (cairo_image_surface_t *)
- _cairo_image_surface_create_with_masks (pixels,
- &masks,
- x2 - x1,
- y2 - y1,
- pf.bytes_per_line);
- if (image->base.status)
- goto FAIL;
- }
-
- _cairo_image_surface_assume_ownership_of_data (image);
-
*image_out = image;
return CAIRO_STATUS_SUCCESS;
-
-FAIL:
- free (pixels);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-}
-
-static void
-cairo_format_get_masks (cairo_format_t format,
- uint32_t *bpp,
- uint32_t *alpha,
- uint32_t *red,
- uint32_t *green,
- uint32_t *blue)
-{
- *red = 0x0;
- *green = 0x0;
- *blue = 0x0;
- *alpha = 0x0;
-
- switch (format)
- {
- case CAIRO_FORMAT_ARGB32:
- *alpha = 0xff000000;
- case CAIRO_FORMAT_RGB24:
- default:
- *bpp = 32;
- *red = 0x00ff0000;
- *green = 0x0000ff00;
- *blue = 0x000000ff;
- break;
-
- case CAIRO_FORMAT_A8:
- *bpp = 8;
- *alpha = 0xff;
- break;
-
- case CAIRO_FORMAT_A1:
- *bpp = 1;
- *alpha = 0x1;
- break;
- }
}
static cairo_status_t
_cairo_glitz_surface_set_image (void *abstract_surface,
cairo_image_surface_t *image,
int src_x,
int src_y,
int width,
int height,
int x_dst,
int y_dst)
{
cairo_glitz_surface_t *surface = abstract_surface;
glitz_buffer_t *buffer;
glitz_pixel_format_t pf;
- uint32_t bpp, am, rm, gm, bm;
+ cairo_format_masks_t masks;
char *data;
- cairo_format_get_masks (image->format, &bpp, &am, &rm, &gm, &bm);
+ _pixman_format_to_masks (image->pixman_format, &masks);
pf.fourcc = GLITZ_FOURCC_RGB;
- pf.masks.bpp = bpp;
- pf.masks.alpha_mask = am;
- pf.masks.red_mask = rm;
- pf.masks.green_mask = gm;
- pf.masks.blue_mask = bm;
+ pf.masks.bpp = masks.bpp;
+ pf.masks.alpha_mask = masks.alpha_mask;
+ pf.masks.red_mask = masks.red_mask;
+ pf.masks.green_mask = masks.green_mask;
+ pf.masks.blue_mask = masks.blue_mask;
pf.xoffset = src_x;
pf.skip_lines = src_y;
/* check for negative stride */
- if (image->stride < 0)
- {
+ if (image->stride < 0) {
pf.bytes_per_line = -image->stride;
pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP;
data = (char *) image->data + image->stride * (image->height - 1);
- }
- else
- {
+ } else {
pf.bytes_per_line = image->stride;
pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;
data = (char *) image->data;
}
buffer = glitz_buffer_create_for_data (data);
- if (!buffer)
+ if (buffer == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
glitz_set_pixels (surface->surface,
x_dst, y_dst,
width, height,
&pf,
buffer);
@@ -528,76 +373,60 @@ static cairo_status_t
*clone_offset_y = 0;
*clone_out = cairo_surface_reference (src);
return CAIRO_STATUS_SUCCESS;
}
else if (_cairo_surface_is_image (src))
{
cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
- cairo_content_t content;
- cairo_rectangle_int_t image_extent;
- cairo_rectangle_int_t extent;
-
- content = _cairo_content_from_format (image_src->format);
clone = (cairo_glitz_surface_t *)
- _cairo_glitz_surface_create_similar (surface, content,
- image_src->width,
- image_src->height);
+ _cairo_glitz_surface_create_similar (surface, src->content,
+ width, height);
if (clone == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
if (clone->base.status)
return clone->base.status;
- image_extent.x = 0;
- image_extent.y = 0;
- image_extent.width = image_src->width;
- image_extent.height = image_src->height;
- extent.x = src_x;
- extent.y = src_y;
- extent.width = width;
- extent.height = height;
-
- _cairo_rectangle_intersect(&extent, &image_extent);
-
status = _cairo_glitz_surface_set_image (clone, image_src,
- extent.x, extent.y,
- extent.width, extent.height,
- extent.x, extent.y);
+ src_x, src_y,
+ width, height,
+ 0, 0);
if (status) {
cairo_surface_destroy (&clone->base);
return status;
}
*clone_out = &clone->base;
-
+ *clone_offset_x = src_x;
+ *clone_offset_y = src_y;
return CAIRO_STATUS_SUCCESS;
}
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static void
_cairo_glitz_surface_set_matrix (cairo_glitz_surface_t *surface,
cairo_matrix_t *matrix)
{
glitz_transform_t transform;
- transform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx);
- transform.matrix[0][1] = _cairo_fixed_from_double (matrix->xy);
- transform.matrix[0][2] = _cairo_fixed_from_double (matrix->x0);
+ transform.matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
+ transform.matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
+ transform.matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0);
- transform.matrix[1][0] = _cairo_fixed_from_double (matrix->yx);
- transform.matrix[1][1] = _cairo_fixed_from_double (matrix->yy);
- transform.matrix[1][2] = _cairo_fixed_from_double (matrix->y0);
+ transform.matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx);
+ transform.matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy);
+ transform.matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0);
transform.matrix[2][0] = 0;
transform.matrix[2][1] = 0;
- transform.matrix[2][2] = _cairo_fixed_from_double (1);
+ transform.matrix[2][2] = _cairo_fixed_16_16_from_double (1);
glitz_surface_set_transform (surface->surface, &transform);
}
static glitz_operator_t
_glitz_operator (cairo_operator_t op)
{
switch (op) {
@@ -713,17 +542,17 @@ typedef struct _cairo_glitz_surface_attr
glitz_fill_t fill;
glitz_filter_t filter;
glitz_fixed16_16_t *params;
int n_params;
cairo_bool_t acquired;
} cairo_glitz_surface_attributes_t;
static cairo_int_status_t
-_cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern,
+_cairo_glitz_pattern_acquire_surface (const cairo_pattern_t *pattern,
cairo_glitz_surface_t *dst,
int x,
int y,
unsigned int width,
unsigned int height,
cairo_glitz_surface_t **surface_out,
cairo_glitz_surface_attributes_t *attr)
{
@@ -831,32 +660,32 @@ static cairo_int_status_t
(glitz_pixel_format_t *)&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->p1.x;
- params[1] = grad->p1.y;
- params[2] = grad->p2.x;
- params[3] = grad->p2.y;
+ params[0] = _cairo_fixed_to_16_16 (grad->p1.x);
+ params[1] = _cairo_fixed_to_16_16 (grad->p1.y);
+ params[2] = _cairo_fixed_to_16_16 (grad->p2.x);
+ params[3] = _cairo_fixed_to_16_16 (grad->p2.y);
attr->filter = GLITZ_FILTER_LINEAR_GRADIENT;
}
else
{
cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern;
- params[0] = grad->c1.x;
- params[1] = grad->c1.y;
- params[2] = grad->r1;
- params[3] = grad->c2.x;
- params[4] = grad->c2.y;
- params[5] = grad->r2;
+ params[0] = _cairo_fixed_to_16_16 (grad->c1.x);
+ params[1] = _cairo_fixed_to_16_16 (grad->c1.y);
+ params[2] = _cairo_fixed_to_16_16 (grad->r1);
+ params[3] = _cairo_fixed_to_16_16 (grad->c2.x);
+ params[4] = _cairo_fixed_to_16_16 (grad->c2.y);
+ params[5] = _cairo_fixed_to_16_16 (grad->r2);
attr->filter = GLITZ_FILTER_RADIAL_GRADIENT;
}
switch (pattern->extend) {
case CAIRO_EXTEND_NONE:
attr->fill = GLITZ_FILL_TRANSPARENT;
break;
case CAIRO_EXTEND_REPEAT:
@@ -932,29 +761,29 @@ static cairo_int_status_t
}
*surface_out = src;
return CAIRO_STATUS_SUCCESS;
}
static void
-_cairo_glitz_pattern_release_surface (cairo_pattern_t *pattern,
+_cairo_glitz_pattern_release_surface (const cairo_pattern_t *pattern,
cairo_glitz_surface_t *surface,
cairo_glitz_surface_attributes_t *attr)
{
if (attr->acquired)
_cairo_pattern_release_surface (pattern, &surface->base, &attr->base);
else
cairo_surface_destroy (&surface->base);
}
static cairo_int_status_t
-_cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src,
- cairo_pattern_t *mask,
+_cairo_glitz_pattern_acquire_surfaces (const cairo_pattern_t *src,
+ const cairo_pattern_t *mask,
cairo_glitz_surface_t *dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
unsigned int width,
unsigned int height,
cairo_glitz_surface_t **src_out,
@@ -980,47 +809,41 @@ static cairo_int_status_t
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, &combined, CAIRO_CONTENT_COLOR_ALPHA);
mask = NULL;
- } else {
- status = _cairo_pattern_init_copy (&tmp.base, src);
- if (status)
- return status;
+ src = &tmp.base;
}
- status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
+ status = _cairo_glitz_pattern_acquire_surface (src, dst,
src_x, src_y,
width, height,
src_out, sattr);
- _cairo_pattern_fini (&tmp.base);
+ if (src == &tmp.base)
+ _cairo_pattern_fini (&tmp.base);
if (status)
return status;
if (mask)
{
- status = _cairo_pattern_init_copy (&tmp.base, mask);
- if (status)
- return status;
-
- status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst,
+ status = _cairo_glitz_pattern_acquire_surface (mask, dst,
mask_x, mask_y,
width, height,
mask_out, mattr);
- if (status)
- _cairo_glitz_pattern_release_surface (&tmp.base, *src_out, sattr);
-
- _cairo_pattern_fini (&tmp.base);
+ if (status) {
+ /* XXX src == &tmp.base -> invalid (currently inconsequential) */
+ _cairo_glitz_pattern_release_surface (src, *src_out, sattr);
+ }
return status;
}
else
{
*mask_out = NULL;
}
@@ -1034,18 +857,18 @@ static void
_cairo_glitz_surface_set_matrix (surface, &a->base.matrix);
glitz_surface_set_fill (surface->surface, a->fill);
glitz_surface_set_filter (surface->surface, a->filter,
a->params, a->n_params);
}
static cairo_int_status_t
_cairo_glitz_surface_composite (cairo_operator_t op,
- cairo_pattern_t *src_pattern,
- cairo_pattern_t *mask_pattern,
+ const cairo_pattern_t *src_pattern,
+ const cairo_pattern_t *mask_pattern,
void *abstract_dst,
int src_x,
int src_y,
int mask_x,
int mask_y,
int dst_x,
int dst_y,
unsigned int width,
@@ -1082,190 +905,258 @@ static cairo_int_status_t
mask->surface,
dst->surface,
src_x + src_attr.base.x_offset,
src_y + src_attr.base.y_offset,
mask_x + mask_attr.base.x_offset,
mask_y + mask_attr.base.y_offset,
dst_x, dst_y,
width, height);
-
- if (mask_attr.n_params)
- free (mask_attr.params);
-
- _cairo_glitz_pattern_release_surface (mask_pattern, mask, &mask_attr);
}
else
{
glitz_composite (_glitz_operator (op),
src->surface,
NULL,
dst->surface,
src_x + src_attr.base.x_offset,
src_y + src_attr.base.y_offset,
0, 0,
dst_x, dst_y,
width, height);
}
+ if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (status == CAIRO_STATUS_SUCCESS &&
+ ! _cairo_operator_bounded_by_source (op))
+ {
+ int src_width, src_height;
+ int mask_width, mask_height;
+
+ src_width = glitz_surface_get_width (src->surface);
+ src_height = glitz_surface_get_height (src->surface);
+ if (mask)
+ {
+ mask_width = glitz_surface_get_width (mask->surface);
+ mask_height = glitz_surface_get_height (mask->surface);
+ }
+ else
+ {
+ mask_width = 0;
+ mask_height = 0;
+ }
+ status = _cairo_surface_composite_fixup_unbounded (&dst->base,
+ &src_attr.base,
+ src_width, src_height,
+ mask ? &mask_attr.base : NULL,
+ mask_width, mask_height,
+ src_x, src_y,
+ mask_x, mask_y,
+ dst_x, dst_y, width, height);
+ }
+
+ if (mask)
+ {
+ if (mask_attr.n_params)
+ free (mask_attr.params);
+
+ _cairo_glitz_pattern_release_surface (mask_pattern, mask, &mask_attr);
+ }
+
if (src_attr.n_params)
free (src_attr.params);
_cairo_glitz_pattern_release_surface (src_pattern, src, &src_attr);
- if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_glitz_surface_fill_rectangles (void *abstract_dst,
cairo_operator_t op,
const cairo_color_t *color,
cairo_rectangle_int_t *rects,
int n_rects)
{
cairo_glitz_surface_t *dst = abstract_dst;
cairo_glitz_surface_t *src;
+ glitz_rectangle_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (glitz_rectangle_t)];
+ glitz_rectangle_t *glitz_rects = stack_rects;
+ glitz_rectangle_t *current_rect;
+ int i;
+
+ if (n_rects > ARRAY_LENGTH (stack_rects)) {
+ glitz_rects = _cairo_malloc_ab (n_rects, sizeof (glitz_rectangle_t));
+ if (glitz_rects == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ for (i = 0; i < n_rects; i++) {
+ glitz_rects[i].x = rects[i].x;
+ glitz_rects[i].y = rects[i].y;
+ glitz_rects[i].width = rects[i].width;
+ glitz_rects[i].height = rects[i].height;
+ }
switch (op) {
+ case CAIRO_OPERATOR_CLEAR:
case CAIRO_OPERATOR_SOURCE: {
glitz_color_t glitz_color;
+ glitz_format_t *format;
glitz_color.red = color->red_short;
glitz_color.green = color->green_short;
glitz_color.blue = color->blue_short;
glitz_color.alpha = color->alpha_short;
- glitz_set_rectangles (dst->surface, &glitz_color,
- (glitz_rectangle_t *) rects, n_rects);
- } break;
- case CAIRO_OPERATOR_CLEAR: {
- static const glitz_color_t glitz_color = { 0, 0, 0, 0 };
+ /*
+ * XXX even if the dst surface don't have an alpha channel, the
+ * above alpha still effect the dst surface because the
+ * underlying glitz drawable may have an alpha channel. So
+ * replacing the color with an opaque one is needed.
+ */
+ format = glitz_surface_get_format (dst->surface);
+ if (format->color.alpha_size == 0)
+ glitz_color.alpha = 0xffff;
- glitz_set_rectangles (dst->surface, &glitz_color,
- (glitz_rectangle_t *) rects, n_rects);
+ glitz_set_rectangles (dst->surface, &glitz_color,
+ glitz_rects, n_rects);
} break;
case CAIRO_OPERATOR_SATURATE:
return CAIRO_INT_STATUS_UNSUPPORTED;
case CAIRO_OPERATOR_OVER:
case CAIRO_OPERATOR_IN:
case CAIRO_OPERATOR_OUT:
case CAIRO_OPERATOR_ATOP:
case CAIRO_OPERATOR_DEST:
case CAIRO_OPERATOR_DEST_OVER:
case CAIRO_OPERATOR_DEST_IN:
case CAIRO_OPERATOR_DEST_OUT:
case CAIRO_OPERATOR_DEST_ATOP:
case CAIRO_OPERATOR_XOR:
case CAIRO_OPERATOR_ADD:
default:
if (_glitz_ensure_target (dst->surface))
+ {
+ if (glitz_rects != stack_rects)
+ free (glitz_rects);
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);
if (src->base.status)
+ {
+ if (glitz_rects != stack_rects)
+ free (glitz_rects);
return src->base.status;
+ }
glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT);
+ current_rect = glitz_rects;
while (n_rects--)
{
glitz_composite (_glitz_operator (op),
src->surface,
NULL,
dst->surface,
0, 0,
0, 0,
- rects->x, rects->y,
- rects->width, rects->height);
- rects++;
+ current_rect->x, current_rect->y,
+ current_rect->width, current_rect->height);
+ current_rect++;
}
cairo_surface_destroy (&src->base);
break;
}
+ if (glitz_rects != stack_rects)
+ free (glitz_rects);
+
if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
_cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
- cairo_pattern_t *pattern,
+ const cairo_pattern_t *pattern,
void *abstract_dst,
cairo_antialias_t antialias,
int src_x,
int src_y,
int dst_x,
int dst_y,
unsigned int width,
unsigned int height,
cairo_trapezoid_t *traps,
int n_traps)
{
- cairo_pattern_union_t tmp_src_pattern;
- cairo_pattern_t *src_pattern;
cairo_glitz_surface_attributes_t attributes;
cairo_glitz_surface_t *dst = abstract_dst;
cairo_glitz_surface_t *src;
cairo_glitz_surface_t *mask = NULL;
glitz_buffer_t *buffer = NULL;
void *data = NULL;
cairo_int_status_t status;
unsigned short alpha;
+ pixman_trapezoid_t stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)];
+ pixman_trapezoid_t *pixman_traps = stack_traps;
+ int i;
if (antialias != CAIRO_ANTIALIAS_DEFAULT &&
antialias != CAIRO_ANTIALIAS_GRAY)
+ {
return CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (dst->base.status)
- return dst->base.status;
+ }
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;
+ /* Convert traps to pixman traps */
+ if (n_traps > ARRAY_LENGTH (stack_traps)) {
+ pixman_traps = _cairo_malloc_ab (n_traps, sizeof (pixman_trapezoid_t));
+ if (pixman_traps == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
- 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;
+ for (i = 0; i < n_traps; i++) {
+ pixman_traps[i].top = _cairo_fixed_to_16_16 (traps[i].top);
+ pixman_traps[i].bottom = _cairo_fixed_to_16_16 (traps[i].bottom);
+ pixman_traps[i].left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x);
+ pixman_traps[i].left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y);
+ pixman_traps[i].left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x);
+ pixman_traps[i].left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y);
+ pixman_traps[i].right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x);
+ pixman_traps[i].right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y);
+ pixman_traps[i].right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x);
+ pixman_traps[i].right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y);
}
- else
- {
- status = _cairo_glitz_pattern_acquire_surface (pattern, dst,
- src_x, src_y,
- width, height,
- &src, &attributes);
- src_pattern = pattern;
- }
+
+ status = _cairo_glitz_pattern_acquire_surface (pattern, dst,
+ src_x, src_y,
+ width, height,
+ &src, &attributes);
+ if (status)
+ goto FAIL;
+
alpha = 0xffff;
- if (status)
- return status;
-
- if (op == CAIRO_OPERATOR_ADD || n_traps <= 1)
- {
+ if (op == CAIRO_OPERATOR_ADD || n_traps <= 1) {
static const glitz_color_t clear_black = { 0, 0, 0, 0 };
glitz_color_t color;
glitz_geometry_format_t format;
int n_trap_added;
int offset = 0;
int data_size = 0;
int size = 30 * n_traps; /* just a guess */
@@ -1277,143 +1168,124 @@ static cairo_int_status_t
format.vertex.mask.size = GLITZ_COORDINATE_SIZE_X;
format.vertex.mask.offset = 2 * sizeof (glitz_float_t);
mask = (cairo_glitz_surface_t *)
_cairo_glitz_surface_create_similar (&dst->base,
CAIRO_CONTENT_ALPHA,
2, 1);
if (mask == NULL) {
- _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
- if (src_pattern == &tmp_src_pattern.base)
- _cairo_pattern_fini (&tmp_src_pattern.base);
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto FAIL;
}
if (mask->base.status) {
- _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
- if (src_pattern == &tmp_src_pattern.base)
- _cairo_pattern_fini (&tmp_src_pattern.base);
-
- return mask->base.status;
+ status = mask->base.status;
+ goto FAIL;
}
color.red = color.green = color.blue = color.alpha = 0xffff;
glitz_set_rectangle (mask->surface, &clear_black, 0, 0, 1, 1);
glitz_set_rectangle (mask->surface, &color, 1, 0, 1, 1);
glitz_surface_set_fill (mask->surface, GLITZ_FILL_NEAREST);
glitz_surface_set_filter (mask->surface,
GLITZ_FILTER_BILINEAR,
NULL, 0);
size *= format.vertex.bytes_per_vertex;
- while (n_traps)
- {
- if (data_size < size)
- {
+ while (n_traps) {
+ if (data_size < size) {
void *p;
+
data_size = size;
p = realloc (data, data_size);
- if (!p)
- {
- _cairo_glitz_pattern_release_surface (src_pattern, src,
- &attributes);
- if (src_pattern == &tmp_src_pattern.base)
- _cairo_pattern_fini (&tmp_src_pattern.base);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (p == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FAIL;
}
data = p;
if (buffer)
glitz_buffer_destroy (buffer);
buffer = glitz_buffer_create_for_data (data);
- if (!buffer) {
+ if (buffer == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
free (data);
- _cairo_glitz_pattern_release_surface (src_pattern, src,
- &attributes);
- if (src_pattern == &tmp_src_pattern.base)
- _cairo_pattern_fini (&tmp_src_pattern.base);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FAIL;
}
}
offset +=
glitz_add_trapezoids (buffer,
offset, size - offset,
format.vertex.type, mask->surface,
- (glitz_trapezoid_t *) traps, n_traps,
+ (glitz_trapezoid_t *) pixman_traps, n_traps,
&n_trap_added);
n_traps -= n_trap_added;
traps += n_trap_added;
size *= 2;
}
glitz_set_geometry (dst->surface,
GLITZ_GEOMETRY_TYPE_VERTEX,
&format, buffer);
glitz_set_array (dst->surface, 0, 3,
offset / format.vertex.bytes_per_vertex,
0, 0);
- }
- else
- {
+ } else {
cairo_image_surface_t *image;
unsigned char *ptr;
int stride;
stride = (width + 3) & -4;
data = calloc (stride, height);
- if (!data)
- {
- _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
- if (src_pattern == &tmp_src_pattern.base)
- _cairo_pattern_fini (&tmp_src_pattern.base);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (data == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto FAIL;
}
/* using negative stride */
ptr = (unsigned char *) data + stride * (height - 1);
image = (cairo_image_surface_t *)
cairo_image_surface_create_for_data (ptr,
CAIRO_FORMAT_A8,
width, height,
-stride);
- if (image->base.status)
- {
- cairo_surface_destroy (&src->base);
+ status = image->base.status;
+ if (status) {
free (data);
- return image->base.status;
+ goto FAIL;
}
pixman_add_trapezoids (image->pixman_image, -dst_x, -dst_y,
- n_traps, (pixman_trapezoid_t *) traps);
+ n_traps, (pixman_trapezoid_t *) pixman_traps);
mask = (cairo_glitz_surface_t *)
_cairo_surface_create_similar_scratch (&dst->base,
CAIRO_CONTENT_ALPHA,
width, height);
- if (mask->base.status) {
- _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
+ status = mask->base.status;
+ if (status) {
free (data);
cairo_surface_destroy (&image->base);
- return mask->base.status;
+ goto FAIL;
}
status = _cairo_glitz_surface_set_image (mask, image,
0, 0, width, height, 0, 0);
- cairo_surface_destroy(&image->base);
+ cairo_surface_destroy (&image->base);
if (status)
- return status;
+ goto FAIL;
}
_cairo_glitz_surface_set_attributes (src, &attributes);
glitz_composite (_glitz_operator (op),
src->surface,
mask->surface,
dst->surface,
@@ -1430,86 +1302,82 @@ static cairo_int_status_t
GLITZ_GEOMETRY_TYPE_NONE,
NULL, NULL);
if (buffer)
glitz_buffer_destroy (buffer);
free (data);
- _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes);
- if (src_pattern == &tmp_src_pattern.base)
- _cairo_pattern_fini (&tmp_src_pattern.base);
+ if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto FAIL;
+ }
- if (mask)
+ if (! _cairo_operator_bounded_by_mask (op)) {
+ status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
+ &attributes.base,
+ glitz_surface_get_width (src->surface),
+ glitz_surface_get_height (src->surface),
+ width, height,
+ src_x, src_y,
+ 0, 0,
+ dst_x, dst_y,
+ width, height);
+ }
+
+FAIL:
+ _cairo_glitz_pattern_release_surface (pattern, src, &attributes);
+
+ if (mask != NULL)
cairo_surface_destroy (&mask->base);
- if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ if (pixman_traps != stack_traps)
+ free (pixman_traps);
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
static cairo_int_status_t
_cairo_glitz_surface_set_clip_region (void *abstract_surface,
cairo_region_t *region)
{
cairo_glitz_surface_t *surface = abstract_surface;
- if (region)
- {
- glitz_box_t *box;
- int n;
+ if (region != NULL) {
cairo_status_t status;
- if (!surface->has_clip) {
- _cairo_region_init (&surface->clip);
- surface->has_clip = TRUE;
- }
-
- status = _cairo_region_copy (&surface->clip, region);
- if (status) {
- _cairo_region_fini (&surface->clip);
- surface->has_clip = FALSE;
+ status = _cairo_glitz_get_boxes_from_region (region,
+ &surface->clip_boxes,
+ &surface->num_clip_boxes);
+ if (status)
return status;
- }
- status = _cairo_glitz_get_boxes_from_region (&surface->clip, &box, &n);
- if (status) {
- _cairo_region_fini (&surface->clip);
- surface->has_clip = FALSE;
- return status;
- }
-
- glitz_surface_set_clip_region (surface->surface, 0, 0, box, n);
-
- free (box);
- }
- else
- {
+ glitz_surface_set_clip_region (surface->surface,
+ 0, 0,
+ surface->clip_boxes,
+ surface->num_clip_boxes);
+ surface->has_clip = TRUE;
+ } else {
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);