2008-08-27 21:14:51 -07:00
|
|
|
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
|
2004-08-02 13:13:28 +00:00
|
|
|
/* cairo - a vector graphics library with display and print output
|
|
|
|
|
*
|
2004-10-21 18:40:50 +00:00
|
|
|
* Copyright © 2002 University of Southern California
|
2005-07-21 14:31:28 +00:00
|
|
|
* Copyright © 2005 Red Hat, Inc.
|
2003-09-30 18:56:22 +00:00
|
|
|
*
|
2004-08-02 13:13:28 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
2004-09-04 06:38:34 +00:00
|
|
|
* 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
|
2010-04-27 10:17:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
2004-09-04 06:38:34 +00:00
|
|
|
* You should have received a copy of the MPL along with this library
|
|
|
|
|
* in the file COPYING-MPL-1.1
|
|
|
|
|
*
|
|
|
|
|
* The contents of this file are subject to the Mozilla Public License
|
|
|
|
|
* Version 1.1 (the "License"); you may not use this file except in
|
|
|
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
|
*
|
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
|
|
|
|
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
|
|
|
|
* the specific language governing rights and limitations.
|
|
|
|
|
*
|
|
|
|
|
* The Original Code is the cairo graphics library.
|
|
|
|
|
*
|
|
|
|
|
* The Initial Developer of the Original Code is University of Southern
|
|
|
|
|
* California.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s):
|
2005-02-22 11:35:03 +00:00
|
|
|
* Carl D. Worth <cworth@cworth.org>
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
* Behdad Esfahbod <behdad@behdad.org>
|
2008-09-02 10:08:04 +01:00
|
|
|
* Chris Wilson <chris@chris-wilson.co.uk>
|
|
|
|
|
* Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
|
2003-09-30 18:56:22 +00:00
|
|
|
*/
|
|
|
|
|
|
2009-07-27 19:18:21 +01:00
|
|
|
/* Heed well the words of Owen Taylor:
|
|
|
|
|
* "Any patch that works around a render bug, or claims to, without a
|
|
|
|
|
* specific reference to the bug filed in bugzilla.freedesktop.org will
|
|
|
|
|
* never pass approval."
|
|
|
|
|
*/
|
|
|
|
|
|
2003-09-30 18:56:22 +00:00
|
|
|
#include "cairoint.h"
|
2007-08-31 20:52:43 -04:00
|
|
|
|
2005-07-21 06:52:13 +00:00
|
|
|
#include "cairo-xlib-private.h"
|
2007-04-20 01:46:23 -04:00
|
|
|
#include "cairo-xlib-surface-private.h"
|
2006-03-08 21:08:57 -08:00
|
|
|
#include "cairo-clip-private.h"
|
2010-01-18 16:58:40 +00:00
|
|
|
#include "cairo-error-private.h"
|
2008-05-06 14:52:02 +01:00
|
|
|
#include "cairo-scaled-font-private.h"
|
2010-06-19 10:26:05 +01:00
|
|
|
#include "cairo-surface-snapshot-private.h"
|
|
|
|
|
#include "cairo-surface-subsurface-private.h"
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
#include "cairo-region-private.h"
|
2005-05-13 17:54:43 +00:00
|
|
|
|
2008-01-14 18:09:32 +00:00
|
|
|
#include <X11/Xutil.h> /* for XDestroyImage */
|
|
|
|
|
|
2008-08-27 21:14:51 -07:00
|
|
|
#define XLIB_COORD_MAX 32767
|
2010-12-17 11:03:03 +01:00
|
|
|
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
|
2008-08-27 21:14:51 -07:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
#define DEBUG 0
|
|
|
|
|
|
|
|
|
|
#if DEBUG
|
2009-08-10 17:57:16 +01:00
|
|
|
#define UNSUPPORTED(reason) \
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
fprintf (stderr, \
|
|
|
|
|
"cairo-xlib: hit unsupported operation %s(), line %d: %s\n", \
|
2009-08-10 17:57:16 +01:00
|
|
|
__FUNCTION__, __LINE__, reason), \
|
|
|
|
|
CAIRO_INT_STATUS_UNSUPPORTED
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
#else
|
|
|
|
|
#define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED
|
|
|
|
|
#endif
|
|
|
|
|
|
2009-09-29 03:02:40 +01:00
|
|
|
#if DEBUG
|
|
|
|
|
#include <X11/Xlibint.h>
|
|
|
|
|
static void CAIRO_PRINTF_FORMAT (2, 3)
|
|
|
|
|
_x_bread_crumb (Display *dpy,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
...)
|
|
|
|
|
{
|
|
|
|
|
xReq *req;
|
|
|
|
|
char buf[2048];
|
|
|
|
|
unsigned int len, len_dwords;
|
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
|
|
va_start (ap, fmt);
|
|
|
|
|
len = vsnprintf (buf, sizeof (buf), fmt, ap);
|
|
|
|
|
va_end (ap);
|
|
|
|
|
|
|
|
|
|
buf[len++] = '\0';
|
|
|
|
|
while (len & 3)
|
|
|
|
|
buf[len++] = '\0';
|
|
|
|
|
|
|
|
|
|
LockDisplay (dpy);
|
|
|
|
|
GetEmptyReq (NoOperation, req);
|
|
|
|
|
|
|
|
|
|
len_dwords = len >> 2;
|
|
|
|
|
SetReqLen (req, len_dwords, len_dwords);
|
|
|
|
|
Data (dpy, buf, len);
|
|
|
|
|
|
|
|
|
|
UnlockDisplay (dpy);
|
|
|
|
|
SyncHandle ();
|
|
|
|
|
}
|
|
|
|
|
#define X_DEBUG(x) _x_bread_crumb x
|
|
|
|
|
#else
|
2009-09-30 00:37:36 +01:00
|
|
|
#define X_DEBUG(x)
|
2009-09-29 03:02:40 +01:00
|
|
|
#endif
|
|
|
|
|
|
2010-07-08 13:05:18 +02:00
|
|
|
/**
|
|
|
|
|
* SECTION:cairo-xlib
|
|
|
|
|
* @Title: XLib Surfaces
|
|
|
|
|
* @Short_Description: X Window System rendering using XLib
|
|
|
|
|
* @See_Also: #cairo_surface_t
|
|
|
|
|
*
|
|
|
|
|
* The XLib surface is used to render cairo graphics to X Window System
|
|
|
|
|
* windows and pixmaps using the XLib library.
|
|
|
|
|
*
|
|
|
|
|
* Note that the XLib surface automatically takes advantage of X render extension
|
|
|
|
|
* if it is available.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* CAIRO_HAS_XLIB_SURFACE:
|
|
|
|
|
*
|
|
|
|
|
* Defined if the Xlib surface backend is available.
|
|
|
|
|
* This macro can be used to conditionally compile backend-specific code.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SECTION:cairo-xlib-xrender
|
|
|
|
|
* @Title: XLib/XRender Backend
|
|
|
|
|
* @Short_Description: X Window System rendering using XLib and the X Render extension
|
|
|
|
|
* @See_Also: #cairo_surface_t
|
|
|
|
|
*
|
|
|
|
|
* The XLib surface is used to render cairo graphics to X Window System
|
|
|
|
|
* windows and pixmaps using the XLib and Xrender libraries.
|
|
|
|
|
*
|
|
|
|
|
* Note that the XLib surface automatically takes advantage of X Render extension
|
|
|
|
|
* if it is available.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* CAIRO_HAS_XLIB_XRENDER_SURFACE:
|
|
|
|
|
*
|
|
|
|
|
* Defined if the XLib/XRender surface functions are available.
|
|
|
|
|
* This macro can be used to conditionally compile backend-specific code.
|
|
|
|
|
*/
|
|
|
|
|
|
2005-05-13 17:54:43 +00:00
|
|
|
/* Xlib doesn't define a typedef, so define one ourselves */
|
|
|
|
|
typedef int (*cairo_xlib_error_func_t) (Display *display,
|
|
|
|
|
XErrorEvent *event);
|
2003-09-30 18:56:22 +00:00
|
|
|
|
2008-04-02 10:43:39 +01:00
|
|
|
static cairo_surface_t *
|
2009-09-01 23:12:43 +01:00
|
|
|
_cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
|
2008-04-02 10:43:39 +01:00
|
|
|
Drawable drawable,
|
|
|
|
|
Visual *visual,
|
|
|
|
|
XRenderPictFormat *xrender_format,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
int depth);
|
|
|
|
|
|
2005-06-20 15:48:46 +00:00
|
|
|
static cairo_bool_t
|
|
|
|
|
_cairo_surface_is_xlib (cairo_surface_t *surface);
|
|
|
|
|
|
2005-08-31 15:09:35 +00:00
|
|
|
static cairo_bool_t
|
|
|
|
|
_native_byte_order_lsb (void);
|
|
|
|
|
|
2006-03-08 21:08:57 -08:00
|
|
|
static cairo_int_status_t
|
|
|
|
|
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
|
|
|
|
cairo_operator_t op,
|
2008-10-22 19:24:44 +01:00
|
|
|
const cairo_pattern_t *src_pattern,
|
2007-08-31 16:53:21 +01:00
|
|
|
cairo_glyph_t *glyphs,
|
2006-03-08 21:08:57 -08:00
|
|
|
int num_glyphs,
|
2008-05-23 19:57:48 -04:00
|
|
|
cairo_scaled_font_t *scaled_font,
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
cairo_clip_t *clip,
|
|
|
|
|
int *remaining_glyphs);
|
2006-03-08 21:08:57 -08:00
|
|
|
|
2005-05-17 06:05:13 +00:00
|
|
|
/*
|
|
|
|
|
* Instead of taking two round trips for each blending request,
|
|
|
|
|
* assume that if a particular drawable fails GetImage that it will
|
|
|
|
|
* fail for a "while"; use temporary pixmaps to avoid the errors
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define CAIRO_ASSUME_PIXMAP 20
|
|
|
|
|
|
2007-04-18 18:08:45 +01:00
|
|
|
static const XTransform identity = { {
|
|
|
|
|
{ 1 << 16, 0x00000, 0x00000 },
|
|
|
|
|
{ 0x00000, 1 << 16, 0x00000 },
|
|
|
|
|
{ 0x00000, 0x00000, 1 << 16 },
|
|
|
|
|
} };
|
|
|
|
|
|
2003-09-30 18:56:22 +00:00
|
|
|
#define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \
|
|
|
|
|
(((surface)->render_major > major) || \
|
|
|
|
|
(((surface)->render_major == major) && ((surface)->render_minor >= minor)))
|
|
|
|
|
|
|
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
|
|
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
|
2005-01-31 08:50:22 +00:00
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
|
|
|
|
|
|
2003-09-30 18:56:22 +00:00
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
|
|
|
|
|
|
|
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_DISJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
|
|
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_CONJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
|
|
|
|
|
|
|
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
|
|
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_TRIANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
|
|
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_TRISTRIP(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
|
|
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_TRIFAN(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
|
|
|
|
|
|
|
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
|
2004-02-02 11:20:44 +00:00
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_FILTERS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
|
2003-09-30 18:56:22 +00:00
|
|
|
|
2009-07-31 11:35:45 +01:00
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_EXTENDED_REPEAT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
|
2009-07-31 13:17:24 +01:00
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_GRADIENTS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
|
2009-07-31 11:35:45 +01:00
|
|
|
|
2009-07-16 14:18:13 +01:00
|
|
|
#define CAIRO_SURFACE_RENDER_HAS_PDF_OPERATORS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 11)
|
|
|
|
|
|
2009-08-14 11:35:55 -05:00
|
|
|
#define CAIRO_SURFACE_RENDER_SUPPORTS_OPERATOR(surface, op) \
|
|
|
|
|
((op) <= CAIRO_OPERATOR_SATURATE || \
|
|
|
|
|
(CAIRO_SURFACE_RENDER_HAS_PDF_OPERATORS(surface) && \
|
|
|
|
|
(op) <= CAIRO_OPERATOR_HSL_LUMINOSITY))
|
2009-07-16 14:18:13 +01:00
|
|
|
|
2010-06-11 10:35:43 +01:00
|
|
|
static Visual *
|
|
|
|
|
_visual_for_xrender_format(Screen *screen,
|
|
|
|
|
XRenderPictFormat *xrender_format)
|
|
|
|
|
{
|
|
|
|
|
int d, v;
|
|
|
|
|
|
|
|
|
|
/* XXX Consider searching through the list of known cairo_visual_t for
|
|
|
|
|
* the reverse mapping.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
for (d = 0; d < screen->ndepths; d++) {
|
|
|
|
|
Depth *d_info = &screen->depths[d];
|
|
|
|
|
|
|
|
|
|
if (d_info->depth != xrender_format->depth)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
for (v = 0; v < d_info->nvisuals; v++) {
|
|
|
|
|
Visual *visual = &d_info->visuals[v];
|
|
|
|
|
|
|
|
|
|
switch (visual->class) {
|
|
|
|
|
case TrueColor:
|
|
|
|
|
if (xrender_format->type != PictTypeDirect)
|
|
|
|
|
continue;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DirectColor:
|
|
|
|
|
/* Prefer TrueColor to DirectColor.
|
|
|
|
|
* (XRenderFindVisualFormat considers both TrueColor and DirectColor
|
|
|
|
|
* Visuals to match the same PictFormat.)
|
|
|
|
|
*/
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
case StaticGray:
|
|
|
|
|
case GrayScale:
|
|
|
|
|
case StaticColor:
|
|
|
|
|
case PseudoColor:
|
|
|
|
|
if (xrender_format->type != PictTypeIndexed)
|
|
|
|
|
continue;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (xrender_format ==
|
|
|
|
|
XRenderFindVisualFormat (DisplayOfScreen(screen), visual))
|
|
|
|
|
return visual;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_xlib_surface_set_clip_region (cairo_xlib_surface_t *surface,
|
|
|
|
|
cairo_region_t *region)
|
|
|
|
|
{
|
|
|
|
|
cairo_bool_t had_clip_rects = surface->clip_region != NULL;
|
|
|
|
|
|
|
|
|
|
if (had_clip_rects == FALSE && region == NULL)
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
if (surface->clip_region == region)
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
if (cairo_region_equal (surface->clip_region, region))
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
cairo_region_destroy (surface->clip_region);
|
|
|
|
|
surface->clip_region = cairo_region_reference (region);
|
|
|
|
|
|
|
|
|
|
if (surface->clip_rects != surface->embedded_clip_rects) {
|
|
|
|
|
free (surface->clip_rects);
|
|
|
|
|
surface->clip_rects = surface->embedded_clip_rects;
|
|
|
|
|
}
|
|
|
|
|
surface->num_clip_rects = 0;
|
|
|
|
|
|
|
|
|
|
if (region != NULL) {
|
|
|
|
|
XRectangle *rects = NULL;
|
|
|
|
|
int n_rects, i;
|
|
|
|
|
|
|
|
|
|
n_rects = cairo_region_num_rectangles (region);
|
|
|
|
|
if (n_rects > ARRAY_LENGTH (surface->embedded_clip_rects)) {
|
|
|
|
|
rects = _cairo_malloc_ab (n_rects, sizeof (XRectangle));
|
|
|
|
|
if (unlikely (rects == NULL))
|
|
|
|
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
} else {
|
|
|
|
|
rects = surface->embedded_clip_rects;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n_rects; i++) {
|
|
|
|
|
cairo_rectangle_int_t rect;
|
|
|
|
|
|
|
|
|
|
cairo_region_get_rectangle (region, i, &rect);
|
|
|
|
|
|
|
|
|
|
rects[i].x = rect.x;
|
|
|
|
|
rects[i].y = rect.y;
|
|
|
|
|
rects[i].width = rect.width;
|
|
|
|
|
rects[i].height = rect.height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
surface->clip_rects = rects;
|
|
|
|
|
surface->num_clip_rects = n_rects;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
surface->clip_dirty = CAIRO_XLIB_SURFACE_CLIP_DIRTY_ALL;
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2006-05-24 17:05:51 -07:00
|
|
|
static cairo_content_t
|
|
|
|
|
_xrender_format_to_content (XRenderPictFormat *xrender_format)
|
2006-05-19 08:26:08 +12:00
|
|
|
{
|
2006-05-24 17:05:51 -07:00
|
|
|
cairo_bool_t xrender_format_has_alpha;
|
|
|
|
|
cairo_bool_t xrender_format_has_color;
|
|
|
|
|
|
|
|
|
|
/* This only happens when using a non-Render server. Let's punt
|
|
|
|
|
* and say there's no alpha here. */
|
|
|
|
|
if (xrender_format == NULL)
|
|
|
|
|
return CAIRO_CONTENT_COLOR;
|
|
|
|
|
|
2007-10-18 20:07:12 +01:00
|
|
|
xrender_format_has_alpha = (xrender_format->direct.alphaMask != 0);
|
|
|
|
|
xrender_format_has_color = (xrender_format->direct.redMask != 0 ||
|
|
|
|
|
xrender_format->direct.greenMask != 0 ||
|
|
|
|
|
xrender_format->direct.blueMask != 0);
|
2006-05-24 17:05:51 -07:00
|
|
|
|
|
|
|
|
if (xrender_format_has_alpha)
|
|
|
|
|
if (xrender_format_has_color)
|
|
|
|
|
return CAIRO_CONTENT_COLOR_ALPHA;
|
|
|
|
|
else
|
|
|
|
|
return CAIRO_CONTENT_ALPHA;
|
|
|
|
|
else
|
|
|
|
|
return CAIRO_CONTENT_COLOR;
|
2006-05-19 08:26:08 +12:00
|
|
|
}
|
|
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
static cairo_surface_t *
|
|
|
|
|
_cairo_xlib_surface_create_similar (void *abstract_src,
|
|
|
|
|
cairo_content_t content,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
|
|
|
|
{
|
2006-05-19 08:26:08 +12:00
|
|
|
cairo_xlib_surface_t *src = abstract_src;
|
2009-06-19 16:09:26 +01:00
|
|
|
XRenderPictFormat *xrender_format;
|
2006-05-18 15:36:43 -07:00
|
|
|
cairo_xlib_surface_t *surface;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2006-05-18 15:36:43 -07:00
|
|
|
Pixmap pix;
|
2006-05-19 08:26:08 +12:00
|
|
|
|
2008-08-27 21:14:51 -07:00
|
|
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
|
2009-05-20 18:49:28 +01:00
|
|
|
return NULL;
|
2008-08-27 21:14:51 -07:00
|
|
|
|
2009-09-20 18:46:19 +01:00
|
|
|
if (! CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (src))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
if (_cairo_xlib_display_acquire (src->base.device, &display))
|
|
|
|
|
return NULL;
|
2007-04-19 12:15:04 +01:00
|
|
|
|
2006-05-18 15:36:43 -07:00
|
|
|
/* If we never found an XRenderFormat or if it isn't compatible
|
|
|
|
|
* with the content being requested, then we fallback to just
|
|
|
|
|
* constructing a cairo_format_t instead, (which will fairly
|
|
|
|
|
* arbitrarily pick a visual/depth for the similar surface.
|
|
|
|
|
*/
|
2009-06-19 16:09:26 +01:00
|
|
|
xrender_format = src->xrender_format;
|
2009-09-20 18:46:19 +01:00
|
|
|
if ((xrender_format != NULL &&
|
|
|
|
|
_xrender_format_to_content (xrender_format) == content) ||
|
|
|
|
|
(xrender_format =
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_display_get_xrender_format (display,
|
2009-09-20 18:46:19 +01:00
|
|
|
_cairo_format_from_content (content))))
|
2006-05-18 15:36:43 -07:00
|
|
|
{
|
2009-09-20 18:46:19 +01:00
|
|
|
Visual *visual;
|
|
|
|
|
|
|
|
|
|
/* We've got a compatible XRenderFormat now, which means the
|
|
|
|
|
* similar surface will match the existing surface as closely in
|
|
|
|
|
* visual/depth etc. as possible. */
|
2010-04-18 23:20:02 +02:00
|
|
|
pix = XCreatePixmap (display->display, src->drawable,
|
2009-09-20 18:46:19 +01:00
|
|
|
width <= 0 ? 1 : width, height <= 0 ? 1 : height,
|
|
|
|
|
xrender_format->depth);
|
|
|
|
|
|
|
|
|
|
if (xrender_format == src->xrender_format)
|
|
|
|
|
visual = src->visual;
|
2010-06-11 10:35:43 +01:00
|
|
|
else
|
|
|
|
|
visual = _visual_for_xrender_format(src->screen->screen,
|
|
|
|
|
xrender_format);
|
2009-09-20 18:46:19 +01:00
|
|
|
|
|
|
|
|
surface = (cairo_xlib_surface_t *)
|
|
|
|
|
_cairo_xlib_surface_create_internal (src->screen, pix,
|
|
|
|
|
visual,
|
|
|
|
|
xrender_format,
|
|
|
|
|
width, height,
|
|
|
|
|
xrender_format->depth);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#ifdef DEBUG_FORCE_FALLBACKS
|
|
|
|
|
Screen *screen = src->screen->screen;
|
|
|
|
|
int depth;
|
|
|
|
|
|
|
|
|
|
/* No compatabile XRenderFormat, see if we can make an ordinary pixmap,
|
|
|
|
|
* so that we can still accelerate blits with XCopyArea(). */
|
2010-04-18 23:20:02 +02:00
|
|
|
if (content != CAIRO_CONTENT_COLOR) {
|
|
|
|
|
cairo_device_release (&display->base);
|
2009-09-20 18:46:19 +01:00
|
|
|
return NULL;
|
2010-04-18 23:20:02 +02:00
|
|
|
}
|
2009-09-20 18:46:19 +01:00
|
|
|
|
|
|
|
|
depth = DefaultDepthOfScreen (screen);
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
pix = XCreatePixmap (display->display, RootWindowOfScreen (screen),
|
2009-09-20 18:46:19 +01:00
|
|
|
width <= 0 ? 1 : width, height <= 0 ? 1 : height,
|
|
|
|
|
depth);
|
|
|
|
|
|
|
|
|
|
surface = (cairo_xlib_surface_t *)
|
|
|
|
|
_cairo_xlib_surface_create_internal (src->screen, pix,
|
|
|
|
|
DefaultVisualOfScreen (screen),
|
|
|
|
|
NULL,
|
|
|
|
|
width, height, depth);
|
|
|
|
|
#else
|
|
|
|
|
/* No compatabile XRenderFormat, just say no. */
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_device_release (&display->base);
|
2009-09-20 18:46:19 +01:00
|
|
|
return NULL;
|
|
|
|
|
#endif
|
2006-05-18 15:36:43 -07:00
|
|
|
}
|
|
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (unlikely (surface->base.status)) {
|
2010-04-18 23:20:02 +02:00
|
|
|
XFreePixmap (display->display, pix);
|
|
|
|
|
cairo_device_release (&display->base);
|
2008-01-16 16:23:23 +00:00
|
|
|
return &surface->base;
|
2006-05-19 08:26:08 +12:00
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2006-05-18 15:36:43 -07:00
|
|
|
surface->owns_pixmap = TRUE;
|
2006-05-19 08:26:08 +12:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_device_release (&display->base);
|
|
|
|
|
|
2006-05-18 15:36:43 -07:00
|
|
|
return &surface->base;
|
2005-08-31 15:08:02 +00:00
|
|
|
}
|
|
|
|
|
|
2005-03-16 12:08:41 +00:00
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_xlib_surface_finish (void *abstract_surface)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2003-10-27 18:40:55 +00:00
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_status_t status;
|
|
|
|
|
cairo_xlib_display_t *display;
|
|
|
|
|
|
|
|
|
|
X_DEBUG ((display->display, "finish (drawable=%x)", (unsigned int) surface->drawable));
|
2007-04-17 12:03:07 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
2009-09-29 03:02:40 +01:00
|
|
|
|
2007-06-27 10:53:29 -07:00
|
|
|
if (surface->owns_pixmap) {
|
2007-04-17 12:03:07 +01:00
|
|
|
cairo_status_t status2;
|
|
|
|
|
|
2007-06-27 10:53:29 -07:00
|
|
|
if (surface->dst_picture != None) {
|
|
|
|
|
status2 = _cairo_xlib_display_queue_resource (display,
|
|
|
|
|
XRenderFreePicture,
|
|
|
|
|
surface->dst_picture);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (status == CAIRO_STATUS_SUCCESS)
|
2007-06-27 10:53:29 -07:00
|
|
|
status = status2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (surface->src_picture != None) {
|
|
|
|
|
status2 = _cairo_xlib_display_queue_resource (display,
|
|
|
|
|
XRenderFreePicture,
|
|
|
|
|
surface->src_picture);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (status == CAIRO_STATUS_SUCCESS)
|
2007-06-27 10:53:29 -07:00
|
|
|
status = status2;
|
|
|
|
|
}
|
2007-04-17 12:03:07 +01:00
|
|
|
|
|
|
|
|
status2 = _cairo_xlib_display_queue_resource (display,
|
|
|
|
|
(cairo_xlib_notify_resource_func) XFreePixmap,
|
|
|
|
|
surface->drawable);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (status == CAIRO_STATUS_SUCCESS)
|
2007-04-17 12:03:07 +01:00
|
|
|
status = status2;
|
2007-06-27 10:53:29 -07:00
|
|
|
} else {
|
|
|
|
|
if (surface->dst_picture != None)
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderFreePicture (display->display, surface->dst_picture);
|
2007-06-27 10:53:29 -07:00
|
|
|
|
|
|
|
|
if (surface->src_picture != None)
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderFreePicture (display->display, surface->src_picture);
|
2007-04-17 12:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
2007-04-19 20:24:27 +01:00
|
|
|
if (surface->clip_rects != surface->embedded_clip_rects)
|
2005-06-20 15:48:46 +00:00
|
|
|
free (surface->clip_rects);
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
if (display->display != NULL)
|
|
|
|
|
_cairo_xlib_remove_close_display_hook (display,
|
2008-09-02 10:08:04 +01:00
|
|
|
&surface->close_display_hook);
|
2010-04-18 23:20:02 +02:00
|
|
|
|
|
|
|
|
cairo_device_release (&display->base);
|
2003-10-31 10:41:37 +00:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
cairo_region_destroy (surface->clip_region);
|
2008-09-02 10:28:17 +01:00
|
|
|
|
2007-04-17 12:03:07 +01:00
|
|
|
return status;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_xlib_surface_get_gc (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *surface,
|
|
|
|
|
GC *gc)
|
|
|
|
|
{
|
|
|
|
|
*gc = _cairo_xlib_screen_get_gc (display,
|
|
|
|
|
surface->screen,
|
|
|
|
|
surface->depth,
|
|
|
|
|
surface->drawable);
|
|
|
|
|
if (unlikely (*gc == NULL))
|
|
|
|
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_cairo_xlib_surface_put_gc (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *surface,
|
|
|
|
|
GC gc)
|
|
|
|
|
{
|
|
|
|
|
_cairo_xlib_screen_put_gc (display,
|
|
|
|
|
surface->screen,
|
|
|
|
|
surface->depth,
|
|
|
|
|
gc);
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-13 17:54:43 +00:00
|
|
|
static int
|
|
|
|
|
_noop_error_handler (Display *display,
|
|
|
|
|
XErrorEvent *event)
|
|
|
|
|
{
|
|
|
|
|
return False; /* return value is ignored */
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-31 15:09:35 +00:00
|
|
|
static void
|
|
|
|
|
_swap_ximage_2bytes (XImage *ximage)
|
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
char *line = ximage->data;
|
|
|
|
|
|
|
|
|
|
for (j = ximage->height; j; j--) {
|
2008-10-15 10:21:05 +01:00
|
|
|
uint16_t *p = (uint16_t *) line;
|
2005-08-31 15:09:35 +00:00
|
|
|
for (i = ximage->width; i; i--) {
|
2008-05-28 10:43:47 -04:00
|
|
|
*p = bswap_16 (*p);
|
2005-08-31 15:09:35 +00:00
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
line += ximage->bytes_per_line;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-15 10:21:05 +01:00
|
|
|
static void
|
|
|
|
|
_swap_ximage_3bytes (XImage *ximage)
|
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
char *line = ximage->data;
|
|
|
|
|
|
|
|
|
|
for (j = ximage->height; j; j--) {
|
|
|
|
|
uint8_t *p = (uint8_t *) line;
|
|
|
|
|
for (i = ximage->width; i; i--) {
|
|
|
|
|
uint8_t tmp;
|
|
|
|
|
tmp = p[2];
|
|
|
|
|
p[2] = p[0];
|
|
|
|
|
p[0] = tmp;
|
|
|
|
|
p += 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
line += ximage->bytes_per_line;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-31 15:09:35 +00:00
|
|
|
static void
|
|
|
|
|
_swap_ximage_4bytes (XImage *ximage)
|
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
char *line = ximage->data;
|
|
|
|
|
|
|
|
|
|
for (j = ximage->height; j; j--) {
|
2008-10-15 10:21:05 +01:00
|
|
|
uint32_t *p = (uint32_t *) line;
|
2005-08-31 15:09:35 +00:00
|
|
|
for (i = ximage->width; i; i--) {
|
2008-05-28 10:43:47 -04:00
|
|
|
*p = bswap_32 (*p);
|
2005-08-31 15:09:35 +00:00
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
line += ximage->bytes_per_line;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-15 10:21:05 +01:00
|
|
|
static void
|
|
|
|
|
_swap_ximage_nibbles (XImage *ximage)
|
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
char *line = ximage->data;
|
|
|
|
|
|
|
|
|
|
for (j = ximage->height; j; j--) {
|
|
|
|
|
uint8_t *p = (uint8_t *) line;
|
|
|
|
|
for (i = (ximage->width + 1) / 2; i; i--) {
|
|
|
|
|
*p = ((*p >> 4) & 0xf) | ((*p << 4) & ~0xf);
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
line += ximage->bytes_per_line;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-31 15:09:35 +00:00
|
|
|
static void
|
|
|
|
|
_swap_ximage_bits (XImage *ximage)
|
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
char *line = ximage->data;
|
|
|
|
|
int unit = ximage->bitmap_unit;
|
|
|
|
|
int line_bytes = ((ximage->width + unit - 1) & ~(unit - 1)) / 8;
|
|
|
|
|
|
|
|
|
|
for (j = ximage->height; j; j--) {
|
|
|
|
|
char *p = line;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-08-31 15:09:35 +00:00
|
|
|
for (i = line_bytes; i; i--) {
|
|
|
|
|
char b = *p;
|
|
|
|
|
b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
|
|
|
|
|
b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
|
|
|
|
|
b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
|
|
|
|
|
*p = b;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-08-31 15:09:35 +00:00
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
line += ximage->bytes_per_line;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_swap_ximage_to_native (XImage *ximage)
|
|
|
|
|
{
|
|
|
|
|
int unit_bytes = 0;
|
|
|
|
|
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
|
|
|
|
|
|
|
|
|
|
if (ximage->bits_per_pixel == 1 &&
|
2008-10-15 10:21:05 +01:00
|
|
|
ximage->bitmap_bit_order != native_byte_order)
|
|
|
|
|
{
|
2005-08-31 15:09:35 +00:00
|
|
|
_swap_ximage_bits (ximage);
|
|
|
|
|
if (ximage->bitmap_bit_order == ximage->byte_order)
|
|
|
|
|
return;
|
|
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-08-31 15:09:35 +00:00
|
|
|
if (ximage->byte_order == native_byte_order)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
switch (ximage->bits_per_pixel) {
|
|
|
|
|
case 1:
|
|
|
|
|
unit_bytes = ximage->bitmap_unit / 8;
|
|
|
|
|
break;
|
2008-10-15 10:21:05 +01:00
|
|
|
case 4:
|
|
|
|
|
_swap_ximage_nibbles (ximage);
|
|
|
|
|
/* fall-through */
|
2005-08-31 15:09:35 +00:00
|
|
|
case 8:
|
|
|
|
|
case 16:
|
2008-10-15 10:21:05 +01:00
|
|
|
case 20:
|
|
|
|
|
case 24:
|
|
|
|
|
case 28:
|
|
|
|
|
case 30:
|
2005-08-31 15:09:35 +00:00
|
|
|
case 32:
|
2008-10-15 10:21:05 +01:00
|
|
|
unit_bytes = (ximage->bits_per_pixel + 7) / 8;
|
2005-08-31 15:09:35 +00:00
|
|
|
break;
|
|
|
|
|
default:
|
2008-10-15 10:21:05 +01:00
|
|
|
/* This could be hit on some rare but possible cases. */
|
2005-08-31 15:09:35 +00:00
|
|
|
ASSERT_NOT_REACHED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (unit_bytes) {
|
|
|
|
|
case 1:
|
2008-10-15 10:21:05 +01:00
|
|
|
break;
|
2005-08-31 15:09:35 +00:00
|
|
|
case 2:
|
|
|
|
|
_swap_ximage_2bytes (ximage);
|
|
|
|
|
break;
|
2008-10-15 10:21:05 +01:00
|
|
|
case 3:
|
|
|
|
|
_swap_ximage_3bytes (ximage);
|
|
|
|
|
break;
|
2005-08-31 15:09:35 +00:00
|
|
|
case 4:
|
|
|
|
|
_swap_ximage_4bytes (ximage);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT_NOT_REACHED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-25 17:50:37 +04:30
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
/* Given a mask, (with a single sequence of contiguous 1 bits), return
|
|
|
|
|
* the number of 1 bits in 'width' and the number of 0 bits to its
|
|
|
|
|
* right in 'shift'. */
|
2008-03-25 17:50:37 +04:30
|
|
|
static void
|
2008-03-19 14:23:35 -07:00
|
|
|
_characterize_field (uint32_t mask, int *width, int *shift)
|
|
|
|
|
{
|
2008-03-25 16:32:24 -07:00
|
|
|
*width = _cairo_popcount (mask);
|
2008-03-19 14:23:35 -07:00
|
|
|
/* The final '& 31' is to force a 0 mask to result in 0 shift. */
|
2008-03-25 16:32:24 -07:00
|
|
|
*shift = _cairo_popcount ((mask - 1) & ~mask) & 31;
|
2008-03-19 14:23:35 -07:00
|
|
|
}
|
|
|
|
|
|
2008-03-25 17:50:37 +04:30
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
/* Convert a field of 'width' bits to 'new_width' bits with correct
|
|
|
|
|
* rounding. */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
_resize_field (uint32_t field, int width, int new_width)
|
|
|
|
|
{
|
|
|
|
|
if (width == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (width >= new_width) {
|
|
|
|
|
return field >> (width - new_width);
|
|
|
|
|
} else {
|
|
|
|
|
uint32_t result = field << (new_width - width);
|
|
|
|
|
|
|
|
|
|
while (width < new_width) {
|
|
|
|
|
result |= result >> width;
|
|
|
|
|
width <<= 1;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-25 17:50:37 +04:30
|
|
|
static inline uint32_t
|
|
|
|
|
_adjust_field (uint32_t field, int adjustment)
|
|
|
|
|
{
|
|
|
|
|
return MIN (255, MAX(0, (int)field + adjustment));
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
/* Given a shifted field value, (described by 'width' and 'shift),
|
|
|
|
|
* resize it 8-bits and return that value.
|
|
|
|
|
*
|
|
|
|
|
* Note that the original field value must not have any non-field bits
|
|
|
|
|
* set.
|
|
|
|
|
*/
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
_field_to_8 (uint32_t field, int width, int shift)
|
|
|
|
|
{
|
|
|
|
|
return _resize_field (field >> shift, width, 8);
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-25 17:50:37 +04:30
|
|
|
static inline uint32_t
|
|
|
|
|
_field_to_8_undither (uint32_t field, int width, int shift,
|
|
|
|
|
int dither_adjustment)
|
|
|
|
|
{
|
|
|
|
|
return _adjust_field (_field_to_8 (field, width, shift), - dither_adjustment>>width);
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
/* Given an 8-bit value, convert it to a field of 'width', shift it up
|
|
|
|
|
* to 'shift, and return it. */
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
_field_from_8 (uint32_t field, int width, int shift)
|
|
|
|
|
{
|
|
|
|
|
return _resize_field (field, 8, width) << shift;
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-25 17:50:37 +04:30
|
|
|
static inline uint32_t
|
|
|
|
|
_field_from_8_dither (uint32_t field, int width, int shift,
|
|
|
|
|
int8_t dither_adjustment)
|
|
|
|
|
{
|
|
|
|
|
return _field_from_8 (_adjust_field (field, dither_adjustment>>width), width, shift);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline uint32_t
|
|
|
|
|
_pseudocolor_from_rgb888_dither (cairo_xlib_visual_info_t *visual_info,
|
|
|
|
|
uint32_t r, uint32_t g, uint32_t b,
|
|
|
|
|
int8_t dither_adjustment)
|
|
|
|
|
{
|
|
|
|
|
if (r == g && g == b) {
|
|
|
|
|
dither_adjustment /= RAMP_SIZE;
|
|
|
|
|
return visual_info->gray8_to_pseudocolor[_adjust_field (r, dither_adjustment)];
|
|
|
|
|
} else {
|
|
|
|
|
dither_adjustment = visual_info->dither8_to_cube[dither_adjustment+128];
|
|
|
|
|
return visual_info->cube_to_pseudocolor[visual_info->field8_to_cube[_adjust_field (r, dither_adjustment)]]
|
|
|
|
|
[visual_info->field8_to_cube[_adjust_field (g, dither_adjustment)]]
|
|
|
|
|
[visual_info->field8_to_cube[_adjust_field (b, dither_adjustment)]];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline uint32_t
|
2008-06-19 22:24:13 -04:00
|
|
|
_pseudocolor_to_rgb888 (cairo_xlib_visual_info_t *visual_info,
|
|
|
|
|
uint32_t pixel)
|
2008-03-25 17:50:37 +04:30
|
|
|
{
|
|
|
|
|
uint32_t r, g, b;
|
|
|
|
|
pixel &= 0xff;
|
|
|
|
|
r = visual_info->colors[pixel].r;
|
|
|
|
|
g = visual_info->colors[pixel].g;
|
|
|
|
|
b = visual_info->colors[pixel].b;
|
2008-06-19 22:24:13 -04:00
|
|
|
return (r << 16) |
|
|
|
|
|
(g << 8) |
|
|
|
|
|
(b );
|
2008-03-25 17:50:37 +04:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* should range from -128 to 127 */
|
|
|
|
|
#define X 16
|
|
|
|
|
static const int8_t dither_pattern[4][4] = {
|
|
|
|
|
{-8*X, +0*X, -6*X, +2*X},
|
|
|
|
|
{+4*X, -4*X, +6*X, -2*X},
|
|
|
|
|
{-5*X, +4*X, -7*X, +1*X},
|
|
|
|
|
{+7*X, -1*X, +5*X, -3*X}
|
|
|
|
|
};
|
|
|
|
|
#undef X
|
|
|
|
|
|
|
|
|
|
|
2005-01-31 08:50:22 +00:00
|
|
|
static cairo_status_t
|
2006-05-04 03:43:34 -07:00
|
|
|
_get_image_surface (cairo_xlib_surface_t *surface,
|
2007-06-18 16:56:24 -07:00
|
|
|
cairo_rectangle_int_t *interest_rect,
|
2006-05-04 03:43:34 -07:00
|
|
|
cairo_image_surface_t **image_out,
|
2007-06-18 16:56:24 -07:00
|
|
|
cairo_rectangle_int_t *image_rect)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2008-01-27 10:31:58 -08:00
|
|
|
cairo_int_status_t status;
|
2008-03-25 17:50:37 +04:30
|
|
|
cairo_image_surface_t *image = NULL;
|
2003-10-31 10:41:37 +00:00
|
|
|
XImage *ximage;
|
2008-10-23 14:34:30 +01:00
|
|
|
cairo_rectangle_int_t extents;
|
2007-08-17 10:29:37 -07:00
|
|
|
pixman_format_code_t pixman_format;
|
2008-03-19 14:23:35 -07:00
|
|
|
cairo_format_masks_t xlib_masks;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2003-09-30 18:56:22 +00:00
|
|
|
|
2008-10-23 14:34:30 +01:00
|
|
|
extents.x = 0;
|
|
|
|
|
extents.y = 0;
|
|
|
|
|
extents.width = surface->width;
|
|
|
|
|
extents.height = surface->height;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
|
|
|
|
if (interest_rect) {
|
2008-10-23 14:34:30 +01:00
|
|
|
if (! _cairo_rectangle_intersect (&extents, interest_rect)) {
|
2005-01-31 08:50:22 +00:00
|
|
|
*image_out = NULL;
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
|
|
|
|
if (status)
|
|
|
|
|
return status;
|
|
|
|
|
|
2008-10-23 14:34:30 +01:00
|
|
|
if (image_rect)
|
|
|
|
|
*image_rect = extents;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2005-03-15 16:25:30 +00:00
|
|
|
/* XXX: This should try to use the XShm extension if available */
|
2005-05-13 17:54:43 +00:00
|
|
|
|
2005-05-17 06:05:13 +00:00
|
|
|
if (surface->use_pixmap == 0)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_error_func_t old_handler;
|
|
|
|
|
|
|
|
|
|
old_handler = XSetErrorHandler (_noop_error_handler);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
ximage = XGetImage (display->display,
|
2005-05-17 06:05:13 +00:00
|
|
|
surface->drawable,
|
2008-10-23 14:34:30 +01:00
|
|
|
extents.x, extents.y,
|
|
|
|
|
extents.width, extents.height,
|
2005-05-17 06:05:13 +00:00
|
|
|
AllPlanes, ZPixmap);
|
|
|
|
|
|
|
|
|
|
XSetErrorHandler (old_handler);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-05-17 06:05:13 +00:00
|
|
|
/* If we get an error, the surface must have been a window,
|
|
|
|
|
* so retry with the safe code path.
|
|
|
|
|
*/
|
|
|
|
|
if (!ximage)
|
|
|
|
|
surface->use_pixmap = CAIRO_ASSUME_PIXMAP;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
surface->use_pixmap--;
|
2005-08-22 20:43:23 +00:00
|
|
|
ximage = NULL;
|
2005-05-17 06:05:13 +00:00
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (ximage == NULL) {
|
2005-03-15 16:25:30 +00:00
|
|
|
/* XGetImage from a window is dangerous because it can
|
|
|
|
|
* produce errors if the window is unmapped or partially
|
|
|
|
|
* outside the screen. We could check for errors and
|
|
|
|
|
* retry, but to keep things simple, we just create a
|
|
|
|
|
* temporary pixmap
|
|
|
|
|
*/
|
2007-03-16 19:35:02 +00:00
|
|
|
Pixmap pixmap;
|
2009-09-02 00:34:37 +01:00
|
|
|
GC gc;
|
2008-10-29 15:46:10 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_get_gc (display, surface, &gc);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2010-04-18 23:20:02 +02:00
|
|
|
goto BAIL;
|
2007-03-16 19:35:02 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
pixmap = XCreatePixmap (display->display,
|
2008-08-27 21:14:51 -07:00
|
|
|
surface->drawable,
|
2008-10-23 14:34:30 +01:00
|
|
|
extents.width, extents.height,
|
2008-08-27 21:14:51 -07:00
|
|
|
surface->depth);
|
2007-03-16 19:35:02 +00:00
|
|
|
if (pixmap) {
|
2010-04-18 23:20:02 +02:00
|
|
|
XCopyArea (display->display, surface->drawable, pixmap, gc,
|
2008-10-23 14:34:30 +01:00
|
|
|
extents.x, extents.y,
|
|
|
|
|
extents.width, extents.height,
|
|
|
|
|
0, 0);
|
2005-03-15 16:25:30 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
ximage = XGetImage (display->display,
|
2007-03-16 19:35:02 +00:00
|
|
|
pixmap,
|
|
|
|
|
0, 0,
|
2008-10-23 14:34:30 +01:00
|
|
|
extents.width, extents.height,
|
2007-03-16 19:35:02 +00:00
|
|
|
AllPlanes, ZPixmap);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XFreePixmap (display->display, pixmap);
|
2007-03-16 19:35:02 +00:00
|
|
|
}
|
2009-06-18 14:32:53 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_put_gc (display, surface, gc);
|
2009-09-02 00:34:37 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
if (ximage == NULL) {
|
|
|
|
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
goto BAIL;
|
|
|
|
|
}
|
2005-03-15 16:25:30 +00:00
|
|
|
}
|
2005-08-31 15:09:35 +00:00
|
|
|
|
|
|
|
|
_swap_ximage_to_native (ximage);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
xlib_masks.bpp = ximage->bits_per_pixel;
|
|
|
|
|
xlib_masks.alpha_mask = surface->a_mask;
|
|
|
|
|
xlib_masks.red_mask = surface->r_mask;
|
|
|
|
|
xlib_masks.green_mask = surface->g_mask;
|
|
|
|
|
xlib_masks.blue_mask = surface->b_mask;
|
|
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
/* We can't use pixman to simply write to image if:
|
|
|
|
|
* (a) the pixels are not appropriately aligned,
|
|
|
|
|
* (b) pixman does not the pixel format, or
|
|
|
|
|
* (c) if the image is palettized and we need to convert.
|
|
|
|
|
*/
|
|
|
|
|
if (ximage->bitmap_unit == 32 && ximage->bitmap_pad == 32 &&
|
|
|
|
|
_pixman_format_from_masks (&xlib_masks, &pixman_format) &&
|
|
|
|
|
(surface->visual == NULL || surface->visual->class == TrueColor))
|
2008-10-15 10:21:05 +01:00
|
|
|
{
|
2008-03-19 14:23:35 -07:00
|
|
|
image = (cairo_image_surface_t*)
|
|
|
|
|
_cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
|
|
|
|
|
pixman_format,
|
|
|
|
|
ximage->width,
|
|
|
|
|
ximage->height,
|
|
|
|
|
ximage->bytes_per_line);
|
|
|
|
|
status = image->base.status;
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-03-25 17:50:37 +04:30
|
|
|
goto BAIL;
|
2005-05-17 06:05:13 +00:00
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
/* Let the surface take ownership of the data */
|
|
|
|
|
_cairo_image_surface_assume_ownership_of_data (image);
|
|
|
|
|
ximage->data = NULL;
|
|
|
|
|
} else {
|
2008-03-25 17:50:37 +04:30
|
|
|
/* The visual we are dealing with is not supported by the
|
|
|
|
|
* standard pixman formats. So we must first convert the data
|
|
|
|
|
* to a supported format. */
|
|
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
cairo_format_t format;
|
|
|
|
|
unsigned char *data;
|
|
|
|
|
uint32_t *row;
|
|
|
|
|
uint32_t in_pixel, out_pixel;
|
|
|
|
|
unsigned int rowstride;
|
2008-04-01 14:53:55 -07:00
|
|
|
uint32_t a_mask=0, r_mask=0, g_mask=0, b_mask=0;
|
|
|
|
|
int a_width=0, r_width=0, g_width=0, b_width=0;
|
|
|
|
|
int a_shift=0, r_shift=0, g_shift=0, b_shift=0;
|
2008-03-25 17:50:37 +04:30
|
|
|
int x, y, x0, y0, x_off, y_off;
|
2009-08-16 14:20:35 +01:00
|
|
|
cairo_xlib_visual_info_t *visual_info = NULL;
|
2008-03-19 14:23:35 -07:00
|
|
|
|
2008-06-13 21:39:19 -04:00
|
|
|
if (surface->visual == NULL || surface->visual->class == TrueColor) {
|
2008-03-19 13:00:47 -07:00
|
|
|
cairo_bool_t has_alpha;
|
2008-03-25 17:50:37 +04:30
|
|
|
cairo_bool_t has_color;
|
2008-03-19 13:00:47 -07:00
|
|
|
|
2008-03-25 17:50:37 +04:30
|
|
|
has_alpha = surface->a_mask;
|
2008-03-19 13:00:47 -07:00
|
|
|
has_color = (surface->r_mask ||
|
|
|
|
|
surface->g_mask ||
|
|
|
|
|
surface->b_mask);
|
|
|
|
|
|
|
|
|
|
if (has_color) {
|
|
|
|
|
if (has_alpha) {
|
|
|
|
|
format = CAIRO_FORMAT_ARGB32;
|
|
|
|
|
} else {
|
|
|
|
|
format = CAIRO_FORMAT_RGB24;
|
|
|
|
|
}
|
2008-03-19 14:23:35 -07:00
|
|
|
} else {
|
|
|
|
|
/* XXX: Using CAIRO_FORMAT_A8 here would be more
|
|
|
|
|
* efficient, but would require slightly different code in
|
|
|
|
|
* the image conversion to put the alpha channel values
|
|
|
|
|
* into the right place. */
|
|
|
|
|
format = CAIRO_FORMAT_ARGB32;
|
|
|
|
|
}
|
2008-03-19 13:00:47 -07:00
|
|
|
|
|
|
|
|
a_mask = surface->a_mask;
|
|
|
|
|
r_mask = surface->r_mask;
|
|
|
|
|
g_mask = surface->g_mask;
|
|
|
|
|
b_mask = surface->b_mask;
|
|
|
|
|
|
|
|
|
|
_characterize_field (a_mask, &a_width, &a_shift);
|
|
|
|
|
_characterize_field (r_mask, &r_width, &r_shift);
|
|
|
|
|
_characterize_field (g_mask, &g_width, &g_shift);
|
|
|
|
|
_characterize_field (b_mask, &b_width, &b_shift);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
format = CAIRO_FORMAT_RGB24;
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_screen_get_visual_info (display,
|
|
|
|
|
surface->screen,
|
2008-03-31 21:49:34 +01:00
|
|
|
surface->visual,
|
|
|
|
|
&visual_info);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-03-25 17:50:37 +04:30
|
|
|
goto BAIL;
|
2008-03-19 14:23:35 -07:00
|
|
|
}
|
2008-01-27 10:31:58 -08:00
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
image = (cairo_image_surface_t *) cairo_image_surface_create
|
|
|
|
|
(format, ximage->width, ximage->height);
|
|
|
|
|
status = image->base.status;
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-03-25 17:50:37 +04:30
|
|
|
goto BAIL;
|
2008-01-27 10:31:58 -08:00
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
data = cairo_image_surface_get_data (&image->base);
|
|
|
|
|
rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
|
|
|
|
|
row = (uint32_t *) data;
|
2008-10-23 14:34:30 +01:00
|
|
|
x0 = extents.x + surface->base.device_transform.x0;
|
|
|
|
|
y0 = extents.y + surface->base.device_transform.y0;
|
2008-03-25 17:50:37 +04:30
|
|
|
for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
|
|
|
|
|
y < ximage->height;
|
|
|
|
|
y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) {
|
|
|
|
|
const int8_t *dither_row = dither_pattern[y_off];
|
|
|
|
|
for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
|
|
|
|
|
x < ximage->width;
|
|
|
|
|
x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0])) {
|
|
|
|
|
int dither_adjustment = dither_row[x_off];
|
|
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
in_pixel = XGetPixel (ximage, x, y);
|
2009-08-16 14:20:35 +01:00
|
|
|
if (visual_info == NULL) {
|
2008-03-19 13:00:47 -07:00
|
|
|
out_pixel = (
|
|
|
|
|
_field_to_8 (in_pixel & a_mask, a_width, a_shift) << 24 |
|
2008-03-25 17:50:37 +04:30
|
|
|
_field_to_8_undither (in_pixel & r_mask, r_width, r_shift, dither_adjustment) << 16 |
|
|
|
|
|
_field_to_8_undither (in_pixel & g_mask, g_width, g_shift, dither_adjustment) << 8 |
|
|
|
|
|
_field_to_8_undither (in_pixel & b_mask, b_width, b_shift, dither_adjustment));
|
2008-03-19 13:00:47 -07:00
|
|
|
} else {
|
2008-06-19 22:24:13 -04:00
|
|
|
/* Undithering pseudocolor does not look better */
|
|
|
|
|
out_pixel = _pseudocolor_to_rgb888 (visual_info, in_pixel);
|
2008-03-19 13:00:47 -07:00
|
|
|
}
|
2008-03-19 14:23:35 -07:00
|
|
|
row[x] = out_pixel;
|
|
|
|
|
}
|
|
|
|
|
row += rowstride;
|
|
|
|
|
}
|
2009-11-29 15:56:26 +02:00
|
|
|
cairo_surface_mark_dirty (&image->base);
|
2008-02-29 11:16:39 +00:00
|
|
|
}
|
2003-09-30 18:56:22 +00:00
|
|
|
|
2008-03-25 17:50:37 +04:30
|
|
|
BAIL:
|
2010-04-18 23:20:02 +02:00
|
|
|
if (ximage)
|
|
|
|
|
XDestroyImage (ximage);
|
|
|
|
|
|
|
|
|
|
cairo_device_release (&display->base);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status)) {
|
2008-03-25 17:50:37 +04:30
|
|
|
if (image) {
|
|
|
|
|
cairo_surface_destroy (&image->base);
|
|
|
|
|
image = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-01-31 08:50:22 +00:00
|
|
|
*image_out = image;
|
2008-03-25 17:50:37 +04:30
|
|
|
return status;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2005-05-26 11:35:44 +00:00
|
|
|
static void
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_ensure_src_picture (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *surface)
|
2005-05-26 11:35:44 +00:00
|
|
|
{
|
2009-06-30 22:04:01 +01:00
|
|
|
if (!surface->src_picture) {
|
2007-06-13 18:59:22 -04:00
|
|
|
XRenderPictureAttributes pa;
|
|
|
|
|
int mask = 0;
|
|
|
|
|
|
|
|
|
|
pa.subwindow_mode = IncludeInferiors;
|
|
|
|
|
mask |= CPSubwindowMode;
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
surface->src_picture = XRenderCreatePicture (display->display,
|
2006-06-06 15:41:31 -07:00
|
|
|
surface->drawable,
|
2006-05-18 15:20:25 -07:00
|
|
|
surface->xrender_format,
|
2007-06-13 18:59:22 -04:00
|
|
|
mask, &pa);
|
|
|
|
|
}
|
2005-05-26 11:35:44 +00:00
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-06-20 15:48:46 +00:00
|
|
|
static void
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *surface)
|
2005-06-20 15:48:46 +00:00
|
|
|
{
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (surface->clip_region != NULL) {
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderSetPictureClipRectangles (display->display, surface->dst_picture,
|
2005-06-20 15:48:46 +00:00
|
|
|
0, 0,
|
|
|
|
|
surface->clip_rects,
|
|
|
|
|
surface->num_clip_rects);
|
2007-05-01 18:34:47 +01:00
|
|
|
} else {
|
|
|
|
|
XRenderPictureAttributes pa;
|
|
|
|
|
pa.clip_mask = None;
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderChangePicture (display->display, surface->dst_picture,
|
2007-05-01 18:34:47 +01:00
|
|
|
CPClipMask, &pa);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
surface->clip_dirty &= ~CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE;
|
2005-06-20 15:48:46 +00:00
|
|
|
}
|
|
|
|
|
|
2010-06-11 11:16:42 +01:00
|
|
|
static void
|
|
|
|
|
_cairo_xlib_surface_set_precision (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *surface,
|
|
|
|
|
cairo_antialias_t antialias)
|
|
|
|
|
{
|
|
|
|
|
int precision;
|
|
|
|
|
|
|
|
|
|
switch (antialias) {
|
|
|
|
|
case CAIRO_ANTIALIAS_DEFAULT:
|
|
|
|
|
case CAIRO_ANTIALIAS_GRAY:
|
|
|
|
|
precision = PolyModeImprecise;
|
|
|
|
|
break;
|
2010-06-19 11:15:13 +01:00
|
|
|
case CAIRO_ANTIALIAS_NONE:
|
|
|
|
|
case CAIRO_ANTIALIAS_SUBPIXEL:
|
|
|
|
|
precision = PolyModePrecise;
|
|
|
|
|
break;
|
2010-06-11 11:16:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (surface->precision != precision) {
|
|
|
|
|
XRenderPictureAttributes pa;
|
|
|
|
|
|
|
|
|
|
pa.poly_mode = precision;
|
|
|
|
|
XRenderChangePicture (display->display, surface->dst_picture,
|
|
|
|
|
CPPolyMode, &pa);
|
|
|
|
|
|
|
|
|
|
surface->precision = precision;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-26 11:35:44 +00:00
|
|
|
static void
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *surface)
|
2005-05-26 11:35:44 +00:00
|
|
|
{
|
2005-06-20 15:48:46 +00:00
|
|
|
if (!surface->dst_picture) {
|
2010-04-18 23:20:02 +02:00
|
|
|
surface->dst_picture = XRenderCreatePicture (display->display,
|
2006-06-06 15:41:31 -07:00
|
|
|
surface->drawable,
|
2006-05-18 15:20:25 -07:00
|
|
|
surface->xrender_format,
|
2005-05-26 11:35:44 +00:00
|
|
|
0, NULL);
|
2008-10-28 17:38:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE)
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_set_picture_clip_rects (display, surface);
|
2009-06-18 14:32:53 +01:00
|
|
|
}
|
|
|
|
|
|
2003-10-31 10:41:37 +00:00
|
|
|
static cairo_status_t
|
2005-01-31 08:50:22 +00:00
|
|
|
_draw_image_surface (cairo_xlib_surface_t *surface,
|
|
|
|
|
cairo_image_surface_t *image,
|
2006-10-18 17:06:23 -07:00
|
|
|
int src_x,
|
|
|
|
|
int src_y,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
2005-01-31 08:50:22 +00:00
|
|
|
int dst_x,
|
|
|
|
|
int dst_y)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2005-08-31 15:09:35 +00:00
|
|
|
XImage ximage;
|
2008-03-14 16:48:41 +01:00
|
|
|
cairo_format_masks_t image_masks;
|
2005-08-31 15:09:35 +00:00
|
|
|
int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst;
|
2009-09-24 23:42:05 +02:00
|
|
|
pixman_image_t *pixman_image = NULL;
|
2007-03-16 19:35:02 +00:00
|
|
|
cairo_status_t status;
|
2008-03-19 14:23:35 -07:00
|
|
|
cairo_bool_t own_data;
|
2009-09-02 00:34:37 +01:00
|
|
|
GC gc;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-08-31 15:09:35 +00:00
|
|
|
ximage.width = image->width;
|
|
|
|
|
ximage.height = image->height;
|
|
|
|
|
ximage.format = ZPixmap;
|
|
|
|
|
ximage.byte_order = native_byte_order;
|
|
|
|
|
ximage.bitmap_unit = 32; /* always for libpixman */
|
|
|
|
|
ximage.bitmap_bit_order = native_byte_order;
|
|
|
|
|
ximage.bitmap_pad = 32; /* always for libpixman */
|
2008-03-19 14:23:35 -07:00
|
|
|
ximage.depth = surface->depth;
|
|
|
|
|
ximage.red_mask = surface->r_mask;
|
|
|
|
|
ximage.green_mask = surface->g_mask;
|
|
|
|
|
ximage.blue_mask = surface->b_mask;
|
2005-10-06 11:32:54 +00:00
|
|
|
ximage.xoffset = 0;
|
2005-08-31 15:09:35 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
2009-09-24 23:42:05 +02:00
|
|
|
if (!_pixman_format_to_masks (image->pixman_format, &image_masks))
|
|
|
|
|
{
|
|
|
|
|
pixman_format_code_t intermediate_format;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
image_masks.alpha_mask = surface->a_mask;
|
|
|
|
|
image_masks.red_mask = surface->r_mask;
|
|
|
|
|
image_masks.green_mask = surface->g_mask;
|
|
|
|
|
image_masks.blue_mask = surface->b_mask;
|
2009-09-29 00:23:12 +02:00
|
|
|
image_masks.bpp = surface->depth;
|
2009-09-24 23:42:05 +02:00
|
|
|
ret = _pixman_format_from_masks (&image_masks, &intermediate_format);
|
|
|
|
|
assert (ret);
|
|
|
|
|
|
2010-05-16 23:58:47 +02:00
|
|
|
own_data = FALSE;
|
|
|
|
|
|
2009-09-24 23:42:05 +02:00
|
|
|
pixman_image = pixman_image_create_bits (intermediate_format,
|
|
|
|
|
image->width,
|
|
|
|
|
image->height,
|
|
|
|
|
NULL,
|
|
|
|
|
0);
|
2010-04-18 23:20:02 +02:00
|
|
|
if (pixman_image == NULL) {
|
|
|
|
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
goto BAIL;
|
|
|
|
|
}
|
2009-09-24 23:42:05 +02:00
|
|
|
|
2010-01-27 10:56:22 +01:00
|
|
|
pixman_image_composite32 (PIXMAN_OP_SRC,
|
|
|
|
|
image->pixman_image,
|
|
|
|
|
NULL,
|
|
|
|
|
pixman_image,
|
|
|
|
|
0, 0,
|
|
|
|
|
0, 0,
|
|
|
|
|
0, 0,
|
|
|
|
|
image->width, image->height);
|
2009-09-24 23:42:05 +02:00
|
|
|
|
|
|
|
|
ximage.bits_per_pixel = image_masks.bpp;
|
|
|
|
|
ximage.data = (char *) pixman_image_get_data (pixman_image);
|
|
|
|
|
ximage.bytes_per_line = pixman_image_get_stride (pixman_image);
|
|
|
|
|
|
|
|
|
|
ret = XInitImage (&ximage);
|
|
|
|
|
assert (ret != 0);
|
|
|
|
|
}
|
|
|
|
|
else if ((image_masks.alpha_mask == surface->a_mask || surface->a_mask == 0) &&
|
|
|
|
|
(image_masks.red_mask == surface->r_mask || surface->r_mask == 0) &&
|
|
|
|
|
(image_masks.green_mask == surface->g_mask || surface->g_mask == 0) &&
|
|
|
|
|
(image_masks.blue_mask == surface->b_mask || surface->b_mask == 0))
|
2008-03-19 14:23:35 -07:00
|
|
|
{
|
2008-08-10 08:31:19 +01:00
|
|
|
int ret;
|
|
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
ximage.bits_per_pixel = image_masks.bpp;
|
|
|
|
|
ximage.bytes_per_line = image->stride;
|
|
|
|
|
ximage.data = (char *)image->data;
|
|
|
|
|
own_data = FALSE;
|
2008-08-10 08:31:19 +01:00
|
|
|
|
|
|
|
|
ret = XInitImage (&ximage);
|
|
|
|
|
assert (ret != 0);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2008-03-19 14:23:35 -07:00
|
|
|
unsigned int stride, rowstride;
|
2008-03-25 17:50:37 +04:30
|
|
|
int x, y, x0, y0, x_off, y_off;
|
2008-03-19 14:23:35 -07:00
|
|
|
uint32_t in_pixel, out_pixel, *row;
|
2008-06-13 02:35:30 -04:00
|
|
|
int i_a_width=0, i_r_width=0, i_g_width=0, i_b_width=0;
|
|
|
|
|
int i_a_shift=0, i_r_shift=0, i_g_shift=0, i_b_shift=0;
|
|
|
|
|
int o_a_width=0, o_r_width=0, o_g_width=0, o_b_width=0;
|
|
|
|
|
int o_a_shift=0, o_r_shift=0, o_g_shift=0, o_b_shift=0;
|
2008-03-25 17:50:37 +04:30
|
|
|
cairo_xlib_visual_info_t *visual_info = NULL;
|
2008-08-10 08:31:19 +01:00
|
|
|
cairo_bool_t true_color;
|
|
|
|
|
int ret;
|
2008-03-19 14:23:35 -07:00
|
|
|
|
2009-09-20 18:46:19 +01:00
|
|
|
if (surface->depth > 16)
|
2008-03-19 14:23:35 -07:00
|
|
|
ximage.bits_per_pixel = 32;
|
2009-09-20 18:46:19 +01:00
|
|
|
else if (surface->depth > 8)
|
2008-03-19 14:23:35 -07:00
|
|
|
ximage.bits_per_pixel = 16;
|
2009-09-20 18:46:19 +01:00
|
|
|
else if (surface->depth > 1)
|
2008-03-19 14:23:35 -07:00
|
|
|
ximage.bits_per_pixel = 8;
|
2009-09-20 18:46:19 +01:00
|
|
|
else
|
2008-03-19 14:23:35 -07:00
|
|
|
ximage.bits_per_pixel = 1;
|
|
|
|
|
stride = CAIRO_STRIDE_FOR_WIDTH_BPP (ximage.width,
|
|
|
|
|
ximage.bits_per_pixel);
|
|
|
|
|
ximage.bytes_per_line = stride;
|
2008-03-31 21:49:34 +01:00
|
|
|
ximage.data = _cairo_malloc_ab (stride, ximage.height);
|
2010-04-18 23:20:02 +02:00
|
|
|
if (unlikely (ximage.data == NULL)) {
|
2010-05-16 23:58:47 +02:00
|
|
|
own_data = FALSE;
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
goto BAIL;
|
|
|
|
|
}
|
2008-03-31 21:49:34 +01:00
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
own_data = TRUE;
|
|
|
|
|
|
2008-08-10 08:31:19 +01:00
|
|
|
ret = XInitImage (&ximage);
|
|
|
|
|
assert (ret != 0);
|
2008-03-19 14:23:35 -07:00
|
|
|
|
2008-06-13 02:35:30 -04:00
|
|
|
_characterize_field (image_masks.alpha_mask, &i_a_width, &i_a_shift);
|
|
|
|
|
_characterize_field (image_masks.red_mask , &i_r_width, &i_r_shift);
|
|
|
|
|
_characterize_field (image_masks.green_mask, &i_g_width, &i_g_shift);
|
|
|
|
|
_characterize_field (image_masks.blue_mask , &i_b_width, &i_b_shift);
|
|
|
|
|
|
2008-08-10 08:31:19 +01:00
|
|
|
true_color = surface->visual == NULL ||
|
|
|
|
|
surface->visual->class == TrueColor;
|
|
|
|
|
if (true_color) {
|
2008-06-13 02:35:30 -04:00
|
|
|
_characterize_field (surface->a_mask, &o_a_width, &o_a_shift);
|
|
|
|
|
_characterize_field (surface->r_mask, &o_r_width, &o_r_shift);
|
|
|
|
|
_characterize_field (surface->g_mask, &o_g_width, &o_g_shift);
|
|
|
|
|
_characterize_field (surface->b_mask, &o_b_width, &o_b_shift);
|
2008-03-19 13:00:47 -07:00
|
|
|
} else {
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_screen_get_visual_info (display,
|
|
|
|
|
surface->screen,
|
2008-03-31 21:49:34 +01:00
|
|
|
surface->visual,
|
|
|
|
|
&visual_info);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-03-31 21:49:34 +01:00
|
|
|
goto BAIL;
|
2008-03-19 13:00:47 -07:00
|
|
|
}
|
2008-03-19 14:23:35 -07:00
|
|
|
|
2009-05-05 18:37:25 +01:00
|
|
|
rowstride = image->stride >> 2;
|
|
|
|
|
row = (uint32_t *) image->data;
|
2008-03-25 17:50:37 +04:30
|
|
|
x0 = dst_x + surface->base.device_transform.x0;
|
|
|
|
|
y0 = dst_y + surface->base.device_transform.y0;
|
|
|
|
|
for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
|
|
|
|
|
y < ximage.height;
|
2008-08-10 08:31:19 +01:00
|
|
|
y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern))
|
|
|
|
|
{
|
2008-03-25 17:50:37 +04:30
|
|
|
const int8_t *dither_row = dither_pattern[y_off];
|
2008-08-10 08:31:19 +01:00
|
|
|
|
2008-03-25 17:50:37 +04:30
|
|
|
for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
|
|
|
|
|
x < ximage.width;
|
2008-08-10 08:31:19 +01:00
|
|
|
x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0]))
|
|
|
|
|
{
|
2008-03-25 17:50:37 +04:30
|
|
|
int dither_adjustment = dither_row[x_off];
|
2008-03-19 14:23:35 -07:00
|
|
|
int a, r, g, b;
|
2008-03-25 17:50:37 +04:30
|
|
|
|
2010-03-02 13:57:02 +00:00
|
|
|
if (image_masks.bpp == 1)
|
|
|
|
|
in_pixel = !! (((uint8_t*)row)[x/8] & (1 << (x & 7)));
|
|
|
|
|
else if (image_masks.bpp <= 8)
|
2008-06-13 02:35:30 -04:00
|
|
|
in_pixel = ((uint8_t*)row)[x];
|
|
|
|
|
else if (image_masks.bpp <= 16)
|
|
|
|
|
in_pixel = ((uint16_t*)row)[x];
|
2009-09-28 23:52:14 +02:00
|
|
|
else if (image_masks.bpp <= 24)
|
|
|
|
|
#ifdef WORDS_BIGENDIAN
|
|
|
|
|
in_pixel = ((uint8_t*)row)[3 * x] << 16 |
|
|
|
|
|
((uint8_t*)row)[3 * x + 1] << 8 |
|
|
|
|
|
((uint8_t*)row)[3 * x + 2];
|
|
|
|
|
#else
|
|
|
|
|
in_pixel = ((uint8_t*)row)[3 * x] |
|
|
|
|
|
((uint8_t*)row)[3 * x + 1] << 8 |
|
|
|
|
|
((uint8_t*)row)[3 * x + 2] << 16;
|
|
|
|
|
#endif
|
2008-06-13 02:35:30 -04:00
|
|
|
else
|
|
|
|
|
in_pixel = row[x];
|
2008-08-10 08:31:19 +01:00
|
|
|
|
2008-10-30 09:54:47 +00:00
|
|
|
/* If the incoming image has no alpha channel, then the input
|
|
|
|
|
* is opaque and the output should have the maximum alpha value.
|
|
|
|
|
* For all other channels, their absence implies 0.
|
|
|
|
|
*/
|
|
|
|
|
if (image_masks.alpha_mask == 0x0)
|
|
|
|
|
a = 0xff;
|
|
|
|
|
else
|
|
|
|
|
a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
|
2008-06-13 02:35:30 -04:00
|
|
|
r = _field_to_8 (in_pixel & image_masks.red_mask , i_r_width, i_r_shift);
|
|
|
|
|
g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
|
|
|
|
|
b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
|
2008-08-10 08:31:19 +01:00
|
|
|
|
|
|
|
|
if (true_color) {
|
|
|
|
|
out_pixel = _field_from_8 (a, o_a_width, o_a_shift) |
|
|
|
|
|
_field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
|
|
|
|
|
_field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
|
|
|
|
|
_field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment);
|
2008-03-25 17:50:37 +04:30
|
|
|
} else {
|
|
|
|
|
out_pixel = _pseudocolor_from_rgb888_dither (visual_info, r, g, b, dither_adjustment);
|
|
|
|
|
}
|
2008-08-10 08:31:19 +01:00
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
XPutPixel (&ximage, x, y, out_pixel);
|
|
|
|
|
}
|
2008-08-10 08:31:19 +01:00
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
row += rowstride;
|
|
|
|
|
}
|
|
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_get_gc (display, surface, &gc);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-03-31 21:49:34 +01:00
|
|
|
goto BAIL;
|
2008-03-19 14:23:35 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XPutImage (display->display, surface->drawable, gc,
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
&ximage, src_x, src_y, dst_x, dst_y,
|
|
|
|
|
width, height);
|
2003-10-31 10:41:37 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_put_gc (display, surface, gc);
|
2009-06-18 14:32:53 +01:00
|
|
|
|
2008-03-31 21:49:34 +01:00
|
|
|
BAIL:
|
2010-04-18 23:20:02 +02:00
|
|
|
|
|
|
|
|
cairo_device_release (&display->base);
|
|
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
if (own_data)
|
|
|
|
|
free (ximage.data);
|
2009-09-24 23:42:05 +02:00
|
|
|
if (pixman_image)
|
|
|
|
|
pixman_image_unref (pixman_image);
|
2005-01-31 08:50:22 +00:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2005-01-31 08:50:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_xlib_surface_acquire_source_image (void *abstract_surface,
|
|
|
|
|
cairo_image_surface_t **image_out,
|
|
|
|
|
void **image_extra)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
cairo_image_surface_t *image;
|
|
|
|
|
cairo_status_t status;
|
|
|
|
|
|
|
|
|
|
status = _get_image_surface (surface, NULL, &image, NULL);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2005-06-10 12:46:49 +00:00
|
|
|
return status;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2005-06-10 12:46:49 +00:00
|
|
|
*image_out = image;
|
2005-07-28 09:54:03 +00:00
|
|
|
*image_extra = NULL;
|
2005-06-10 12:46:49 +00:00
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2005-01-31 08:50:22 +00:00
|
|
|
}
|
|
|
|
|
|
2008-11-25 20:15:15 +01:00
|
|
|
static cairo_surface_t *
|
|
|
|
|
_cairo_xlib_surface_snapshot (void *abstract_surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
cairo_image_surface_t *image;
|
|
|
|
|
cairo_status_t status;
|
|
|
|
|
|
|
|
|
|
status = _get_image_surface (surface, NULL, &image, NULL);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return _cairo_surface_create_in_error (status);
|
|
|
|
|
|
|
|
|
|
return &image->base;
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-31 08:50:22 +00:00
|
|
|
static void
|
|
|
|
|
_cairo_xlib_surface_release_source_image (void *abstract_surface,
|
|
|
|
|
cairo_image_surface_t *image,
|
|
|
|
|
void *image_extra)
|
|
|
|
|
{
|
|
|
|
|
cairo_surface_destroy (&image->base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_xlib_surface_acquire_dest_image (void *abstract_surface,
|
2007-06-18 16:56:24 -07:00
|
|
|
cairo_rectangle_int_t *interest_rect,
|
2005-01-31 08:50:22 +00:00
|
|
|
cairo_image_surface_t **image_out,
|
2007-06-18 16:56:24 -07:00
|
|
|
cairo_rectangle_int_t *image_rect_out,
|
2005-01-31 08:50:22 +00:00
|
|
|
void **image_extra)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
cairo_image_surface_t *image;
|
|
|
|
|
cairo_status_t status;
|
|
|
|
|
|
|
|
|
|
status = _get_image_surface (surface, interest_rect, &image, image_rect_out);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2005-06-10 12:46:49 +00:00
|
|
|
return status;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2005-06-10 12:46:49 +00:00
|
|
|
*image_out = image;
|
2005-07-28 09:54:03 +00:00
|
|
|
*image_extra = NULL;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-06-10 12:46:49 +00:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2005-01-31 08:50:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2006-05-04 03:43:34 -07:00
|
|
|
_cairo_xlib_surface_release_dest_image (void *abstract_surface,
|
2007-06-18 16:56:24 -07:00
|
|
|
cairo_rectangle_int_t *interest_rect,
|
2006-05-04 03:43:34 -07:00
|
|
|
cairo_image_surface_t *image,
|
2007-06-18 16:56:24 -07:00
|
|
|
cairo_rectangle_int_t *image_rect,
|
2006-05-04 03:43:34 -07:00
|
|
|
void *image_extra)
|
2005-01-31 08:50:22 +00:00
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
2007-10-09 12:49:08 +01:00
|
|
|
cairo_status_t status;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2007-10-09 12:49:08 +01:00
|
|
|
status = _draw_image_surface (surface, image,
|
|
|
|
|
0, 0, image->width, image->height,
|
|
|
|
|
image_rect->x, image_rect->y);
|
|
|
|
|
status = _cairo_surface_set_error (&surface->base, status);
|
2005-01-31 08:50:22 +00:00
|
|
|
|
|
|
|
|
cairo_surface_destroy (&image->base);
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
/*
|
|
|
|
|
* Return whether two xlib surfaces share the same
|
|
|
|
|
* screen. Both core and Render drawing require this
|
|
|
|
|
* when using multiple drawables in an operation.
|
|
|
|
|
*/
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
static inline cairo_bool_t
|
2005-07-20 18:52:31 +00:00
|
|
|
_cairo_xlib_surface_same_screen (cairo_xlib_surface_t *dst,
|
|
|
|
|
cairo_xlib_surface_t *src)
|
|
|
|
|
{
|
2009-09-01 23:12:43 +01:00
|
|
|
return dst->screen == src->screen;
|
2005-07-20 18:52:31 +00:00
|
|
|
}
|
|
|
|
|
|
2005-01-31 08:50:22 +00:00
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_xlib_surface_clone_similar (void *abstract_surface,
|
|
|
|
|
cairo_surface_t *src,
|
2006-10-18 17:06:23 -07:00
|
|
|
int src_x,
|
|
|
|
|
int src_y,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
2008-09-27 17:24:57 +01:00
|
|
|
int *clone_offset_x,
|
|
|
|
|
int *clone_offset_y,
|
2005-01-31 08:50:22 +00:00
|
|
|
cairo_surface_t **clone_out)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
cairo_xlib_surface_t *clone;
|
2007-04-08 23:09:31 +01:00
|
|
|
cairo_status_t status;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
|
|
|
|
if (src->backend == surface->base.backend ) {
|
|
|
|
|
cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src;
|
|
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
if (_cairo_xlib_surface_same_screen (surface, xlib_src)) {
|
2008-09-27 17:24:57 +01:00
|
|
|
*clone_offset_x = 0;
|
|
|
|
|
*clone_offset_y = 0;
|
2005-08-04 18:44:29 +00:00
|
|
|
*clone_out = cairo_surface_reference (src);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-01-31 08:50:22 +00:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
} else if (_cairo_surface_is_image (src)) {
|
|
|
|
|
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
|
2006-08-04 16:06:59 -07:00
|
|
|
|
2008-09-27 00:18:07 +01:00
|
|
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("roi too large for xlib");
|
2008-08-28 23:58:29 -07:00
|
|
|
|
2005-01-31 08:50:22 +00:00
|
|
|
clone = (cairo_xlib_surface_t *)
|
2009-09-20 18:46:19 +01:00
|
|
|
_cairo_xlib_surface_create_similar (surface,
|
2009-10-16 10:11:41 +01:00
|
|
|
image_src->base.content,
|
2009-09-20 18:46:19 +01:00
|
|
|
width, height);
|
2008-04-07 23:06:18 +01:00
|
|
|
if (clone == NULL)
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("unhandled image format, no similar surface");
|
2008-04-07 23:06:18 +01:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (unlikely (clone->base.status))
|
2007-10-04 13:15:46 +01:00
|
|
|
return clone->base.status;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2008-09-27 00:18:07 +01:00
|
|
|
status = _draw_image_surface (clone, image_src,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
width, height,
|
|
|
|
|
0, 0);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status)) {
|
2007-04-08 23:09:31 +01:00
|
|
|
cairo_surface_destroy (&clone->base);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2008-09-27 17:24:57 +01:00
|
|
|
*clone_offset_x = src_x;
|
|
|
|
|
*clone_offset_y = src_y;
|
2005-01-31 08:50:22 +00:00
|
|
|
*clone_out = &clone->base;
|
|
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-01-31 08:50:22 +00:00
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2008-06-13 21:37:45 -04:00
|
|
|
static cairo_surface_t *
|
|
|
|
|
_cairo_xlib_surface_create_solid_pattern_surface (void *abstract_surface,
|
2008-10-22 19:24:44 +01:00
|
|
|
const cairo_solid_pattern_t *solid_pattern)
|
2008-06-13 21:37:45 -04:00
|
|
|
{
|
|
|
|
|
/* This function's only responsibility is to create a proper surface
|
|
|
|
|
* for when XRender is not available. The proper surface is a xlib
|
|
|
|
|
* surface (as opposed to image surface which is what create_similar
|
|
|
|
|
* returns in those cases) and the size of the dithering pattern, not
|
|
|
|
|
* 1x1. This surface can then be used in
|
|
|
|
|
* _cairo_xlib_surface_solid_fill_rectangles() to do dithered "solid"
|
|
|
|
|
* fills using core protocol */
|
|
|
|
|
|
|
|
|
|
cairo_xlib_surface_t *other = abstract_surface;
|
|
|
|
|
cairo_image_surface_t *image;
|
|
|
|
|
cairo_xlib_surface_t *surface = NULL;
|
|
|
|
|
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2008-06-13 21:37:45 -04:00
|
|
|
|
2008-08-27 21:14:51 -07:00
|
|
|
int width = ARRAY_LENGTH (dither_pattern[0]);
|
|
|
|
|
int height = ARRAY_LENGTH (dither_pattern);
|
|
|
|
|
|
|
|
|
|
Pixmap pixmap = None;
|
2008-06-13 21:37:45 -04:00
|
|
|
|
|
|
|
|
if (CAIRO_SURFACE_RENDER_HAS_COMPOSITE (other))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
image = (cairo_image_surface_t *)
|
2010-04-19 09:53:00 +02:00
|
|
|
_cairo_image_surface_create_with_content (_cairo_color_get_content (&solid_pattern->color),
|
|
|
|
|
width, height);
|
2008-06-13 21:37:45 -04:00
|
|
|
status = image->base.status;
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-06-13 21:37:45 -04:00
|
|
|
goto BAIL;
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (other->base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
goto BAIL;
|
|
|
|
|
|
|
|
|
|
pixmap = XCreatePixmap (display->display,
|
2008-06-13 21:37:45 -04:00
|
|
|
other->drawable,
|
2008-08-27 21:14:51 -07:00
|
|
|
width, height,
|
2008-06-13 21:37:45 -04:00
|
|
|
other->depth);
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_device_release (&display->base);
|
2008-06-13 21:37:45 -04:00
|
|
|
|
|
|
|
|
surface = (cairo_xlib_surface_t *)
|
2009-09-01 23:12:43 +01:00
|
|
|
_cairo_xlib_surface_create_internal (other->screen,
|
2008-06-26 16:08:21 -04:00
|
|
|
pixmap,
|
2009-09-01 23:12:43 +01:00
|
|
|
other->visual,
|
2008-08-10 08:31:19 +01:00
|
|
|
other->xrender_format,
|
2008-08-27 21:14:51 -07:00
|
|
|
width, height,
|
2008-08-10 08:31:19 +01:00
|
|
|
other->depth);
|
2008-06-13 21:37:45 -04:00
|
|
|
status = surface->base.status;
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-06-13 21:37:45 -04:00
|
|
|
goto BAIL;
|
|
|
|
|
|
2008-10-16 12:33:22 +01:00
|
|
|
status = _cairo_surface_paint (&image->base,
|
|
|
|
|
CAIRO_OPERATOR_SOURCE,
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
&solid_pattern->base,
|
|
|
|
|
NULL);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-06-13 21:37:45 -04:00
|
|
|
goto BAIL;
|
|
|
|
|
|
|
|
|
|
status = _draw_image_surface (surface, image,
|
|
|
|
|
0, 0,
|
2008-08-27 21:14:51 -07:00
|
|
|
width, height,
|
2008-06-13 21:37:45 -04:00
|
|
|
0, 0);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-06-13 21:37:45 -04:00
|
|
|
goto BAIL;
|
|
|
|
|
|
|
|
|
|
BAIL:
|
|
|
|
|
cairo_surface_destroy (&image->base);
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
if (status) {
|
|
|
|
|
if (pixmap != None) {
|
|
|
|
|
if (!_cairo_xlib_display_acquire (other->base.device, &display)) {
|
|
|
|
|
XFreePixmap (display->display, pixmap);
|
|
|
|
|
cairo_device_release (&display->base);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cairo_surface_destroy (&surface->base);
|
2008-10-16 12:33:22 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
return _cairo_surface_create_in_error (status);
|
2008-06-13 21:37:45 -04:00
|
|
|
}
|
|
|
|
|
|
2008-10-16 12:33:22 +01:00
|
|
|
surface->owns_pixmap = TRUE;
|
|
|
|
|
return &surface->base;
|
2008-06-13 21:37:45 -04:00
|
|
|
}
|
|
|
|
|
|
2008-12-17 20:34:45 +00:00
|
|
|
static cairo_bool_t
|
|
|
|
|
_cairo_xlib_surface_can_repaint_solid_pattern_surface (void *abstract_surface,
|
|
|
|
|
const cairo_solid_pattern_t *solid_pattern)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *other = abstract_surface;
|
|
|
|
|
return CAIRO_SURFACE_RENDER_HAS_COMPOSITE (other);
|
|
|
|
|
}
|
|
|
|
|
|
2003-09-30 18:56:22 +00:00
|
|
|
static cairo_status_t
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_set_matrix (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *surface,
|
2010-04-29 18:20:44 +02:00
|
|
|
const cairo_matrix_t *matrix,
|
2010-12-17 11:04:41 +01:00
|
|
|
cairo_filter_t filter,
|
2008-11-04 18:42:05 +00:00
|
|
|
double xc,
|
2010-12-17 11:04:41 +01:00
|
|
|
double yc,
|
|
|
|
|
int *x_offset,
|
|
|
|
|
int *y_offset)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2003-10-31 10:41:37 +00:00
|
|
|
XTransform xtransform;
|
2010-12-17 11:04:41 +01:00
|
|
|
pixman_transform_t *pixman_transform;
|
|
|
|
|
cairo_status_t status;
|
2003-10-31 10:41:37 +00:00
|
|
|
|
2008-09-17 15:14:16 -04:00
|
|
|
/* Casting between pixman_transform_t and XTransform is safe because
|
|
|
|
|
* they happen to be the exact same type.
|
|
|
|
|
*/
|
2010-12-17 11:04:41 +01:00
|
|
|
pixman_transform = (pixman_transform_t *) &xtransform;
|
|
|
|
|
|
|
|
|
|
status = _cairo_matrix_to_pixman_matrix_offset (matrix, filter, xc, yc,
|
|
|
|
|
pixman_transform,
|
|
|
|
|
x_offset, y_offset);
|
|
|
|
|
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
|
|
|
|
status = CAIRO_STATUS_SUCCESS;
|
|
|
|
|
if (unlikely (status != CAIRO_STATUS_SUCCESS))
|
|
|
|
|
return status;
|
2003-10-31 10:41:37 +00:00
|
|
|
|
2007-04-18 18:08:45 +01:00
|
|
|
if (memcmp (&xtransform, &surface->xtransform, sizeof (XTransform)) == 0)
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (! CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface))
|
|
|
|
|
return UNSUPPORTED ("XRender does not support picture transforms");
|
2008-11-04 18:42:05 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderSetPictureTransform (display->display, surface->src_picture, &xtransform);
|
2007-04-18 18:08:45 +01:00
|
|
|
surface->xtransform = xtransform;
|
2005-03-03 18:20:28 +00:00
|
|
|
|
2003-09-30 18:56:22 +00:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2003-10-31 10:41:37 +00:00
|
|
|
static cairo_status_t
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_set_filter (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *surface,
|
2005-03-03 18:20:28 +00:00
|
|
|
cairo_filter_t filter)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2006-08-07 13:13:33 -07:00
|
|
|
const char *render_filter;
|
2003-10-31 10:41:37 +00:00
|
|
|
|
2007-04-18 18:08:45 +01:00
|
|
|
if (surface->filter == filter)
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface)) {
|
2005-03-03 18:20:28 +00:00
|
|
|
if (filter == CAIRO_FILTER_FAST || filter == CAIRO_FILTER_NEAREST)
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("XRender does not support filter");
|
2005-03-03 18:20:28 +00:00
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2003-09-30 18:56:22 +00:00
|
|
|
switch (filter) {
|
|
|
|
|
case CAIRO_FILTER_FAST:
|
2004-01-30 14:44:18 +00:00
|
|
|
render_filter = FilterFast;
|
2004-01-24 01:46:20 +00:00
|
|
|
break;
|
2003-09-30 18:56:22 +00:00
|
|
|
case CAIRO_FILTER_GOOD:
|
2004-01-30 14:44:18 +00:00
|
|
|
render_filter = FilterGood;
|
2004-01-24 01:46:20 +00:00
|
|
|
break;
|
2003-09-30 18:56:22 +00:00
|
|
|
case CAIRO_FILTER_BEST:
|
2004-01-30 14:44:18 +00:00
|
|
|
render_filter = FilterBest;
|
2004-01-24 01:46:20 +00:00
|
|
|
break;
|
2003-09-30 18:56:22 +00:00
|
|
|
case CAIRO_FILTER_NEAREST:
|
2004-01-30 14:44:18 +00:00
|
|
|
render_filter = FilterNearest;
|
2004-01-24 01:46:20 +00:00
|
|
|
break;
|
2003-09-30 18:56:22 +00:00
|
|
|
case CAIRO_FILTER_BILINEAR:
|
2004-01-30 14:44:18 +00:00
|
|
|
render_filter = FilterBilinear;
|
2004-01-24 01:46:20 +00:00
|
|
|
break;
|
2006-07-31 11:47:45 -07:00
|
|
|
case CAIRO_FILTER_GAUSSIAN:
|
|
|
|
|
/* XXX: The GAUSSIAN value has no implementation in cairo
|
|
|
|
|
* whatsoever, so it was really a mistake to have it in the
|
|
|
|
|
* API. We could fix this by officially deprecating it, or
|
|
|
|
|
* else inventing semantics and providing an actual
|
|
|
|
|
* implementation for it. */
|
2003-09-30 18:56:22 +00:00
|
|
|
default:
|
2004-01-30 14:44:18 +00:00
|
|
|
render_filter = FilterBest;
|
2004-01-24 01:46:20 +00:00
|
|
|
break;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderSetPictureFilter (display->display, surface->src_picture,
|
2006-08-07 13:13:33 -07:00
|
|
|
(char *) render_filter, NULL, 0);
|
2007-04-18 18:08:45 +01:00
|
|
|
surface->filter = filter;
|
2003-09-30 18:56:22 +00:00
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
static cairo_status_t
|
2009-10-16 16:48:54 +01:00
|
|
|
_cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface,
|
|
|
|
|
cairo_extend_t extend,
|
|
|
|
|
unsigned long *mask,
|
|
|
|
|
XRenderPictureAttributes *pa)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
int repeat;
|
2005-03-03 17:40:04 +00:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
if (surface->extend == extend)
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
switch (extend) {
|
2005-03-03 17:40:04 +00:00
|
|
|
case CAIRO_EXTEND_NONE:
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
repeat = RepeatNone;
|
2005-03-03 17:40:04 +00:00
|
|
|
break;
|
|
|
|
|
case CAIRO_EXTEND_REPEAT:
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
repeat = RepeatNormal;
|
2005-03-03 17:40:04 +00:00
|
|
|
break;
|
|
|
|
|
case CAIRO_EXTEND_REFLECT:
|
2009-02-19 12:02:41 -05:00
|
|
|
if (surface->buggy_pad_reflect)
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("buggy reflect");
|
|
|
|
|
|
|
|
|
|
repeat = RepeatReflect;
|
2009-02-19 12:02:41 -05:00
|
|
|
break;
|
2005-10-10 12:45:15 +00:00
|
|
|
case CAIRO_EXTEND_PAD:
|
2009-02-19 12:02:41 -05:00
|
|
|
if (surface->buggy_pad_reflect)
|
2009-09-11 14:59:58 +01:00
|
|
|
return UNSUPPORTED ("buggy pad");
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
|
|
|
|
|
repeat = RepeatPad;
|
2009-02-19 12:02:41 -05:00
|
|
|
break;
|
2007-12-17 01:14:27 -05:00
|
|
|
default:
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
ASSERT_NOT_REACHED;
|
2007-11-07 00:12:00 +00:00
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
2005-03-03 17:40:04 +00:00
|
|
|
}
|
2009-09-11 14:59:58 +01:00
|
|
|
|
2009-10-16 16:48:54 +01:00
|
|
|
*mask |= CPRepeat;
|
|
|
|
|
pa->repeat = repeat;
|
2009-09-11 14:59:58 +01:00
|
|
|
|
|
|
|
|
surface->extend = extend;
|
2009-10-16 16:48:54 +01:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_xlib_surface_set_component_alpha (cairo_xlib_surface_t *surface,
|
|
|
|
|
cairo_bool_t ca,
|
|
|
|
|
unsigned long *mask,
|
|
|
|
|
XRenderPictureAttributes *pa)
|
|
|
|
|
{
|
|
|
|
|
if (surface->has_component_alpha == ca)
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2009-09-11 14:59:58 +01:00
|
|
|
|
2009-10-16 16:48:54 +01:00
|
|
|
*mask |= CPComponentAlpha;
|
|
|
|
|
pa->component_alpha = ca;
|
|
|
|
|
|
|
|
|
|
surface->has_component_alpha = ca;
|
2009-09-11 14:59:58 +01:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_int_status_t
|
2010-12-17 11:04:41 +01:00
|
|
|
_cairo_xlib_surface_set_attributes (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *surface,
|
|
|
|
|
cairo_surface_attributes_t *attributes,
|
|
|
|
|
double xc,
|
|
|
|
|
double yc)
|
2009-09-11 14:59:58 +01:00
|
|
|
{
|
|
|
|
|
cairo_int_status_t status;
|
2009-10-16 16:48:54 +01:00
|
|
|
XRenderPictureAttributes pa;
|
|
|
|
|
unsigned long mask = 0;
|
2009-09-11 14:59:58 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_ensure_src_picture (display, surface);
|
2009-09-11 14:59:58 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_set_matrix (display, surface,
|
2010-12-17 11:04:41 +01:00
|
|
|
&attributes->matrix,
|
|
|
|
|
attributes->filter,
|
|
|
|
|
xc, yc,
|
|
|
|
|
&attributes->x_offset,
|
|
|
|
|
&attributes->y_offset);
|
2009-09-11 14:59:58 +01:00
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
2009-10-16 16:48:54 +01:00
|
|
|
status = _cairo_xlib_surface_set_repeat (surface, attributes->extend,
|
|
|
|
|
&mask, &pa);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
status = _cairo_xlib_surface_set_component_alpha (surface,
|
|
|
|
|
attributes->has_component_alpha,
|
|
|
|
|
&mask, &pa);
|
2009-09-11 14:59:58 +01:00
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
2005-03-03 17:40:04 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_set_filter (display, surface, attributes->filter);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2005-03-03 17:40:04 +00:00
|
|
|
return status;
|
|
|
|
|
|
2009-10-16 16:48:54 +01:00
|
|
|
if (mask)
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderChangePicture (display->display, surface->src_picture, mask, &pa);
|
2009-10-16 16:48:54 +01:00
|
|
|
|
2005-03-03 17:40:04 +00:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2005-06-20 15:48:46 +00:00
|
|
|
/* Checks whether we can can directly draw from src to dst with
|
|
|
|
|
* the core protocol: either with CopyArea or using src as a
|
|
|
|
|
* a tile in a GC.
|
|
|
|
|
*/
|
|
|
|
|
static cairo_bool_t
|
2005-07-20 18:52:31 +00:00
|
|
|
_surfaces_compatible (cairo_xlib_surface_t *dst,
|
|
|
|
|
cairo_xlib_surface_t *src)
|
2005-06-20 15:48:46 +00:00
|
|
|
{
|
2005-07-20 18:52:31 +00:00
|
|
|
/* same screen */
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (! _cairo_xlib_surface_same_screen (dst, src))
|
2005-06-20 15:48:46 +00:00
|
|
|
return FALSE;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
/* same depth (for core) */
|
|
|
|
|
if (src->depth != dst->depth)
|
2005-06-20 15:48:46 +00:00
|
|
|
return FALSE;
|
2005-07-20 18:52:31 +00:00
|
|
|
|
|
|
|
|
/* if Render is supported, match picture formats */
|
2008-09-28 17:51:23 +01:00
|
|
|
if (src->xrender_format != dst->xrender_format)
|
|
|
|
|
return FALSE;
|
|
|
|
|
else if (src->xrender_format != NULL)
|
2005-07-20 18:52:31 +00:00
|
|
|
return TRUE;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
/* Without Render, match visuals instead */
|
|
|
|
|
if (src->visual == dst->visual)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2005-06-20 15:48:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_bool_t
|
|
|
|
|
_surface_has_alpha (cairo_xlib_surface_t *surface)
|
|
|
|
|
{
|
2006-05-18 15:20:25 -07:00
|
|
|
if (surface->xrender_format) {
|
|
|
|
|
if (surface->xrender_format->type == PictTypeDirect &&
|
|
|
|
|
surface->xrender_format->direct.alphaMask != 0)
|
2005-06-20 15:48:46 +00:00
|
|
|
return TRUE;
|
|
|
|
|
else
|
|
|
|
|
return FALSE;
|
|
|
|
|
} else {
|
|
|
|
|
/* In the no-render case, we never have alpha */
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-15 13:45:19 +00:00
|
|
|
/* Returns true if the given operator and source-alpha combination
|
|
|
|
|
* requires alpha compositing to complete.
|
|
|
|
|
*/
|
|
|
|
|
static cairo_bool_t
|
2005-12-16 03:02:35 +00:00
|
|
|
_operator_needs_alpha_composite (cairo_operator_t op,
|
2009-05-09 10:10:14 +01:00
|
|
|
cairo_bool_t destination_has_alpha,
|
|
|
|
|
cairo_bool_t source_has_alpha)
|
2005-07-15 13:45:19 +00:00
|
|
|
{
|
2005-12-16 03:02:35 +00:00
|
|
|
if (op == CAIRO_OPERATOR_SOURCE ||
|
2009-05-09 10:10:14 +01:00
|
|
|
(! source_has_alpha &&
|
2005-12-16 03:02:35 +00:00
|
|
|
(op == CAIRO_OPERATOR_OVER ||
|
|
|
|
|
op == CAIRO_OPERATOR_ATOP ||
|
|
|
|
|
op == CAIRO_OPERATOR_IN)))
|
2009-05-09 10:10:14 +01:00
|
|
|
return destination_has_alpha;
|
2005-07-15 13:45:19 +00:00
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-04 15:53:30 +00:00
|
|
|
/* There is a bug in most older X servers with compositing using a
|
|
|
|
|
* untransformed repeating source pattern when the source is in off-screen
|
|
|
|
|
* video memory, and another with repeated transformed images using a
|
2007-01-07 02:03:30 +00:00
|
|
|
* general transform matrix. When these bugs could be triggered, we need a
|
2005-08-04 15:53:30 +00:00
|
|
|
* fallback: in the common case where we have no transformation and the
|
|
|
|
|
* source and destination have the same format/visual, we can do the
|
|
|
|
|
* operation using the core protocol for the first bug, otherwise, we need
|
2005-06-20 15:48:46 +00:00
|
|
|
* a software fallback.
|
2005-07-15 13:45:19 +00:00
|
|
|
*
|
|
|
|
|
* We can also often optimize a compositing operation by calling XCopyArea
|
|
|
|
|
* for some common cases where there is no alpha compositing to be done.
|
|
|
|
|
* We figure that out here as well.
|
2005-06-20 15:48:46 +00:00
|
|
|
*/
|
|
|
|
|
typedef enum {
|
2005-07-15 13:45:19 +00:00
|
|
|
DO_RENDER, /* use render */
|
|
|
|
|
DO_XCOPYAREA, /* core protocol XCopyArea optimization/fallback */
|
|
|
|
|
DO_XTILE, /* core protocol XSetTile optimization/fallback */
|
|
|
|
|
DO_UNSUPPORTED /* software fallback */
|
2005-06-20 15:48:46 +00:00
|
|
|
} composite_operation_t;
|
|
|
|
|
|
2005-08-04 15:53:30 +00:00
|
|
|
/* Initial check for the render bugs; we need to recheck for the
|
|
|
|
|
* offscreen-memory bug after we turn patterns into surfaces, since that
|
|
|
|
|
* may introduce a repeating pattern for gradient patterns. We don't need
|
|
|
|
|
* to check for the repeat+transform bug because gradient surfaces aren't
|
|
|
|
|
* transformed.
|
2005-06-20 15:48:46 +00:00
|
|
|
*
|
|
|
|
|
* All we do here is reject cases where we *know* are going to
|
|
|
|
|
* hit the bug and won't be able to use a core protocol fallback.
|
|
|
|
|
*/
|
|
|
|
|
static composite_operation_t
|
2005-07-15 13:45:19 +00:00
|
|
|
_categorize_composite_operation (cairo_xlib_surface_t *dst,
|
2005-12-16 03:02:35 +00:00
|
|
|
cairo_operator_t op,
|
2008-10-22 19:24:44 +01:00
|
|
|
const cairo_pattern_t *src_pattern,
|
2005-07-15 13:45:19 +00:00
|
|
|
cairo_bool_t have_mask)
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-06-20 15:48:46 +00:00
|
|
|
{
|
2007-08-30 10:16:00 +02:00
|
|
|
if (!CAIRO_SURFACE_RENDER_SUPPORTS_OPERATOR (dst, op))
|
|
|
|
|
return DO_UNSUPPORTED;
|
|
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (! dst->buggy_repeat)
|
2005-06-20 15:48:46 +00:00
|
|
|
return DO_RENDER;
|
2005-07-20 18:52:31 +00:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID &&
|
|
|
|
|
src_pattern->extend == CAIRO_EXTEND_REPEAT)
|
2005-06-20 15:48:46 +00:00
|
|
|
{
|
2009-09-11 14:59:58 +01:00
|
|
|
/* Check for the bug with repeat patterns nad general transforms. */
|
|
|
|
|
if (! _cairo_matrix_is_integer_translation (&src_pattern->matrix,
|
|
|
|
|
NULL, NULL))
|
|
|
|
|
{
|
|
|
|
|
return DO_UNSUPPORTED;
|
|
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
if (have_mask ||
|
|
|
|
|
!(op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER))
|
2005-06-20 15:48:46 +00:00
|
|
|
{
|
2009-09-11 14:59:58 +01:00
|
|
|
return DO_UNSUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (src_pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
|
|
|
|
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) src_pattern;
|
|
|
|
|
|
2005-08-04 15:53:30 +00:00
|
|
|
/* This is the case where we have the bug involving
|
|
|
|
|
* untransformed repeating source patterns with off-screen
|
|
|
|
|
* video memory; reject some cases where a core protocol
|
|
|
|
|
* fallback is impossible.
|
2005-06-20 15:48:46 +00:00
|
|
|
*/
|
|
|
|
|
if (_cairo_surface_is_xlib (surface_pattern->surface)) {
|
2009-09-11 14:59:58 +01:00
|
|
|
cairo_xlib_surface_t *src = (cairo_xlib_surface_t *) surface_pattern->surface;
|
2005-06-20 15:48:46 +00:00
|
|
|
|
2005-12-16 03:02:35 +00:00
|
|
|
if (op == CAIRO_OPERATOR_OVER && _surface_has_alpha (src))
|
2005-06-20 15:48:46 +00:00
|
|
|
return DO_UNSUPPORTED;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
/* If these are on the same screen but otherwise incompatible,
|
|
|
|
|
* make a copy as core drawing can't cross depths and doesn't
|
2007-01-07 02:03:30 +00:00
|
|
|
* work right across visuals of the same depth
|
2005-07-20 18:52:31 +00:00
|
|
|
*/
|
2006-06-06 15:41:31 -07:00
|
|
|
if (_cairo_xlib_surface_same_screen (dst, src) &&
|
2005-07-20 18:52:31 +00:00
|
|
|
!_surfaces_compatible (dst, src))
|
2009-09-11 14:59:58 +01:00
|
|
|
{
|
2005-06-20 15:48:46 +00:00
|
|
|
return DO_UNSUPPORTED;
|
2009-09-11 14:59:58 +01:00
|
|
|
}
|
2005-06-20 15:48:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DO_RENDER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Recheck for composite-repeat once we've turned patterns into Xlib surfaces
|
|
|
|
|
* If we end up returning DO_UNSUPPORTED here, we're throwing away work we
|
|
|
|
|
* did to turn gradients into a pattern, but most of the time we can handle
|
|
|
|
|
* that case with core protocol fallback.
|
2005-07-15 13:45:19 +00:00
|
|
|
*
|
|
|
|
|
* Also check here if we can just use XCopyArea, instead of going through
|
|
|
|
|
* Render.
|
2005-06-20 15:48:46 +00:00
|
|
|
*/
|
|
|
|
|
static composite_operation_t
|
2005-07-15 13:45:19 +00:00
|
|
|
_recategorize_composite_operation (cairo_xlib_surface_t *dst,
|
2005-12-16 03:02:35 +00:00
|
|
|
cairo_operator_t op,
|
2005-07-15 13:45:19 +00:00
|
|
|
cairo_xlib_surface_t *src,
|
|
|
|
|
cairo_surface_attributes_t *src_attr,
|
|
|
|
|
cairo_bool_t have_mask)
|
2005-06-20 15:48:46 +00:00
|
|
|
{
|
2009-09-11 14:59:58 +01:00
|
|
|
/* Can we use the core protocol? */
|
2008-10-10 14:00:32 +01:00
|
|
|
if (! have_mask &&
|
2009-08-26 21:22:07 +02:00
|
|
|
src->owns_pixmap &&
|
2009-09-11 14:59:58 +01:00
|
|
|
src->depth == dst->depth &&
|
|
|
|
|
_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
|
|
|
|
|
! _operator_needs_alpha_composite (op,
|
|
|
|
|
_surface_has_alpha (dst),
|
|
|
|
|
_surface_has_alpha (src)))
|
2005-07-15 13:45:19 +00:00
|
|
|
{
|
2009-09-11 14:59:58 +01:00
|
|
|
if (src_attr->extend == CAIRO_EXTEND_NONE)
|
|
|
|
|
return DO_XCOPYAREA;
|
2005-07-15 13:45:19 +00:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
if (dst->buggy_repeat && src_attr->extend == CAIRO_EXTEND_REPEAT)
|
2005-07-15 13:45:19 +00:00
|
|
|
return DO_XTILE;
|
2009-09-11 14:59:58 +01:00
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
if (dst->buggy_repeat && src_attr->extend == CAIRO_EXTEND_REPEAT)
|
2005-06-20 15:48:46 +00:00
|
|
|
return DO_UNSUPPORTED;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2008-10-10 14:00:32 +01:00
|
|
|
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
|
2007-10-19 22:45:15 +01:00
|
|
|
return DO_UNSUPPORTED;
|
|
|
|
|
|
2008-10-10 14:00:32 +01:00
|
|
|
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
|
2008-05-27 04:41:03 -04:00
|
|
|
return DO_UNSUPPORTED;
|
|
|
|
|
|
2005-06-20 15:48:46 +00:00
|
|
|
return DO_RENDER;
|
|
|
|
|
}
|
|
|
|
|
|
2003-10-31 10:41:37 +00:00
|
|
|
static int
|
2005-12-16 03:02:35 +00:00
|
|
|
_render_operator (cairo_operator_t op)
|
2003-10-31 10:41:37 +00:00
|
|
|
{
|
2005-12-16 03:02:35 +00:00
|
|
|
switch (op) {
|
2003-10-31 10:41:37 +00:00
|
|
|
case CAIRO_OPERATOR_CLEAR:
|
|
|
|
|
return PictOpClear;
|
2005-05-06 13:26:16 +00:00
|
|
|
|
|
|
|
|
case CAIRO_OPERATOR_SOURCE:
|
2003-10-31 10:41:37 +00:00
|
|
|
return PictOpSrc;
|
|
|
|
|
case CAIRO_OPERATOR_OVER:
|
|
|
|
|
return PictOpOver;
|
|
|
|
|
case CAIRO_OPERATOR_IN:
|
|
|
|
|
return PictOpIn;
|
|
|
|
|
case CAIRO_OPERATOR_OUT:
|
|
|
|
|
return PictOpOut;
|
|
|
|
|
case CAIRO_OPERATOR_ATOP:
|
|
|
|
|
return PictOpAtop;
|
2005-05-06 13:26:16 +00:00
|
|
|
|
|
|
|
|
case CAIRO_OPERATOR_DEST:
|
|
|
|
|
return PictOpDst;
|
|
|
|
|
case CAIRO_OPERATOR_DEST_OVER:
|
|
|
|
|
return PictOpOverReverse;
|
|
|
|
|
case CAIRO_OPERATOR_DEST_IN:
|
|
|
|
|
return PictOpInReverse;
|
|
|
|
|
case CAIRO_OPERATOR_DEST_OUT:
|
|
|
|
|
return PictOpOutReverse;
|
|
|
|
|
case CAIRO_OPERATOR_DEST_ATOP:
|
2003-10-31 10:41:37 +00:00
|
|
|
return PictOpAtopReverse;
|
2005-05-06 13:26:16 +00:00
|
|
|
|
2003-10-31 10:41:37 +00:00
|
|
|
case CAIRO_OPERATOR_XOR:
|
|
|
|
|
return PictOpXor;
|
|
|
|
|
case CAIRO_OPERATOR_ADD:
|
|
|
|
|
return PictOpAdd;
|
|
|
|
|
case CAIRO_OPERATOR_SATURATE:
|
|
|
|
|
return PictOpSaturate;
|
2007-08-30 10:16:00 +02:00
|
|
|
|
|
|
|
|
case CAIRO_OPERATOR_MULTIPLY:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpMultiply;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_SCREEN:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpScreen;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_OVERLAY:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpOverlay;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_DARKEN:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpDarken;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_LIGHTEN:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpLighten;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_COLOR_DODGE:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpColorDodge;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_COLOR_BURN:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpColorBurn;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_HARD_LIGHT:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpHardLight;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_SOFT_LIGHT:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpSoftLight;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_DIFFERENCE:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpDifference;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_EXCLUSION:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpExclusion;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_HSL_HUE:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpHSLHue;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_HSL_SATURATION:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpHSLSaturation;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_HSL_COLOR:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpHSLColor;
|
2007-08-30 10:16:00 +02:00
|
|
|
case CAIRO_OPERATOR_HSL_LUMINOSITY:
|
2009-07-16 14:18:13 +01:00
|
|
|
return PictOpHSLLuminosity;
|
2007-08-30 10:16:00 +02:00
|
|
|
|
2003-10-31 10:41:37 +00:00
|
|
|
default:
|
2009-07-16 14:18:13 +01:00
|
|
|
ASSERT_NOT_REACHED;
|
2003-10-31 10:41:37 +00:00
|
|
|
return PictOpOver;
|
|
|
|
|
}
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2009-07-31 13:17:24 +01:00
|
|
|
static cairo_int_status_t
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_acquire_pattern_surface (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *dst,
|
2009-07-31 13:17:24 +01:00
|
|
|
const cairo_pattern_t *pattern,
|
|
|
|
|
int x, int y,
|
|
|
|
|
int width, int height,
|
|
|
|
|
cairo_xlib_surface_t **surface_out,
|
|
|
|
|
cairo_surface_attributes_t *attributes)
|
|
|
|
|
{
|
|
|
|
|
switch (pattern->type) {
|
|
|
|
|
case CAIRO_PATTERN_TYPE_LINEAR:
|
|
|
|
|
case CAIRO_PATTERN_TYPE_RADIAL:
|
|
|
|
|
{
|
|
|
|
|
cairo_gradient_pattern_t *gradient =
|
|
|
|
|
(cairo_gradient_pattern_t *) pattern;
|
|
|
|
|
cairo_matrix_t matrix = pattern->matrix;
|
|
|
|
|
cairo_xlib_surface_t *surface;
|
|
|
|
|
char buf[CAIRO_STACK_BUFFER_SIZE];
|
2010-12-17 11:03:03 +01:00
|
|
|
cairo_circle_double_t extremes[2];
|
2009-07-31 13:17:24 +01:00
|
|
|
XFixed *stops;
|
|
|
|
|
XRenderColor *colors;
|
|
|
|
|
XRenderPictFormat *format;
|
|
|
|
|
Picture picture;
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
|
|
if (dst->buggy_gradients)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (gradient->n_stops < 2) /* becomes a solid */
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (gradient->n_stops < sizeof (buf) / (sizeof (XFixed) + sizeof (XRenderColor)))
|
|
|
|
|
{
|
|
|
|
|
stops = (XFixed *) buf;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
stops =
|
|
|
|
|
_cairo_malloc_ab (gradient->n_stops,
|
|
|
|
|
sizeof (XFixed) + sizeof (XRenderColor));
|
|
|
|
|
if (unlikely (stops == NULL))
|
|
|
|
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
colors = (XRenderColor *) (stops + gradient->n_stops);
|
|
|
|
|
for (i = 0; i < gradient->n_stops; i++) {
|
|
|
|
|
stops[i] =
|
|
|
|
|
_cairo_fixed_16_16_from_double (gradient->stops[i].offset);
|
|
|
|
|
|
|
|
|
|
colors[i].red = gradient->stops[i].color.red_short;
|
|
|
|
|
colors[i].green = gradient->stops[i].color.green_short;
|
|
|
|
|
colors[i].blue = gradient->stops[i].color.blue_short;
|
|
|
|
|
colors[i].alpha = gradient->stops[i].color.alpha_short;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
/* For some weird reason the X server is sometimes getting
|
|
|
|
|
* CreateGradient requests with bad length. So far I've only seen
|
|
|
|
|
* XRenderCreateLinearGradient request with 4 stops sometime end up
|
|
|
|
|
* with length field matching 0 stops at the server side. I've
|
|
|
|
|
* looked at the libXrender code and I can't see anything that
|
|
|
|
|
* could cause this behavior. However, for some reason having a
|
|
|
|
|
* XSync call here seems to avoid the issue so I'll keep it here
|
|
|
|
|
* until it's solved.
|
|
|
|
|
*/
|
2010-04-18 23:20:02 +02:00
|
|
|
XSync (display->display, False);
|
2009-07-31 13:17:24 +01:00
|
|
|
#endif
|
|
|
|
|
|
2010-12-17 11:03:03 +01:00
|
|
|
_cairo_gradient_pattern_fit_to_range (gradient, PIXMAN_MAX_INT >> 1, &matrix, extremes);
|
|
|
|
|
|
2009-07-31 13:17:24 +01:00
|
|
|
if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
|
|
|
|
|
XLinearGradient grad;
|
|
|
|
|
|
2010-12-17 11:03:03 +01:00
|
|
|
grad.p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
|
|
|
|
|
grad.p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
|
|
|
|
|
grad.p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
|
|
|
|
|
grad.p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
|
2009-07-31 13:17:24 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
picture = XRenderCreateLinearGradient (display->display, &grad,
|
2009-07-31 13:17:24 +01:00
|
|
|
stops, colors,
|
|
|
|
|
gradient->n_stops);
|
|
|
|
|
} else {
|
|
|
|
|
XRadialGradient grad;
|
|
|
|
|
|
2010-12-17 11:03:03 +01:00
|
|
|
grad.inner.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
|
|
|
|
|
grad.inner.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
|
|
|
|
|
grad.inner.radius = _cairo_fixed_16_16_from_double (extremes[0].radius);
|
|
|
|
|
grad.outer.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
|
|
|
|
|
grad.outer.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
|
|
|
|
|
grad.outer.radius = _cairo_fixed_16_16_from_double (extremes[1].radius);
|
2009-07-31 13:17:24 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
picture = XRenderCreateRadialGradient (display->display, &grad,
|
2009-07-31 13:17:24 +01:00
|
|
|
stops, colors,
|
|
|
|
|
gradient->n_stops);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (stops != (XFixed *) buf)
|
|
|
|
|
free (stops);
|
|
|
|
|
|
|
|
|
|
if (unlikely (picture == None))
|
|
|
|
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
|
|
|
|
|
/* Wrap the remote Picture in an xlib surface. */
|
2010-04-18 23:20:02 +02:00
|
|
|
format = _cairo_xlib_display_get_xrender_format (display,
|
2009-07-31 13:17:24 +01:00
|
|
|
CAIRO_FORMAT_ARGB32);
|
|
|
|
|
|
|
|
|
|
surface = (cairo_xlib_surface_t *)
|
2009-09-01 23:12:43 +01:00
|
|
|
_cairo_xlib_surface_create_internal (dst->screen, None,
|
|
|
|
|
NULL, format,
|
2010-05-04 13:52:09 +02:00
|
|
|
/* what could possibly go wrong? */
|
|
|
|
|
XLIB_COORD_MAX, XLIB_COORD_MAX, 32);
|
2009-07-31 13:17:24 +01:00
|
|
|
if (unlikely (surface->base.status)) {
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderFreePicture (display->display, picture);
|
2009-07-31 13:17:24 +01:00
|
|
|
return surface->base.status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
surface->src_picture = picture;
|
|
|
|
|
|
|
|
|
|
attributes->matrix = matrix;
|
|
|
|
|
attributes->extend = pattern->extend;
|
|
|
|
|
attributes->filter = CAIRO_FILTER_NEAREST;
|
|
|
|
|
attributes->x_offset = 0;
|
|
|
|
|
attributes->y_offset = 0;
|
2009-10-27 20:27:09 +00:00
|
|
|
attributes->has_component_alpha = FALSE;
|
2009-07-31 13:17:24 +01:00
|
|
|
|
|
|
|
|
*surface_out = surface;
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
ASSERT_NOT_REACHED;
|
|
|
|
|
case CAIRO_PATTERN_TYPE_SOLID:
|
|
|
|
|
case CAIRO_PATTERN_TYPE_SURFACE:
|
2010-12-09 10:34:31 +01:00
|
|
|
case CAIRO_PATTERN_TYPE_MESH:
|
2009-07-31 13:17:24 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _cairo_pattern_acquire_surface (pattern, &dst->base,
|
|
|
|
|
x, y, width, height,
|
|
|
|
|
dst->buggy_pad_reflect ?
|
|
|
|
|
CAIRO_PATTERN_ACQUIRE_NO_REFLECT :
|
|
|
|
|
CAIRO_PATTERN_ACQUIRE_NONE,
|
|
|
|
|
(cairo_surface_t **) surface_out,
|
|
|
|
|
attributes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_int_status_t
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_acquire_pattern_surfaces (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *dst,
|
|
|
|
|
const cairo_pattern_t *src,
|
|
|
|
|
const cairo_pattern_t *mask,
|
2009-07-31 13:17:24 +01:00
|
|
|
int src_x,
|
|
|
|
|
int src_y,
|
|
|
|
|
int mask_x,
|
|
|
|
|
int mask_y,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
unsigned int height,
|
|
|
|
|
cairo_xlib_surface_t **src_out,
|
|
|
|
|
cairo_xlib_surface_t **mask_out,
|
|
|
|
|
cairo_surface_attributes_t *src_attr,
|
|
|
|
|
cairo_surface_attributes_t *mask_attr)
|
|
|
|
|
{
|
|
|
|
|
if (! dst->buggy_gradients &&
|
|
|
|
|
(src->type == CAIRO_PATTERN_TYPE_LINEAR ||
|
|
|
|
|
src->type == CAIRO_PATTERN_TYPE_RADIAL ||
|
|
|
|
|
(mask && (mask->type == CAIRO_PATTERN_TYPE_LINEAR ||
|
|
|
|
|
mask->type == CAIRO_PATTERN_TYPE_RADIAL))))
|
|
|
|
|
{
|
|
|
|
|
cairo_int_status_t status;
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_acquire_pattern_surface (display,
|
|
|
|
|
dst, src,
|
2009-07-31 13:17:24 +01:00
|
|
|
src_x, src_y,
|
|
|
|
|
width, height,
|
|
|
|
|
src_out,
|
|
|
|
|
src_attr);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
if (mask) {
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_acquire_pattern_surface (display,
|
|
|
|
|
dst, mask,
|
2009-07-31 13:17:24 +01:00
|
|
|
mask_x,
|
|
|
|
|
mask_y,
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
mask_out,
|
|
|
|
|
mask_attr);
|
|
|
|
|
if (unlikely (status)) {
|
|
|
|
|
_cairo_pattern_release_surface (src, &(*src_out)->base,
|
|
|
|
|
src_attr);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
*mask_out = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _cairo_pattern_acquire_surfaces (src, mask,
|
|
|
|
|
&dst->base,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
mask_x, mask_y,
|
|
|
|
|
width, height,
|
|
|
|
|
dst->buggy_pad_reflect ?
|
|
|
|
|
CAIRO_PATTERN_ACQUIRE_NO_REFLECT :
|
|
|
|
|
CAIRO_PATTERN_ACQUIRE_NONE,
|
|
|
|
|
(cairo_surface_t **) src_out,
|
|
|
|
|
(cairo_surface_t **) mask_out,
|
|
|
|
|
src_attr, mask_attr);
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-19 10:26:05 +01:00
|
|
|
static cairo_int_status_t
|
|
|
|
|
_cairo_xlib_surface_upload(cairo_xlib_surface_t *surface,
|
|
|
|
|
cairo_operator_t op,
|
|
|
|
|
const cairo_pattern_t *pattern,
|
|
|
|
|
int src_x, int src_y,
|
|
|
|
|
int dst_x, int dst_y,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
unsigned int height,
|
|
|
|
|
cairo_region_t *clip_region)
|
|
|
|
|
{
|
|
|
|
|
cairo_image_surface_t *image;
|
|
|
|
|
cairo_rectangle_int_t extents;
|
|
|
|
|
cairo_status_t status;
|
|
|
|
|
int tx, ty;
|
|
|
|
|
|
|
|
|
|
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
|
|
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
|
|
|
|
|
|
|
|
|
image = (cairo_image_surface_t *) ((cairo_surface_pattern_t *) pattern)->surface;
|
|
|
|
|
if (image->base.type != CAIRO_SURFACE_TYPE_IMAGE)
|
|
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
|
|
|
|
|
|
|
|
|
if (! (op == CAIRO_OPERATOR_SOURCE ||
|
|
|
|
|
(op == CAIRO_OPERATOR_OVER &&
|
|
|
|
|
(image->base.content & CAIRO_CONTENT_ALPHA) == 0)))
|
|
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
|
|
|
|
|
|
|
|
|
if (image->base.backend->type != CAIRO_SURFACE_TYPE_IMAGE) {
|
|
|
|
|
if (image->base.backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SNAPSHOT) {
|
|
|
|
|
image = (cairo_image_surface_t *) ((cairo_surface_snapshot_t *) image)->target;
|
|
|
|
|
extents.x = extents.y = 0;
|
|
|
|
|
extents.width = image->width;
|
|
|
|
|
extents.height = image->height;
|
2010-08-26 12:54:25 +02:00
|
|
|
} else if (image->base.backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
|
2010-06-19 10:26:05 +01:00
|
|
|
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) image;
|
|
|
|
|
image = (cairo_image_surface_t *) sub->target;
|
|
|
|
|
src_x += sub->extents.x;
|
|
|
|
|
src_y += sub->extents.y;
|
|
|
|
|
extents = sub->extents;
|
|
|
|
|
} else {
|
|
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
extents.x = extents.y = 0;
|
|
|
|
|
extents.width = image->width;
|
|
|
|
|
extents.height = image->height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (image->format == CAIRO_FORMAT_INVALID)
|
|
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
|
|
|
|
if (image->depth != surface->depth)
|
|
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
|
|
|
|
|
|
|
|
|
if (! _cairo_matrix_is_integer_translation (&pattern->matrix, &tx, &ty))
|
|
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
|
|
|
|
|
2010-07-02 13:19:17 +01:00
|
|
|
src_x += tx;
|
|
|
|
|
src_y += ty;
|
|
|
|
|
|
2010-06-19 10:26:05 +01:00
|
|
|
/* XXX for EXTEND_NONE perform unbounded fixups? */
|
2010-07-02 13:19:17 +01:00
|
|
|
if (src_x < extents.x ||
|
|
|
|
|
src_y < extents.y ||
|
|
|
|
|
src_x + width > (unsigned) extents.width ||
|
|
|
|
|
src_y + height > (unsigned) extents.height)
|
2010-06-19 10:26:05 +01:00
|
|
|
{
|
|
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = cairo_device_acquire (surface->base.device);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
if (clip_region != NULL) {
|
|
|
|
|
int n, num_rect;
|
|
|
|
|
|
|
|
|
|
src_x -= dst_x;
|
|
|
|
|
src_y -= dst_y;
|
|
|
|
|
|
|
|
|
|
num_rect = cairo_region_num_rectangles (clip_region);
|
|
|
|
|
for (n = 0; n < num_rect; n++) {
|
|
|
|
|
cairo_rectangle_int_t rect;
|
|
|
|
|
|
|
|
|
|
cairo_region_get_rectangle (clip_region, n, &rect);
|
|
|
|
|
status = _draw_image_surface (surface, image,
|
2010-07-02 13:19:17 +01:00
|
|
|
rect.x + src_x, rect.y + src_y,
|
2010-06-19 10:26:05 +01:00
|
|
|
rect.width, rect.height,
|
|
|
|
|
rect.x, rect.y);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
status = _draw_image_surface (surface, image,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
width, height,
|
|
|
|
|
dst_x, dst_y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cairo_device_release (surface->base.device);
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2003-10-27 18:40:55 +00:00
|
|
|
static cairo_int_status_t
|
2005-12-16 03:02:35 +00:00
|
|
|
_cairo_xlib_surface_composite (cairo_operator_t op,
|
2008-10-22 19:24:44 +01:00
|
|
|
const cairo_pattern_t *src_pattern,
|
|
|
|
|
const cairo_pattern_t *mask_pattern,
|
2003-10-27 18:40:55 +00:00
|
|
|
void *abstract_dst,
|
2003-09-30 18:56:22 +00:00
|
|
|
int src_x,
|
|
|
|
|
int src_y,
|
|
|
|
|
int mask_x,
|
|
|
|
|
int mask_y,
|
|
|
|
|
int dst_x,
|
|
|
|
|
int dst_y,
|
|
|
|
|
unsigned int width,
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
unsigned int height,
|
|
|
|
|
cairo_region_t *clip_region)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2005-03-03 18:39:06 +00:00
|
|
|
cairo_surface_attributes_t src_attr, mask_attr;
|
2005-03-03 17:40:04 +00:00
|
|
|
cairo_xlib_surface_t *dst = abstract_dst;
|
|
|
|
|
cairo_xlib_surface_t *src;
|
2005-03-03 18:39:06 +00:00
|
|
|
cairo_xlib_surface_t *mask;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2005-03-03 17:40:04 +00:00
|
|
|
cairo_int_status_t status;
|
2005-06-20 15:48:46 +00:00
|
|
|
composite_operation_t operation;
|
2005-07-15 13:45:19 +00:00
|
|
|
int itx, ity;
|
2007-04-10 13:57:41 -07:00
|
|
|
cairo_bool_t is_integer_translation;
|
2009-09-02 00:34:37 +01:00
|
|
|
GC gc;
|
2003-10-27 18:40:55 +00:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (mask_pattern != NULL && ! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
|
|
|
|
|
return UNSUPPORTED ("no support for masks");
|
2007-04-19 12:15:04 +01:00
|
|
|
|
2005-12-16 03:02:35 +00:00
|
|
|
operation = _categorize_composite_operation (dst, op, src_pattern,
|
2005-07-15 13:45:19 +00:00
|
|
|
mask_pattern != NULL);
|
2005-06-20 15:48:46 +00:00
|
|
|
if (operation == DO_UNSUPPORTED)
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("unsupported operation");
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
X_DEBUG ((display->display, "composite (dst=%x)", (unsigned int) dst->drawable));
|
2009-09-29 03:02:40 +01:00
|
|
|
|
2010-06-19 10:26:05 +01:00
|
|
|
if (mask_pattern == NULL) {
|
|
|
|
|
/* Can we do a simple upload in-place? */
|
|
|
|
|
status = _cairo_xlib_surface_upload(dst, op, src_pattern,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
dst_x, dst_y,
|
|
|
|
|
width, height,
|
|
|
|
|
clip_region);
|
|
|
|
|
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (dst-> base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
|
2009-07-31 13:17:24 +01:00
|
|
|
status =
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_acquire_pattern_surfaces (display, dst,
|
2009-07-31 13:17:24 +01:00
|
|
|
src_pattern, mask_pattern,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
mask_x, mask_y,
|
|
|
|
|
width, height,
|
|
|
|
|
&src, &mask,
|
|
|
|
|
&src_attr, &mask_attr);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2010-04-18 23:20:02 +02:00
|
|
|
goto BAIL0;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2007-05-02 21:17:39 +01:00
|
|
|
/* check for fallback surfaces that we cannot handle ... */
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
assert (_cairo_surface_is_xlib (&src->base));
|
|
|
|
|
assert (mask == NULL || _cairo_surface_is_xlib (&mask->base));
|
|
|
|
|
|
|
|
|
|
if (mask != NULL && ! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (mask)) {
|
|
|
|
|
status = UNSUPPORTED ("unsupported mask");
|
2007-05-02 21:17:39 +01:00
|
|
|
goto BAIL;
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-16 03:02:35 +00:00
|
|
|
operation = _recategorize_composite_operation (dst, op, src, &src_attr,
|
2005-07-15 13:45:19 +00:00
|
|
|
mask_pattern != NULL);
|
2005-06-20 15:48:46 +00:00
|
|
|
if (operation == DO_UNSUPPORTED) {
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
status = UNSUPPORTED ("unsupported operation");
|
2006-06-22 22:38:17 -07:00
|
|
|
goto BAIL;
|
2005-06-20 15:48:46 +00:00
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-07-15 13:45:19 +00:00
|
|
|
switch (operation)
|
2005-06-20 15:48:46 +00:00
|
|
|
{
|
2005-07-15 13:45:19 +00:00
|
|
|
case DO_RENDER:
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_set_attributes (display,
|
|
|
|
|
src, &src_attr,
|
2008-11-04 18:42:05 +00:00
|
|
|
dst_x + width / 2.,
|
|
|
|
|
dst_y + height / 2.);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2007-10-19 22:45:15 +01:00
|
|
|
goto BAIL;
|
|
|
|
|
|
2009-09-02 00:34:37 +01:00
|
|
|
status = _cairo_xlib_surface_set_clip_region (dst, clip_region);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
goto BAIL;
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_ensure_dst_picture (display, dst);
|
2005-05-17 06:05:13 +00:00
|
|
|
if (mask) {
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_set_attributes (display,
|
|
|
|
|
mask, &mask_attr,
|
2008-11-04 18:42:05 +00:00
|
|
|
dst_x + width / 2.,
|
|
|
|
|
dst_y + height/ 2.);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2006-06-22 22:38:17 -07:00
|
|
|
goto BAIL;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderComposite (display->display,
|
2005-12-16 03:02:35 +00:00
|
|
|
_render_operator (op),
|
2005-08-16 18:22:16 +00:00
|
|
|
src->src_picture,
|
|
|
|
|
mask->src_picture,
|
|
|
|
|
dst->dst_picture,
|
|
|
|
|
src_x + src_attr.x_offset,
|
|
|
|
|
src_y + src_attr.y_offset,
|
|
|
|
|
mask_x + mask_attr.x_offset,
|
|
|
|
|
mask_y + mask_attr.y_offset,
|
|
|
|
|
dst_x, dst_y,
|
|
|
|
|
width, height);
|
2005-05-17 06:05:13 +00:00
|
|
|
} else {
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderComposite (display->display,
|
2005-12-16 03:02:35 +00:00
|
|
|
_render_operator (op),
|
2005-05-26 11:35:44 +00:00
|
|
|
src->src_picture,
|
2005-03-03 18:39:06 +00:00
|
|
|
0,
|
2005-05-26 11:35:44 +00:00
|
|
|
dst->dst_picture,
|
2005-03-03 18:39:06 +00:00
|
|
|
src_x + src_attr.x_offset,
|
|
|
|
|
src_y + src_attr.y_offset,
|
|
|
|
|
0, 0,
|
2005-03-17 12:57:42 +00:00
|
|
|
dst_x, dst_y,
|
2005-03-03 18:39:06 +00:00
|
|
|
width, height);
|
|
|
|
|
}
|
2005-08-08 13:46:11 +00:00
|
|
|
|
2005-07-15 13:45:19 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DO_XCOPYAREA:
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_get_gc (display, dst, &gc);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2007-03-16 19:35:02 +00:00
|
|
|
goto BAIL;
|
2008-10-07 21:05:57 +01:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
is_integer_translation =
|
|
|
|
|
_cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity);
|
2008-10-07 21:05:57 +01:00
|
|
|
/* This is a pre-condition for DO_XCOPYAREA. */
|
|
|
|
|
assert (is_integer_translation);
|
|
|
|
|
|
2009-09-02 00:34:37 +01:00
|
|
|
if (clip_region == NULL) {
|
2010-04-18 23:20:02 +02:00
|
|
|
XCopyArea (display->display, src->drawable, dst->drawable, gc,
|
2009-09-02 00:34:37 +01:00
|
|
|
src_x + src_attr.x_offset + itx,
|
|
|
|
|
src_y + src_attr.y_offset + ity,
|
|
|
|
|
width, height,
|
|
|
|
|
dst_x, dst_y);
|
|
|
|
|
} else {
|
2010-04-29 18:20:59 +02:00
|
|
|
int n, num_rects, x, y;
|
2009-09-02 00:34:37 +01:00
|
|
|
|
2010-04-29 18:20:59 +02:00
|
|
|
x = src_x + src_attr.x_offset + itx - dst_x;
|
|
|
|
|
y = src_y + src_attr.y_offset + ity - dst_y;
|
2009-09-02 00:34:37 +01:00
|
|
|
|
|
|
|
|
num_rects = cairo_region_num_rectangles (clip_region);
|
|
|
|
|
for (n = 0; n < num_rects; n++) {
|
|
|
|
|
cairo_rectangle_int_t rect;
|
|
|
|
|
|
|
|
|
|
cairo_region_get_rectangle (clip_region, n, &rect);
|
2010-04-18 23:20:02 +02:00
|
|
|
XCopyArea (display->display, src->drawable, dst->drawable, gc,
|
2010-04-29 18:20:59 +02:00
|
|
|
rect.x + x, rect.y + y,
|
2009-09-02 00:34:37 +01:00
|
|
|
rect.width, rect.height,
|
|
|
|
|
rect.x, rect.y);
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-06-18 14:32:53 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_put_gc (display, dst, gc);
|
2005-07-15 13:45:19 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DO_XTILE:
|
2008-06-13 00:46:01 -04:00
|
|
|
/* This case is only used for bug fallbacks, though we also use it for
|
|
|
|
|
* the case where we don't have the RENDER extension, by forcing
|
|
|
|
|
* buggy_repeat to TRUE.
|
2005-06-20 15:48:46 +00:00
|
|
|
*
|
|
|
|
|
* We've checked that we have a repeating unscaled source in
|
2005-07-15 13:45:19 +00:00
|
|
|
* _recategorize_composite_operation.
|
2005-06-20 15:48:46 +00:00
|
|
|
*/
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_get_gc (display, dst, &gc);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2007-03-16 19:35:02 +00:00
|
|
|
goto BAIL;
|
2009-09-02 00:34:37 +01:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
is_integer_translation =
|
|
|
|
|
_cairo_matrix_is_integer_translation (&src_attr.matrix, &itx, &ity);
|
2007-04-10 13:57:41 -07:00
|
|
|
/* This is a pre-condition for DO_XTILE. */
|
|
|
|
|
assert (is_integer_translation);
|
2005-06-20 15:48:46 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XSetTSOrigin (display->display, gc,
|
2005-06-20 15:48:46 +00:00
|
|
|
- (itx + src_attr.x_offset), - (ity + src_attr.y_offset));
|
2010-04-18 23:20:02 +02:00
|
|
|
XSetTile (display->display, gc, src->drawable);
|
2009-09-02 00:34:37 +01:00
|
|
|
|
|
|
|
|
if (clip_region == NULL) {
|
2010-04-18 23:20:02 +02:00
|
|
|
XFillRectangle (display->display, dst->drawable, gc,
|
2009-09-02 00:34:37 +01:00
|
|
|
dst_x, dst_y, width, height);
|
|
|
|
|
} else {
|
|
|
|
|
int n, num_rects;
|
2005-06-20 15:48:46 +00:00
|
|
|
|
2009-09-02 00:34:37 +01:00
|
|
|
num_rects = cairo_region_num_rectangles (clip_region);
|
|
|
|
|
for (n = 0; n < num_rects; n++) {
|
|
|
|
|
cairo_rectangle_int_t rect;
|
|
|
|
|
|
|
|
|
|
cairo_region_get_rectangle (clip_region, n, &rect);
|
2010-04-18 23:20:02 +02:00
|
|
|
XFillRectangle (display->display, dst->drawable, gc,
|
2009-09-02 00:34:37 +01:00
|
|
|
rect.x, rect.y, rect.width, rect.height);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_put_gc (display, dst, gc);
|
2005-07-15 13:45:19 +00:00
|
|
|
break;
|
|
|
|
|
|
2006-07-31 11:47:45 -07:00
|
|
|
case DO_UNSUPPORTED:
|
2005-07-15 13:45:19 +00:00
|
|
|
default:
|
|
|
|
|
ASSERT_NOT_REACHED;
|
2005-06-20 15:48:46 +00:00
|
|
|
}
|
|
|
|
|
|
2005-12-16 03:02:35 +00:00
|
|
|
if (!_cairo_operator_bounded_by_source (op))
|
2005-08-19 12:55:00 +00:00
|
|
|
status = _cairo_surface_composite_fixup_unbounded (&dst->base,
|
|
|
|
|
&src_attr, src->width, src->height,
|
|
|
|
|
mask ? &mask_attr : NULL,
|
|
|
|
|
mask ? mask->width : 0,
|
|
|
|
|
mask ? mask->height : 0,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
mask_x, mask_y,
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
dst_x, dst_y, width, height,
|
|
|
|
|
clip_region);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2006-06-22 22:38:17 -07:00
|
|
|
BAIL:
|
2005-03-03 18:39:06 +00:00
|
|
|
if (mask)
|
2005-07-14 16:56:08 +00:00
|
|
|
_cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-07-14 16:56:08 +00:00
|
|
|
_cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
BAIL0:
|
|
|
|
|
cairo_device_release (&display->base);
|
|
|
|
|
|
2005-03-03 17:40:04 +00:00
|
|
|
return status;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2009-07-31 13:17:24 +01:00
|
|
|
/* XXX move this out of core and into acquire_pattern_surface() above. */
|
2008-05-27 04:44:08 -04:00
|
|
|
static cairo_int_status_t
|
|
|
|
|
_cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface,
|
|
|
|
|
const cairo_color_t *color,
|
|
|
|
|
cairo_rectangle_int_t *rects,
|
|
|
|
|
int num_rects)
|
|
|
|
|
{
|
2008-10-30 09:59:48 +00:00
|
|
|
cairo_status_t status;
|
2008-06-13 21:39:19 -04:00
|
|
|
cairo_solid_pattern_t solid;
|
|
|
|
|
cairo_surface_t *solid_surface = NULL;
|
|
|
|
|
cairo_surface_attributes_t attrs;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2009-09-02 00:34:37 +01:00
|
|
|
GC gc;
|
2008-05-27 04:44:08 -04:00
|
|
|
int i;
|
|
|
|
|
|
2010-04-19 09:53:00 +02:00
|
|
|
_cairo_pattern_init_solid (&solid, color);
|
2008-05-27 04:44:08 -04:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
status = _cairo_xlib_surface_get_gc (display, surface, &gc);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-06-13 21:39:19 -04:00
|
|
|
return status;
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
X_DEBUG ((display->display, "solid_fill_rectangles (dst=%x)", (unsigned int) surface->drawable));
|
2009-09-29 03:02:40 +01:00
|
|
|
|
2008-10-30 09:59:48 +00:00
|
|
|
status = _cairo_pattern_acquire_surface (&solid.base, &surface->base,
|
2008-06-13 21:39:19 -04:00
|
|
|
0, 0,
|
|
|
|
|
ARRAY_LENGTH (dither_pattern[0]),
|
|
|
|
|
ARRAY_LENGTH (dither_pattern),
|
2009-05-28 14:16:58 +01:00
|
|
|
CAIRO_PATTERN_ACQUIRE_NONE,
|
2008-06-13 21:39:19 -04:00
|
|
|
&solid_surface,
|
|
|
|
|
&attrs);
|
2009-09-02 00:34:37 +01:00
|
|
|
if (unlikely (status)) {
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_put_gc (display, surface, gc);
|
|
|
|
|
cairo_device_release (&display->base);
|
2009-09-02 00:34:37 +01:00
|
|
|
return status;
|
|
|
|
|
}
|
2008-05-27 04:44:08 -04:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
assert (_cairo_surface_is_xlib (solid_surface));
|
2008-05-27 04:44:08 -04:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XSetTSOrigin (display->display, gc,
|
2008-06-13 21:39:19 -04:00
|
|
|
- (surface->base.device_transform.x0 + attrs.x_offset),
|
|
|
|
|
- (surface->base.device_transform.y0 + attrs.y_offset));
|
2010-04-18 23:20:02 +02:00
|
|
|
XSetTile (display->display, gc,
|
2008-10-30 09:59:48 +00:00
|
|
|
((cairo_xlib_surface_t *) solid_surface)->drawable);
|
2008-05-27 04:44:08 -04:00
|
|
|
|
|
|
|
|
for (i = 0; i < num_rects; i++) {
|
2010-04-18 23:20:02 +02:00
|
|
|
XFillRectangle (display->display, surface->drawable, gc,
|
2008-05-27 04:44:08 -04:00
|
|
|
rects[i].x, rects[i].y,
|
|
|
|
|
rects[i].width, rects[i].height);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_put_gc (display, surface, gc);
|
2009-06-18 14:32:53 +01:00
|
|
|
|
2008-06-13 21:39:19 -04:00
|
|
|
_cairo_pattern_release_surface (&solid.base, solid_surface, &attrs);
|
2010-04-18 23:20:02 +02:00
|
|
|
|
|
|
|
|
cairo_device_release (&display->base);
|
2008-06-13 21:39:19 -04:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2008-05-27 04:44:08 -04:00
|
|
|
}
|
|
|
|
|
|
2003-10-27 18:40:55 +00:00
|
|
|
static cairo_int_status_t
|
2006-05-04 03:43:34 -07:00
|
|
|
_cairo_xlib_surface_fill_rectangles (void *abstract_surface,
|
|
|
|
|
cairo_operator_t op,
|
|
|
|
|
const cairo_color_t *color,
|
2007-06-18 16:56:24 -07:00
|
|
|
cairo_rectangle_int_t *rects,
|
2008-05-27 04:44:08 -04:00
|
|
|
int num_rects)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2003-10-27 18:40:55 +00:00
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2003-09-30 18:56:22 +00:00
|
|
|
XRenderColor render_color;
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
cairo_status_t status;
|
2007-06-18 17:33:44 -07:00
|
|
|
int i;
|
2003-09-30 18:56:22 +00:00
|
|
|
|
2007-08-30 10:16:00 +02:00
|
|
|
if (!CAIRO_SURFACE_RENDER_SUPPORTS_OPERATOR (surface, op))
|
|
|
|
|
return CAIRO_INT_STATUS_UNSUPPORTED;
|
|
|
|
|
|
|
|
|
|
if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) {
|
2008-05-27 04:44:08 -04:00
|
|
|
if (op == CAIRO_OPERATOR_CLEAR ||
|
2008-05-10 08:11:54 +01:00
|
|
|
((op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER) &&
|
|
|
|
|
CAIRO_COLOR_IS_OPAQUE (color)))
|
|
|
|
|
{
|
|
|
|
|
return _cairo_xlib_surface_solid_fill_rectangles (surface, color,
|
|
|
|
|
rects, num_rects);
|
2008-05-27 04:44:08 -04:00
|
|
|
}
|
2008-05-10 08:11:54 +01:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("no support for FillRectangles with this op");
|
2008-05-27 04:44:08 -04:00
|
|
|
}
|
2003-09-30 18:56:22 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
X_DEBUG ((display->display, "fill_rectangles (dst=%x)", (unsigned int) surface->drawable));
|
2009-09-29 03:02:40 +01:00
|
|
|
|
2003-09-30 18:56:22 +00:00
|
|
|
render_color.red = color->red_short;
|
|
|
|
|
render_color.green = color->green_short;
|
|
|
|
|
render_color.blue = color->blue_short;
|
|
|
|
|
render_color.alpha = color->alpha_short;
|
|
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
status = _cairo_xlib_surface_set_clip_region (surface, NULL);
|
|
|
|
|
assert (status == CAIRO_STATUS_SUCCESS);
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_ensure_dst_picture (display, surface);
|
2008-10-25 11:33:52 +01:00
|
|
|
if (num_rects == 1) {
|
|
|
|
|
/* Take advantage of the protocol compaction that libXrender performs
|
|
|
|
|
* to amalgamate sequences of XRenderFillRectangle().
|
|
|
|
|
*/
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderFillRectangle (display->display,
|
2008-10-25 11:33:52 +01:00
|
|
|
_render_operator (op),
|
|
|
|
|
surface->dst_picture,
|
|
|
|
|
&render_color,
|
|
|
|
|
rects->x,
|
|
|
|
|
rects->y,
|
|
|
|
|
rects->width,
|
|
|
|
|
rects->height);
|
|
|
|
|
} else {
|
2008-11-25 11:45:30 +00:00
|
|
|
XRectangle static_xrects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)];
|
|
|
|
|
XRectangle *xrects = static_xrects;
|
|
|
|
|
|
2008-10-25 11:33:52 +01:00
|
|
|
if (num_rects > ARRAY_LENGTH (static_xrects)) {
|
|
|
|
|
xrects = _cairo_malloc_ab (num_rects, sizeof (XRectangle));
|
2010-04-18 23:20:02 +02:00
|
|
|
if (unlikely (xrects == NULL)) {
|
|
|
|
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
goto BAIL;
|
|
|
|
|
}
|
2008-10-25 11:33:52 +01:00
|
|
|
}
|
2007-06-18 17:33:44 -07:00
|
|
|
|
2008-10-25 11:33:52 +01:00
|
|
|
for (i = 0; i < num_rects; i++) {
|
|
|
|
|
xrects[i].x = rects[i].x;
|
|
|
|
|
xrects[i].y = rects[i].y;
|
|
|
|
|
xrects[i].width = rects[i].width;
|
|
|
|
|
xrects[i].height = rects[i].height;
|
|
|
|
|
}
|
2007-06-18 17:33:44 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderFillRectangles (display->display,
|
2008-10-25 11:33:52 +01:00
|
|
|
_render_operator (op),
|
|
|
|
|
surface->dst_picture,
|
|
|
|
|
&render_color, xrects, num_rects);
|
2007-06-18 17:33:44 -07:00
|
|
|
|
2008-10-25 11:33:52 +01:00
|
|
|
if (xrects != static_xrects)
|
|
|
|
|
free (xrects);
|
|
|
|
|
}
|
2003-09-30 18:56:22 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
BAIL:
|
|
|
|
|
cairo_device_release (&display->base);
|
|
|
|
|
return status;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
#define CAIRO_FIXED_16_16_MIN -32768
|
|
|
|
|
#define CAIRO_FIXED_16_16_MAX 32767
|
2008-08-27 21:14:51 -07:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
static cairo_bool_t
|
|
|
|
|
_line_exceeds_16_16 (const cairo_line_t *line)
|
|
|
|
|
{
|
|
|
|
|
return
|
2009-11-04 13:59:58 +01:00
|
|
|
line->p1.x < _cairo_fixed_from_int (CAIRO_FIXED_16_16_MIN) ||
|
|
|
|
|
line->p1.x > _cairo_fixed_from_int (CAIRO_FIXED_16_16_MAX) ||
|
|
|
|
|
line->p2.x < _cairo_fixed_from_int (CAIRO_FIXED_16_16_MIN) ||
|
|
|
|
|
line->p2.x > _cairo_fixed_from_int (CAIRO_FIXED_16_16_MAX) ||
|
|
|
|
|
line->p1.y < _cairo_fixed_from_int (CAIRO_FIXED_16_16_MIN) ||
|
|
|
|
|
line->p1.y > _cairo_fixed_from_int (CAIRO_FIXED_16_16_MAX) ||
|
|
|
|
|
line->p2.y < _cairo_fixed_from_int (CAIRO_FIXED_16_16_MIN) ||
|
|
|
|
|
line->p2.y > _cairo_fixed_from_int (CAIRO_FIXED_16_16_MAX);
|
2005-08-08 13:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
static void
|
|
|
|
|
_project_line_x_onto_16_16 (const cairo_line_t *line,
|
|
|
|
|
cairo_fixed_t top,
|
|
|
|
|
cairo_fixed_t bottom,
|
|
|
|
|
XLineFixed *out)
|
2005-08-08 13:46:11 +00:00
|
|
|
{
|
2009-09-11 14:59:58 +01:00
|
|
|
cairo_point_double_t p1, p2;
|
|
|
|
|
double m;
|
2007-06-27 12:34:35 +01:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
p1.x = _cairo_fixed_to_double (line->p1.x);
|
|
|
|
|
p1.y = _cairo_fixed_to_double (line->p1.y);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
p2.x = _cairo_fixed_to_double (line->p2.x);
|
|
|
|
|
p2.y = _cairo_fixed_to_double (line->p2.y);
|
2005-08-08 13:46:11 +00:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
m = (p2.x - p1.x) / (p2.y - p1.y);
|
|
|
|
|
out->p1.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (top - line->p1.y));
|
|
|
|
|
out->p2.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (bottom - line->p1.y));
|
2005-08-08 13:46:11 +00:00
|
|
|
}
|
|
|
|
|
|
2003-10-27 18:40:55 +00:00
|
|
|
static cairo_int_status_t
|
2005-12-16 03:02:35 +00:00
|
|
|
_cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
|
2008-10-22 19:24:44 +01:00
|
|
|
const cairo_pattern_t *pattern,
|
2003-10-27 18:40:55 +00:00
|
|
|
void *abstract_dst,
|
2005-08-08 18:35:22 +00:00
|
|
|
cairo_antialias_t antialias,
|
2005-01-27 10:46:20 +00:00
|
|
|
int src_x,
|
|
|
|
|
int src_y,
|
|
|
|
|
int dst_x,
|
|
|
|
|
int dst_y,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
unsigned int height,
|
2003-09-30 18:56:22 +00:00
|
|
|
cairo_trapezoid_t *traps,
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
int num_traps,
|
|
|
|
|
cairo_region_t *clip_region)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2005-03-03 17:40:04 +00:00
|
|
|
cairo_surface_attributes_t attributes;
|
|
|
|
|
cairo_xlib_surface_t *dst = abstract_dst;
|
|
|
|
|
cairo_xlib_surface_t *src;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2005-03-03 17:40:04 +00:00
|
|
|
cairo_int_status_t status;
|
2005-06-20 15:48:46 +00:00
|
|
|
composite_operation_t operation;
|
2005-03-03 17:40:04 +00:00
|
|
|
int render_reference_x, render_reference_y;
|
|
|
|
|
int render_src_x, render_src_y;
|
2005-08-08 18:35:22 +00:00
|
|
|
XRenderPictFormat *pict_format;
|
2009-09-11 14:59:58 +01:00
|
|
|
XTrapezoid xtraps_stack[CAIRO_STACK_ARRAY_LENGTH (XTrapezoid)];
|
|
|
|
|
XTrapezoid *xtraps = xtraps_stack;
|
|
|
|
|
int i;
|
2003-10-30 18:39:20 +00:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (! CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst))
|
|
|
|
|
return UNSUPPORTED ("XRender does not support CompositeTrapezoids");
|
2005-06-20 15:48:46 +00:00
|
|
|
|
2005-12-16 03:02:35 +00:00
|
|
|
operation = _categorize_composite_operation (dst, op, pattern, TRUE);
|
2005-06-20 15:48:46 +00:00
|
|
|
if (operation == DO_UNSUPPORTED)
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("unsupported operation");
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (dst->base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
X_DEBUG ((display->display, "composite_trapezoids (dst=%x)", (unsigned int) dst->drawable));
|
2009-09-29 03:02:40 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_acquire_pattern_surface (display,
|
|
|
|
|
dst,
|
2009-07-31 13:17:24 +01:00
|
|
|
pattern,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
width, height,
|
|
|
|
|
&src, &attributes);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2010-04-18 23:20:02 +02:00
|
|
|
goto BAIL0;
|
2005-06-20 15:48:46 +00:00
|
|
|
|
2008-10-10 14:00:32 +01:00
|
|
|
operation = _recategorize_composite_operation (dst, op, src,
|
|
|
|
|
&attributes, TRUE);
|
2005-06-20 15:48:46 +00:00
|
|
|
if (operation == DO_UNSUPPORTED) {
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
status = UNSUPPORTED ("unsupported operation");
|
2006-06-22 22:38:17 -07:00
|
|
|
goto BAIL;
|
2005-06-20 15:48:46 +00:00
|
|
|
}
|
2005-08-08 18:35:22 +00:00
|
|
|
|
|
|
|
|
switch (antialias) {
|
|
|
|
|
case CAIRO_ANTIALIAS_NONE:
|
2008-10-11 19:52:28 +01:00
|
|
|
pict_format =
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_display_get_xrender_format (display,
|
2008-10-11 19:52:28 +01:00
|
|
|
CAIRO_FORMAT_A1);
|
2005-08-08 18:35:22 +00:00
|
|
|
break;
|
2006-07-31 11:47:45 -07:00
|
|
|
case CAIRO_ANTIALIAS_GRAY:
|
|
|
|
|
case CAIRO_ANTIALIAS_SUBPIXEL:
|
|
|
|
|
case CAIRO_ANTIALIAS_DEFAULT:
|
2005-08-08 18:35:22 +00:00
|
|
|
default:
|
2008-10-11 19:52:28 +01:00
|
|
|
pict_format =
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_display_get_xrender_format (display,
|
2008-10-11 19:52:28 +01:00
|
|
|
CAIRO_FORMAT_A8);
|
2005-08-08 18:35:22 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
status = _cairo_xlib_surface_set_clip_region (dst, clip_region);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
goto BAIL;
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_ensure_dst_picture (display, dst);
|
2010-06-11 11:16:42 +01:00
|
|
|
_cairo_xlib_surface_set_precision (display, dst, antialias);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_set_attributes (display,
|
|
|
|
|
src, &attributes,
|
2008-11-04 18:42:05 +00:00
|
|
|
dst_x + width / 2.,
|
|
|
|
|
dst_y + height / 2.);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2006-06-22 22:38:17 -07:00
|
|
|
goto BAIL;
|
2005-08-08 13:46:11 +00:00
|
|
|
|
2009-09-11 14:59:58 +01:00
|
|
|
if (num_traps > ARRAY_LENGTH (xtraps_stack)) {
|
|
|
|
|
xtraps = _cairo_malloc_ab (num_traps, sizeof (XTrapezoid));
|
|
|
|
|
if (unlikely (xtraps == NULL)) {
|
|
|
|
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
goto BAIL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < num_traps; i++) {
|
|
|
|
|
/* top/bottom will be clamped to surface bounds */
|
|
|
|
|
xtraps[i].top = _cairo_fixed_to_16_16(traps[i].top);
|
|
|
|
|
xtraps[i].bottom = _cairo_fixed_to_16_16(traps[i].bottom);
|
|
|
|
|
|
|
|
|
|
/* However, all the other coordinates will have been left untouched so
|
|
|
|
|
* as not to introduce numerical error. Recompute them if they
|
|
|
|
|
* exceed the 16.16 limits.
|
|
|
|
|
*/
|
|
|
|
|
if (unlikely (_line_exceeds_16_16 (&traps[i].left))) {
|
|
|
|
|
_project_line_x_onto_16_16 (&traps[i].left,
|
|
|
|
|
traps[i].top,
|
|
|
|
|
traps[i].bottom,
|
|
|
|
|
&xtraps[i].left);
|
|
|
|
|
xtraps[i].left.p1.y = xtraps[i].top;
|
|
|
|
|
xtraps[i].left.p2.y = xtraps[i].bottom;
|
|
|
|
|
} else {
|
|
|
|
|
xtraps[i].left.p1.x = _cairo_fixed_to_16_16(traps[i].left.p1.x);
|
|
|
|
|
xtraps[i].left.p1.y = _cairo_fixed_to_16_16(traps[i].left.p1.y);
|
|
|
|
|
xtraps[i].left.p2.x = _cairo_fixed_to_16_16(traps[i].left.p2.x);
|
|
|
|
|
xtraps[i].left.p2.y = _cairo_fixed_to_16_16(traps[i].left.p2.y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unlikely (_line_exceeds_16_16 (&traps[i].right))) {
|
|
|
|
|
_project_line_x_onto_16_16 (&traps[i].right,
|
|
|
|
|
traps[i].top,
|
|
|
|
|
traps[i].bottom,
|
|
|
|
|
&xtraps[i].right);
|
|
|
|
|
xtraps[i].right.p1.y = xtraps[i].top;
|
|
|
|
|
xtraps[i].right.p2.y = xtraps[i].bottom;
|
|
|
|
|
} else {
|
|
|
|
|
xtraps[i].right.p1.x = _cairo_fixed_to_16_16(traps[i].right.p1.x);
|
|
|
|
|
xtraps[i].right.p1.y = _cairo_fixed_to_16_16(traps[i].right.p1.y);
|
|
|
|
|
xtraps[i].right.p2.x = _cairo_fixed_to_16_16(traps[i].right.p2.x);
|
|
|
|
|
xtraps[i].right.p2.y = _cairo_fixed_to_16_16(traps[i].right.p2.y);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-04 11:15:57 +01:00
|
|
|
if (xtraps[0].left.p1.y < xtraps[0].left.p2.y) {
|
|
|
|
|
render_reference_x = _cairo_fixed_16_16_floor (xtraps[0].left.p1.x);
|
|
|
|
|
render_reference_y = _cairo_fixed_16_16_floor (xtraps[0].left.p1.y);
|
|
|
|
|
} else {
|
|
|
|
|
render_reference_x = _cairo_fixed_16_16_floor (xtraps[0].left.p2.x);
|
|
|
|
|
render_reference_y = _cairo_fixed_16_16_floor (xtraps[0].left.p2.y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render_src_x = src_x + render_reference_x - dst_x;
|
|
|
|
|
render_src_y = src_y + render_reference_y - dst_y;
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderCompositeTrapezoids (display->display,
|
2009-09-11 14:59:58 +01:00
|
|
|
_render_operator (op),
|
|
|
|
|
src->src_picture, dst->dst_picture,
|
|
|
|
|
pict_format,
|
|
|
|
|
render_src_x + attributes.x_offset,
|
|
|
|
|
render_src_y + attributes.y_offset,
|
|
|
|
|
xtraps, num_traps);
|
|
|
|
|
|
|
|
|
|
if (xtraps != xtraps_stack)
|
2009-09-21 13:50:00 +01:00
|
|
|
free (xtraps);
|
|
|
|
|
|
|
|
|
|
if (! _cairo_operator_bounded_by_mask (op)) {
|
|
|
|
|
cairo_traps_t _traps;
|
|
|
|
|
cairo_box_t box;
|
|
|
|
|
cairo_rectangle_int_t extents;
|
2009-09-11 14:59:58 +01:00
|
|
|
|
2005-08-08 13:46:11 +00:00
|
|
|
/* XRenderCompositeTrapezoids() creates a mask only large enough for the
|
|
|
|
|
* trapezoids themselves, but if the operator is unbounded, then we need
|
2009-09-21 13:50:00 +01:00
|
|
|
* to actually composite all the way out to the bounds.
|
2005-08-08 13:46:11 +00:00
|
|
|
*/
|
2009-09-21 13:50:00 +01:00
|
|
|
/* XXX: update the interface to pass composite rects */
|
|
|
|
|
_traps.traps = traps;
|
|
|
|
|
_traps.num_traps = num_traps;
|
|
|
|
|
_cairo_traps_extents (&_traps, &box);
|
|
|
|
|
_cairo_box_round_to_rectangle (&box, &extents);
|
|
|
|
|
|
2005-08-16 18:22:16 +00:00
|
|
|
status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
|
2009-09-21 13:50:00 +01:00
|
|
|
&attributes,
|
|
|
|
|
src->width, src->height,
|
|
|
|
|
extents.width, extents.height,
|
2005-08-16 18:22:16 +00:00
|
|
|
src_x, src_y,
|
2009-09-21 13:50:00 +01:00
|
|
|
-extents.x + dst_x, -extents.y + dst_y,
|
|
|
|
|
dst_x, dst_y,
|
|
|
|
|
width, height,
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
clip_region);
|
2005-08-08 13:46:11 +00:00
|
|
|
}
|
2005-03-03 17:40:04 +00:00
|
|
|
|
2006-06-22 22:38:17 -07:00
|
|
|
BAIL:
|
2005-07-14 16:56:08 +00:00
|
|
|
_cairo_pattern_release_surface (pattern, &src->base, &attributes);
|
2010-04-18 23:20:02 +02:00
|
|
|
BAIL0:
|
|
|
|
|
cairo_device_release (&display->base);
|
2005-01-27 10:46:20 +00:00
|
|
|
|
2005-03-03 17:40:04 +00:00
|
|
|
return status;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
static cairo_bool_t
|
2006-05-04 03:43:34 -07:00
|
|
|
_cairo_xlib_surface_get_extents (void *abstract_surface,
|
2007-06-18 16:56:24 -07:00
|
|
|
cairo_rectangle_int_t *rectangle)
|
2005-04-19 16:29:04 +00:00
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
|
|
|
|
|
rectangle->x = 0;
|
|
|
|
|
rectangle->y = 0;
|
|
|
|
|
|
2005-05-17 06:05:13 +00:00
|
|
|
rectangle->width = surface->width;
|
|
|
|
|
rectangle->height = surface->height;
|
2005-04-19 16:29:04 +00:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return TRUE;
|
2005-04-19 16:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-21 06:52:13 +00:00
|
|
|
static void
|
|
|
|
|
_cairo_xlib_surface_get_font_options (void *abstract_surface,
|
|
|
|
|
cairo_font_options_t *options)
|
|
|
|
|
{
|
2005-07-27 15:04:03 +00:00
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2009-09-01 23:12:43 +01:00
|
|
|
*options = *_cairo_xlib_screen_get_font_options (surface->screen);
|
2006-03-27 13:49:58 -08:00
|
|
|
}
|
|
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
static void
|
|
|
|
|
_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font);
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
|
|
|
|
cairo_scaled_font_t *scaled_font);
|
|
|
|
|
|
2007-05-02 10:00:22 +01:00
|
|
|
static cairo_bool_t
|
|
|
|
|
_cairo_xlib_surface_is_similar (void *surface_a,
|
2010-04-19 09:51:26 +02:00
|
|
|
void *surface_b)
|
2007-05-02 10:00:22 +01:00
|
|
|
{
|
2010-04-19 09:51:26 +02:00
|
|
|
return _cairo_xlib_surface_same_screen (surface_a, surface_b);
|
2007-05-02 10:00:22 +01:00
|
|
|
}
|
|
|
|
|
|
2005-01-13 06:50:23 +00:00
|
|
|
static const cairo_surface_backend_t cairo_xlib_surface_backend = {
|
2006-02-27 23:11:32 -08:00
|
|
|
CAIRO_SURFACE_TYPE_XLIB,
|
2003-10-27 18:40:55 +00:00
|
|
|
_cairo_xlib_surface_create_similar,
|
2005-03-16 12:08:41 +00:00
|
|
|
_cairo_xlib_surface_finish,
|
2005-01-31 08:50:22 +00:00
|
|
|
_cairo_xlib_surface_acquire_source_image,
|
|
|
|
|
_cairo_xlib_surface_release_source_image,
|
|
|
|
|
_cairo_xlib_surface_acquire_dest_image,
|
|
|
|
|
_cairo_xlib_surface_release_dest_image,
|
|
|
|
|
_cairo_xlib_surface_clone_similar,
|
2003-10-27 18:40:55 +00:00
|
|
|
_cairo_xlib_surface_composite,
|
|
|
|
|
_cairo_xlib_surface_fill_rectangles,
|
|
|
|
|
_cairo_xlib_surface_composite_trapezoids,
|
2008-07-11 00:59:47 +03:00
|
|
|
NULL, /* create_span_renderer */
|
|
|
|
|
NULL, /* check_span_renderer */
|
2005-04-07 14:25:00 +00:00
|
|
|
NULL, /* copy_page */
|
|
|
|
|
NULL, /* show_page */
|
2005-04-19 16:29:04 +00:00
|
|
|
_cairo_xlib_surface_get_extents,
|
2006-03-08 21:08:57 -08:00
|
|
|
NULL, /* old_show_glyphs */
|
2005-08-31 15:08:02 +00:00
|
|
|
_cairo_xlib_surface_get_font_options,
|
2006-07-17 11:33:47 -07:00
|
|
|
NULL, /* flush */
|
2005-08-31 15:08:02 +00:00
|
|
|
NULL, /* mark_dirty_rectangle */
|
|
|
|
|
_cairo_xlib_surface_scaled_font_fini,
|
|
|
|
|
_cairo_xlib_surface_scaled_glyph_fini,
|
2006-03-08 21:08:57 -08:00
|
|
|
|
|
|
|
|
NULL, /* paint */
|
|
|
|
|
NULL, /* mask */
|
|
|
|
|
NULL, /* stroke */
|
|
|
|
|
NULL, /* fill */
|
|
|
|
|
_cairo_xlib_surface_show_glyphs,
|
2008-11-25 20:15:15 +01:00
|
|
|
|
|
|
|
|
_cairo_xlib_surface_snapshot,
|
2007-05-02 10:00:22 +01:00
|
|
|
_cairo_xlib_surface_is_similar,
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
|
2008-06-13 21:37:45 -04:00
|
|
|
NULL, /* fill_stroke */
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
|
2008-12-17 20:34:45 +00:00
|
|
|
_cairo_xlib_surface_create_solid_pattern_surface,
|
|
|
|
|
_cairo_xlib_surface_can_repaint_solid_pattern_surface
|
2003-09-30 18:56:22 +00:00
|
|
|
};
|
|
|
|
|
|
2005-04-14 14:42:26 +00:00
|
|
|
/**
|
|
|
|
|
* _cairo_surface_is_xlib:
|
|
|
|
|
* @surface: a #cairo_surface_t
|
2006-06-06 15:35:48 -07:00
|
|
|
*
|
2005-04-14 14:42:26 +00:00
|
|
|
* Checks if a surface is a #cairo_xlib_surface_t
|
2006-06-06 15:35:48 -07:00
|
|
|
*
|
2005-04-14 14:42:26 +00:00
|
|
|
* Return value: True if the surface is an xlib surface
|
|
|
|
|
**/
|
|
|
|
|
static cairo_bool_t
|
|
|
|
|
_cairo_surface_is_xlib (cairo_surface_t *surface)
|
|
|
|
|
{
|
|
|
|
|
return surface->backend == &cairo_xlib_surface_backend;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-02 10:08:04 +01:00
|
|
|
/* callback from CloseDisplay */
|
2007-04-17 12:03:07 +01:00
|
|
|
static void
|
2008-09-02 10:28:17 +01:00
|
|
|
_cairo_xlib_surface_detach_display (cairo_xlib_display_t *display, void *data)
|
2007-04-17 12:03:07 +01:00
|
|
|
{
|
2008-09-02 10:08:04 +01:00
|
|
|
cairo_xlib_surface_t *surface = cairo_container_of (data,
|
|
|
|
|
cairo_xlib_surface_t,
|
|
|
|
|
close_display_hook);
|
2008-09-02 10:28:17 +01:00
|
|
|
Display *dpy;
|
2007-04-17 12:03:07 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
dpy = display->display;
|
2007-04-17 12:03:07 +01:00
|
|
|
|
2009-09-29 03:02:40 +01:00
|
|
|
X_DEBUG ((dpy, "detach (drawable=%x)", (unsigned int) surface->drawable));
|
|
|
|
|
|
2007-04-17 12:03:07 +01:00
|
|
|
if (surface->dst_picture != None) {
|
|
|
|
|
XRenderFreePicture (dpy, surface->dst_picture);
|
|
|
|
|
surface->dst_picture = None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (surface->src_picture != None) {
|
|
|
|
|
XRenderFreePicture (dpy, surface->src_picture);
|
|
|
|
|
surface->src_picture = None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (surface->owns_pixmap) {
|
|
|
|
|
XFreePixmap (dpy, surface->drawable);
|
|
|
|
|
surface->drawable = None;
|
|
|
|
|
surface->owns_pixmap = FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-20 08:52:47 +00:00
|
|
|
static cairo_surface_t *
|
2009-09-01 23:12:43 +01:00
|
|
|
_cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
|
|
|
|
|
Drawable drawable,
|
|
|
|
|
Visual *visual,
|
|
|
|
|
XRenderPictFormat *xrender_format,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
int depth)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2003-10-27 18:40:55 +00:00
|
|
|
cairo_xlib_surface_t *surface;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
|
|
|
|
cairo_status_t status;
|
2008-02-08 17:36:59 -05:00
|
|
|
|
2009-09-20 18:46:19 +01:00
|
|
|
if (depth == 0) {
|
|
|
|
|
if (xrender_format) {
|
|
|
|
|
depth = xrender_format->depth;
|
2008-08-10 08:31:19 +01:00
|
|
|
|
2009-09-20 18:46:19 +01:00
|
|
|
/* XXX find matching visual for core/dithering fallbacks? */
|
|
|
|
|
} else if (visual) {
|
|
|
|
|
Screen *scr = screen->screen;
|
2005-03-15 16:25:30 +00:00
|
|
|
|
2009-09-20 18:46:19 +01:00
|
|
|
if (visual == DefaultVisualOfScreen (scr)) {
|
|
|
|
|
depth = DefaultDepthOfScreen (scr);
|
|
|
|
|
} else {
|
|
|
|
|
int j, k;
|
|
|
|
|
|
|
|
|
|
/* This is ugly, but we have to walk over all visuals
|
|
|
|
|
* for the display to find the correct depth.
|
|
|
|
|
*/
|
|
|
|
|
depth = 0;
|
|
|
|
|
for (j = 0; j < scr->ndepths; j++) {
|
|
|
|
|
Depth *d = &scr->depths[j];
|
|
|
|
|
for (k = 0; k < d->nvisuals; k++) {
|
|
|
|
|
if (&d->visuals[k] == visual) {
|
|
|
|
|
depth = d->depth;
|
|
|
|
|
goto found;
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-03-15 16:25:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-09-20 18:46:19 +01:00
|
|
|
|
|
|
|
|
if (depth == 0)
|
|
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
|
|
|
|
|
|
|
|
|
|
found:
|
2005-05-17 06:05:13 +00:00
|
|
|
;
|
2005-03-15 16:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
2008-08-10 08:31:19 +01:00
|
|
|
surface = malloc (sizeof (cairo_xlib_surface_t));
|
2009-09-01 23:12:43 +01:00
|
|
|
if (unlikely (surface == NULL))
|
2008-08-10 08:31:19 +01:00
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
2009-09-01 23:12:43 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (screen->device, &display);
|
|
|
|
|
if (unlikely (status)) {
|
|
|
|
|
free (surface);
|
|
|
|
|
return _cairo_surface_create_in_error (_cairo_error (status));
|
|
|
|
|
}
|
2008-08-10 08:31:19 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_display_get_xrender_version (display,
|
2009-09-01 23:12:43 +01:00
|
|
|
&surface->render_major,
|
|
|
|
|
&surface->render_minor);
|
2006-05-24 17:05:51 -07:00
|
|
|
if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) {
|
|
|
|
|
if (!xrender_format) {
|
2008-10-11 19:52:28 +01:00
|
|
|
if (visual) {
|
2010-04-18 23:20:02 +02:00
|
|
|
xrender_format = XRenderFindVisualFormat (display->display, visual);
|
2008-10-11 19:52:28 +01:00
|
|
|
} else if (depth == 1) {
|
|
|
|
|
xrender_format =
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_display_get_xrender_format (display,
|
2008-10-11 19:52:28 +01:00
|
|
|
CAIRO_FORMAT_A1);
|
|
|
|
|
}
|
2006-05-24 17:05:51 -07:00
|
|
|
}
|
|
|
|
|
} else {
|
2009-09-20 18:46:19 +01:00
|
|
|
/* we cannot use XRender for this surface, so ensure we don't try */
|
2008-10-10 14:00:32 +01:00
|
|
|
surface->render_major = -1;
|
|
|
|
|
surface->render_minor = -1;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
/* initialize and hook into the CloseDisplay callback */
|
|
|
|
|
surface->close_display_hook.func = _cairo_xlib_surface_detach_display;
|
|
|
|
|
_cairo_xlib_add_close_display_hook (display,
|
|
|
|
|
&surface->close_display_hook);
|
2010-05-06 10:46:49 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_device_release (&display->base);
|
|
|
|
|
|
2010-01-18 21:53:42 +00:00
|
|
|
_cairo_surface_init (&surface->base,
|
|
|
|
|
&cairo_xlib_surface_backend,
|
2010-04-18 23:20:02 +02:00
|
|
|
screen->device,
|
2006-05-24 17:05:51 -07:00
|
|
|
_xrender_format_to_content (xrender_format));
|
|
|
|
|
|
2010-05-06 10:46:49 +01:00
|
|
|
surface->screen = screen;
|
2006-05-24 17:05:51 -07:00
|
|
|
|
|
|
|
|
surface->drawable = drawable;
|
|
|
|
|
surface->owns_pixmap = FALSE;
|
|
|
|
|
surface->use_pixmap = 0;
|
|
|
|
|
surface->width = width;
|
|
|
|
|
surface->height = height;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
surface->buggy_repeat = ! _cairo_xlib_display_has_repeat (screen->device);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (! CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) {
|
2008-06-13 00:46:01 -04:00
|
|
|
/* so we can use the XTile fallback */
|
|
|
|
|
surface->buggy_repeat = TRUE;
|
|
|
|
|
}
|
2009-07-31 13:17:24 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
surface->buggy_pad_reflect = ! _cairo_xlib_display_has_reflect (screen->device);
|
2009-07-31 11:35:45 +01:00
|
|
|
if (! CAIRO_SURFACE_RENDER_HAS_EXTENDED_REPEAT (surface))
|
|
|
|
|
surface->buggy_pad_reflect = TRUE;
|
2005-06-20 15:48:46 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
surface->buggy_gradients = ! _cairo_xlib_display_has_gradients (screen->device);
|
2009-07-31 13:17:24 +01:00
|
|
|
if (! CAIRO_SURFACE_RENDER_HAS_GRADIENTS (surface))
|
|
|
|
|
surface->buggy_gradients = TRUE;
|
|
|
|
|
|
2005-05-26 11:35:44 +00:00
|
|
|
surface->dst_picture = None;
|
|
|
|
|
surface->src_picture = None;
|
2005-03-15 16:25:30 +00:00
|
|
|
|
2005-05-26 11:35:44 +00:00
|
|
|
surface->visual = visual;
|
2006-05-24 17:05:51 -07:00
|
|
|
surface->xrender_format = xrender_format;
|
2005-05-26 11:35:44 +00:00
|
|
|
surface->depth = depth;
|
2007-04-18 18:08:45 +01:00
|
|
|
surface->filter = CAIRO_FILTER_NEAREST;
|
2009-09-11 14:59:58 +01:00
|
|
|
surface->extend = CAIRO_EXTEND_NONE;
|
2009-10-16 16:48:54 +01:00
|
|
|
surface->has_component_alpha = FALSE;
|
2010-06-11 11:16:42 +01:00
|
|
|
surface->precision = PolyModePrecise;
|
2007-04-18 18:08:45 +01:00
|
|
|
surface->xtransform = identity;
|
2004-04-06 09:36:12 +00:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
surface->clip_region = NULL;
|
2007-04-19 20:24:27 +01:00
|
|
|
surface->clip_rects = surface->embedded_clip_rects;
|
2005-06-20 15:48:46 +00:00
|
|
|
surface->num_clip_rects = 0;
|
2008-10-31 02:03:41 +00:00
|
|
|
surface->clip_dirty = 0;
|
2005-06-20 15:48:46 +00:00
|
|
|
|
2008-03-19 14:23:35 -07:00
|
|
|
/*
|
|
|
|
|
* Compute the pixel format masks from either a XrenderFormat or
|
|
|
|
|
* else from a visual; failing that we assume the drawable is an
|
|
|
|
|
* alpha-only pixmap as it could only have been created that way
|
|
|
|
|
* through the cairo_xlib_surface_create_for_bitmap function.
|
|
|
|
|
*/
|
|
|
|
|
if (xrender_format) {
|
|
|
|
|
surface->a_mask = (unsigned long)
|
|
|
|
|
surface->xrender_format->direct.alphaMask
|
|
|
|
|
<< surface->xrender_format->direct.alpha;
|
|
|
|
|
surface->r_mask = (unsigned long)
|
|
|
|
|
surface->xrender_format->direct.redMask
|
|
|
|
|
<< surface->xrender_format->direct.red;
|
|
|
|
|
surface->g_mask = (unsigned long)
|
|
|
|
|
surface->xrender_format->direct.greenMask
|
|
|
|
|
<< surface->xrender_format->direct.green;
|
|
|
|
|
surface->b_mask = (unsigned long)
|
|
|
|
|
surface->xrender_format->direct.blueMask
|
|
|
|
|
<< surface->xrender_format->direct.blue;
|
|
|
|
|
} else if (visual) {
|
|
|
|
|
surface->a_mask = 0;
|
|
|
|
|
surface->r_mask = visual->red_mask;
|
|
|
|
|
surface->g_mask = visual->green_mask;
|
|
|
|
|
surface->b_mask = visual->blue_mask;
|
|
|
|
|
} else {
|
|
|
|
|
if (depth < 32)
|
|
|
|
|
surface->a_mask = (1 << depth) - 1;
|
|
|
|
|
else
|
|
|
|
|
surface->a_mask = 0xffffffff;
|
|
|
|
|
surface->r_mask = 0;
|
|
|
|
|
surface->g_mask = 0;
|
|
|
|
|
surface->b_mask = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-20 18:46:19 +01:00
|
|
|
return &surface->base;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
static Screen *
|
|
|
|
|
_cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
|
|
|
|
|
{
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
int s, d, v;
|
2005-07-20 18:52:31 +00:00
|
|
|
|
|
|
|
|
for (s = 0; s < ScreenCount (dpy); s++) {
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
Screen *screen;
|
|
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
screen = ScreenOfDisplay (dpy, s);
|
|
|
|
|
if (visual == DefaultVisualOfScreen (screen))
|
|
|
|
|
return screen;
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
for (d = 0; d < screen->ndepths; d++) {
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
Depth *depth;
|
|
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
depth = &screen->depths[d];
|
2005-07-26 22:36:00 +00:00
|
|
|
for (v = 0; v < depth->nvisuals; v++)
|
2005-07-20 18:52:31 +00:00
|
|
|
if (visual == &depth->visuals[v])
|
|
|
|
|
return screen;
|
|
|
|
|
}
|
|
|
|
|
}
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
|
2005-07-20 18:52:31 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-15 16:25:30 +00:00
|
|
|
/**
|
2005-05-13 17:54:43 +00:00
|
|
|
* cairo_xlib_surface_create:
|
2005-05-14 10:15:11 +00:00
|
|
|
* @dpy: an X Display
|
|
|
|
|
* @drawable: an X Drawable, (a Pixmap or a Window)
|
2005-05-17 06:05:13 +00:00
|
|
|
* @visual: the visual to use for drawing to @drawable. The depth
|
|
|
|
|
* of the visual must match the depth of the drawable.
|
|
|
|
|
* Currently, only TrueColor visuals are fully supported.
|
|
|
|
|
* @width: the current width of @drawable.
|
|
|
|
|
* @height: the current height of @drawable.
|
2005-03-15 16:25:30 +00:00
|
|
|
*
|
2005-05-13 17:54:43 +00:00
|
|
|
* Creates an Xlib surface that draws to the given drawable.
|
2005-05-17 06:05:13 +00:00
|
|
|
* The way that colors are represented in the drawable is specified
|
|
|
|
|
* by the provided visual.
|
|
|
|
|
*
|
2008-01-28 21:53:44 -05:00
|
|
|
* Note: If @drawable is a Window, then the function
|
2008-06-01 19:14:13 -04:00
|
|
|
* cairo_xlib_surface_set_size() must be called whenever the size of the
|
2005-05-17 06:05:13 +00:00
|
|
|
* window changes.
|
2005-03-15 16:25:30 +00:00
|
|
|
*
|
2007-06-13 18:59:22 -04:00
|
|
|
* When @drawable is a Window containing child windows then drawing to
|
|
|
|
|
* the created surface will be clipped by those child windows. When
|
|
|
|
|
* the created surface is used as a source, the contents of the
|
|
|
|
|
* children will be included.
|
|
|
|
|
*
|
2005-03-15 16:25:30 +00:00
|
|
|
* Return value: the newly created surface
|
|
|
|
|
**/
|
|
|
|
|
cairo_surface_t *
|
2005-05-17 06:05:13 +00:00
|
|
|
cairo_xlib_surface_create (Display *dpy,
|
|
|
|
|
Drawable drawable,
|
|
|
|
|
Visual *visual,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
2005-03-15 16:25:30 +00:00
|
|
|
{
|
2009-09-01 23:12:43 +01:00
|
|
|
Screen *scr;
|
|
|
|
|
cairo_xlib_screen_t *screen;
|
|
|
|
|
cairo_status_t status;
|
2005-07-20 18:52:31 +00:00
|
|
|
|
2009-09-06 10:17:40 +01:00
|
|
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) {
|
|
|
|
|
/* you're lying, and you know it! */
|
2010-11-08 14:17:37 -05:00
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
2009-09-06 10:17:40 +01:00
|
|
|
}
|
|
|
|
|
|
2009-09-01 23:12:43 +01:00
|
|
|
scr = _cairo_xlib_screen_from_visual (dpy, visual);
|
|
|
|
|
if (scr == NULL)
|
2008-01-16 16:23:23 +00:00
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2009-09-01 23:12:43 +01:00
|
|
|
status = _cairo_xlib_screen_get (dpy, scr, &screen);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return _cairo_surface_create_in_error (status);
|
|
|
|
|
|
2009-09-29 03:02:40 +01:00
|
|
|
X_DEBUG ((dpy, "create (drawable=%x)", (unsigned int) drawable));
|
|
|
|
|
|
2010-05-06 10:46:49 +01:00
|
|
|
return _cairo_xlib_surface_create_internal (screen, drawable,
|
|
|
|
|
visual, NULL,
|
|
|
|
|
width, height, 0);
|
2005-03-15 16:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2005-05-17 06:05:13 +00:00
|
|
|
* cairo_xlib_surface_create_for_bitmap:
|
2005-05-14 10:15:11 +00:00
|
|
|
* @dpy: an X Display
|
2005-05-17 12:21:56 +00:00
|
|
|
* @bitmap: an X Drawable, (a depth-1 Pixmap)
|
2005-07-20 18:52:31 +00:00
|
|
|
* @screen: the X Screen associated with @bitmap
|
2005-05-17 06:05:13 +00:00
|
|
|
* @width: the current width of @bitmap.
|
|
|
|
|
* @height: the current height of @bitmap.
|
2006-06-06 15:35:48 -07:00
|
|
|
*
|
2005-05-17 06:05:13 +00:00
|
|
|
* Creates an Xlib surface that draws to the given bitmap.
|
2008-01-28 20:48:48 -05:00
|
|
|
* This will be drawn to as a %CAIRO_FORMAT_A1 object.
|
2005-05-17 06:05:13 +00:00
|
|
|
*
|
|
|
|
|
* Return value: the newly created surface
|
|
|
|
|
**/
|
|
|
|
|
cairo_surface_t *
|
|
|
|
|
cairo_xlib_surface_create_for_bitmap (Display *dpy,
|
|
|
|
|
Pixmap bitmap,
|
2009-09-01 23:12:43 +01:00
|
|
|
Screen *scr,
|
2005-05-17 06:05:13 +00:00
|
|
|
int width,
|
|
|
|
|
int height)
|
|
|
|
|
{
|
2009-09-01 23:12:43 +01:00
|
|
|
cairo_xlib_screen_t *screen;
|
|
|
|
|
cairo_status_t status;
|
|
|
|
|
|
2009-09-06 10:17:40 +01:00
|
|
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
|
2010-11-08 14:17:37 -05:00
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
2009-09-06 10:17:40 +01:00
|
|
|
|
2009-09-01 23:12:43 +01:00
|
|
|
status = _cairo_xlib_screen_get (dpy, scr, &screen);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return _cairo_surface_create_in_error (status);
|
|
|
|
|
|
2009-09-29 03:02:40 +01:00
|
|
|
X_DEBUG ((dpy, "create_for_bitmap (drawable=%x)", (unsigned int) bitmap));
|
|
|
|
|
|
2010-05-06 10:46:49 +01:00
|
|
|
return _cairo_xlib_surface_create_internal (screen, bitmap,
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
width, height, 1);
|
2005-05-17 06:05:13 +00:00
|
|
|
}
|
|
|
|
|
|
2007-08-31 20:52:43 -04:00
|
|
|
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
2005-05-17 06:05:13 +00:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_create_with_xrender_format:
|
|
|
|
|
* @dpy: an X Display
|
|
|
|
|
* @drawable: an X Drawable, (a Pixmap or a Window)
|
2005-07-20 18:52:31 +00:00
|
|
|
* @screen: the X Screen associated with @drawable
|
2005-05-17 06:05:13 +00:00
|
|
|
* @format: the picture format to use for drawing to @drawable. The depth
|
|
|
|
|
* of @format must match the depth of the drawable.
|
|
|
|
|
* @width: the current width of @drawable.
|
|
|
|
|
* @height: the current height of @drawable.
|
|
|
|
|
*
|
2005-05-13 17:54:43 +00:00
|
|
|
* Creates an Xlib surface that draws to the given drawable.
|
|
|
|
|
* The way that colors are represented in the drawable is specified
|
2005-05-17 06:05:13 +00:00
|
|
|
* by the provided picture format.
|
|
|
|
|
*
|
2008-01-28 21:53:44 -05:00
|
|
|
* Note: If @drawable is a Window, then the function
|
2008-06-01 19:14:13 -04:00
|
|
|
* cairo_xlib_surface_set_size() must be called whenever the size of the
|
2005-05-17 06:05:13 +00:00
|
|
|
* window changes.
|
2005-03-15 16:25:30 +00:00
|
|
|
*
|
|
|
|
|
* Return value: the newly created surface
|
|
|
|
|
**/
|
|
|
|
|
cairo_surface_t *
|
2005-05-17 06:05:13 +00:00
|
|
|
cairo_xlib_surface_create_with_xrender_format (Display *dpy,
|
|
|
|
|
Drawable drawable,
|
2009-09-01 23:12:43 +01:00
|
|
|
Screen *scr,
|
2005-05-17 06:05:13 +00:00
|
|
|
XRenderPictFormat *format,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
2005-03-15 16:25:30 +00:00
|
|
|
{
|
2009-09-01 23:12:43 +01:00
|
|
|
cairo_xlib_screen_t *screen;
|
|
|
|
|
cairo_status_t status;
|
|
|
|
|
|
2009-09-06 10:17:40 +01:00
|
|
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
|
2010-11-08 14:17:37 -05:00
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
2009-09-06 10:17:40 +01:00
|
|
|
|
2009-09-01 23:12:43 +01:00
|
|
|
status = _cairo_xlib_screen_get (dpy, scr, &screen);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return _cairo_surface_create_in_error (status);
|
|
|
|
|
|
2009-09-29 03:02:40 +01:00
|
|
|
X_DEBUG ((dpy, "create_with_xrender_format (drawable=%x)", (unsigned int) drawable));
|
|
|
|
|
|
2010-05-06 10:46:49 +01:00
|
|
|
return _cairo_xlib_surface_create_internal (screen, drawable,
|
2010-06-11 10:35:43 +01:00
|
|
|
_visual_for_xrender_format (scr, format),
|
|
|
|
|
format, width, height, 0);
|
2005-03-15 16:25:30 +00:00
|
|
|
}
|
2008-01-27 12:13:13 -08:00
|
|
|
|
|
|
|
|
/**
|
2008-01-28 21:00:21 -05:00
|
|
|
* cairo_xlib_surface_get_xrender_format:
|
|
|
|
|
* @surface: an xlib surface
|
2008-01-27 12:13:13 -08:00
|
|
|
*
|
2008-01-28 21:00:21 -05:00
|
|
|
* Gets the X Render picture format that @surface uses for rendering with the
|
|
|
|
|
* X Render extension. If the surface was created by
|
|
|
|
|
* cairo_xlib_surface_create_with_xrender_format() originally, the return
|
|
|
|
|
* value is the format passed to that constructor.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the XRenderPictFormat* associated with @surface,
|
|
|
|
|
* or %NULL if the surface is not an xlib surface
|
2008-01-28 23:23:00 -05:00
|
|
|
* or if the X Render extension is not available.
|
2008-01-28 21:00:21 -05:00
|
|
|
*
|
|
|
|
|
* Since: 1.6
|
|
|
|
|
**/
|
2008-01-27 12:13:13 -08:00
|
|
|
XRenderPictFormat *
|
|
|
|
|
cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
|
|
|
|
|
|
|
|
|
|
/* Throw an error for a non-xlib surface */
|
|
|
|
|
if (! _cairo_surface_is_xlib (surface)) {
|
|
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return xlib_surface->xrender_format;
|
|
|
|
|
}
|
2007-08-31 20:52:43 -04:00
|
|
|
#endif
|
2005-03-15 16:25:30 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_set_size:
|
|
|
|
|
* @surface: a #cairo_surface_t for the XLib backend
|
|
|
|
|
* @width: the new width of the surface
|
|
|
|
|
* @height: the new height of the surface
|
2006-06-06 15:35:48 -07:00
|
|
|
*
|
2005-05-17 06:05:13 +00:00
|
|
|
* Informs cairo of the new size of the X Drawable underlying the
|
|
|
|
|
* surface. For a surface created for a Window (rather than a Pixmap),
|
|
|
|
|
* this function must be called each time the size of the window
|
|
|
|
|
* changes. (For a subwindow, you are normally resizing the window
|
|
|
|
|
* yourself, but for a toplevel window, it is necessary to listen for
|
|
|
|
|
* ConfigureNotify events.)
|
2005-03-15 16:25:30 +00:00
|
|
|
*
|
2005-05-17 06:05:13 +00:00
|
|
|
* A Pixmap can never change size, so it is never necessary to call
|
|
|
|
|
* this function on a surface created for a Pixmap.
|
2005-03-15 16:25:30 +00:00
|
|
|
**/
|
|
|
|
|
void
|
2006-05-01 15:44:58 -07:00
|
|
|
cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
|
2005-03-15 16:25:30 +00:00
|
|
|
int width,
|
|
|
|
|
int height)
|
|
|
|
|
{
|
2006-05-01 15:44:58 -07:00
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2007-10-04 13:15:46 +01:00
|
|
|
cairo_status_t status;
|
2005-03-15 16:25:30 +00:00
|
|
|
|
2010-04-14 19:05:09 +01:00
|
|
|
if (unlikely (abstract_surface->status))
|
|
|
|
|
return;
|
2010-07-06 00:21:38 +02:00
|
|
|
if (unlikely (abstract_surface->finished)) {
|
|
|
|
|
status = _cairo_surface_set_error (abstract_surface,
|
|
|
|
|
_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-04-14 19:05:09 +01:00
|
|
|
|
2006-05-01 15:44:58 -07:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
status = _cairo_surface_set_error (abstract_surface,
|
2010-07-06 00:21:38 +02:00
|
|
|
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
|
2005-04-14 14:42:26 +00:00
|
|
|
return;
|
2006-05-01 15:44:58 -07:00
|
|
|
}
|
2005-04-14 14:42:26 +00:00
|
|
|
|
2009-09-06 10:17:40 +01:00
|
|
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) {
|
|
|
|
|
status = _cairo_surface_set_error (abstract_surface,
|
2010-07-06 00:21:38 +02:00
|
|
|
_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
2009-09-06 10:17:40 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2006-05-01 15:44:58 -07:00
|
|
|
surface->width = width;
|
|
|
|
|
surface->height = height;
|
2005-03-15 16:25:30 +00:00
|
|
|
}
|
2005-07-21 08:45:57 +00:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_set_drawable:
|
|
|
|
|
* @surface: a #cairo_surface_t for the XLib backend
|
|
|
|
|
* @drawable: the new drawable for the surface
|
2005-08-23 21:36:08 +00:00
|
|
|
* @width: the width of the new drawable
|
|
|
|
|
* @height: the height of the new drawable
|
2006-06-06 15:35:48 -07:00
|
|
|
*
|
2005-07-21 08:45:57 +00:00
|
|
|
* Informs cairo of a new X Drawable underlying the
|
|
|
|
|
* surface. The drawable must match the display, screen
|
|
|
|
|
* and format of the existing drawable or the application
|
|
|
|
|
* will get X protocol errors and will probably terminate.
|
|
|
|
|
* No checks are done by this function to ensure this
|
|
|
|
|
* compatibility.
|
|
|
|
|
**/
|
|
|
|
|
void
|
|
|
|
|
cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
|
|
|
|
|
Drawable drawable,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
|
2007-04-17 12:03:07 +01:00
|
|
|
cairo_status_t status;
|
2005-07-21 08:45:57 +00:00
|
|
|
|
2010-04-14 19:05:09 +01:00
|
|
|
if (unlikely (abstract_surface->status))
|
|
|
|
|
return;
|
2010-07-06 00:21:38 +02:00
|
|
|
if (unlikely (abstract_surface->finished)) {
|
|
|
|
|
status = _cairo_surface_set_error (abstract_surface,
|
|
|
|
|
_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-04-14 19:05:09 +01:00
|
|
|
|
2006-05-01 15:44:58 -07:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
status = _cairo_surface_set_error (abstract_surface,
|
2010-07-06 00:21:38 +02:00
|
|
|
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
|
2005-07-21 08:45:57 +00:00
|
|
|
return;
|
2006-05-01 15:44:58 -07:00
|
|
|
}
|
2005-07-21 08:45:57 +00:00
|
|
|
|
2009-09-06 10:17:40 +01:00
|
|
|
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) {
|
|
|
|
|
status = _cairo_surface_set_error (abstract_surface,
|
2010-07-06 00:21:38 +02:00
|
|
|
_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
2009-09-06 10:17:40 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-21 08:45:57 +00:00
|
|
|
/* XXX: and what about this case? */
|
|
|
|
|
if (surface->owns_pixmap)
|
|
|
|
|
return;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-07-21 08:45:57 +00:00
|
|
|
if (surface->drawable != drawable) {
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
|
|
|
|
|
|
|
|
|
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
X_DEBUG ((display->display, "set_drawable (drawable=%x)", (unsigned int) drawable));
|
2009-09-29 03:02:40 +01:00
|
|
|
|
2007-04-17 12:03:07 +01:00
|
|
|
if (surface->dst_picture != None) {
|
|
|
|
|
status = _cairo_xlib_display_queue_resource (
|
2010-04-18 23:20:02 +02:00
|
|
|
display,
|
2007-04-17 12:03:07 +01:00
|
|
|
XRenderFreePicture,
|
|
|
|
|
surface->dst_picture);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
status = _cairo_surface_set_error (&surface->base, status);
|
2007-04-17 12:03:07 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2007-04-17 12:03:07 +01:00
|
|
|
surface->dst_picture = None;
|
|
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2007-04-17 12:03:07 +01:00
|
|
|
if (surface->src_picture != None) {
|
|
|
|
|
status = _cairo_xlib_display_queue_resource (
|
2010-04-18 23:20:02 +02:00
|
|
|
display,
|
2007-04-17 12:03:07 +01:00
|
|
|
XRenderFreePicture,
|
|
|
|
|
surface->src_picture);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
status = _cairo_surface_set_error (&surface->base, status);
|
2007-04-17 12:03:07 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
surface->src_picture = None;
|
|
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_device_release (&display->base);
|
|
|
|
|
|
2005-07-21 08:45:57 +00:00
|
|
|
surface->drawable = drawable;
|
|
|
|
|
}
|
|
|
|
|
surface->width = width;
|
|
|
|
|
surface->height = height;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-30 00:46:48 +02:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_get_display:
|
|
|
|
|
* @surface: a #cairo_xlib_surface_t
|
|
|
|
|
*
|
|
|
|
|
* Get the X Display for the underlying X Drawable.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the display.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
2006-05-04 04:01:06 -07:00
|
|
|
Display *
|
|
|
|
|
cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
|
2006-05-04 03:59:56 -07:00
|
|
|
{
|
2006-05-04 04:01:06 -07:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
2006-05-04 04:01:06 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
return ((cairo_xlib_display_t *) abstract_surface->device)->display;
|
2006-05-04 03:59:56 -07:00
|
|
|
}
|
|
|
|
|
|
2006-06-30 00:46:48 +02:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_get_drawable:
|
|
|
|
|
* @surface: a #cairo_xlib_surface_t
|
|
|
|
|
*
|
|
|
|
|
* Get the underlying X Drawable used for the surface.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the drawable.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
2006-05-04 03:59:56 -07:00
|
|
|
Drawable
|
|
|
|
|
cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
|
|
|
|
|
{
|
2006-05-04 04:01:06 -07:00
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2006-05-04 04:01:06 -07:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
2006-05-04 04:01:06 -07:00
|
|
|
return 0;
|
|
|
|
|
}
|
2006-05-04 03:59:56 -07:00
|
|
|
|
|
|
|
|
return surface->drawable;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-30 00:46:48 +02:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_get_screen:
|
|
|
|
|
* @surface: a #cairo_xlib_surface_t
|
|
|
|
|
*
|
|
|
|
|
* Get the X Screen for the underlying X Drawable.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the screen.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
2006-05-04 03:59:56 -07:00
|
|
|
Screen *
|
|
|
|
|
cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
|
|
|
|
|
{
|
2006-05-04 04:01:06 -07:00
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2006-05-04 04:01:06 -07:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
2006-05-04 04:01:06 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2009-09-01 23:12:43 +01:00
|
|
|
return surface->screen->screen;
|
2006-05-04 03:59:56 -07:00
|
|
|
}
|
|
|
|
|
|
2006-06-30 00:46:48 +02:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_get_visual:
|
|
|
|
|
* @surface: a #cairo_xlib_surface_t
|
|
|
|
|
*
|
2010-06-11 10:35:43 +01:00
|
|
|
* Gets the X Visual associated with @surface, suitable for use with the
|
|
|
|
|
* underlying X Drawable. If @surface was created by
|
|
|
|
|
* cairo_xlib_surface_create(), the return value is the Visual passed to that
|
|
|
|
|
* constructor.
|
2006-06-30 00:46:48 +02:00
|
|
|
*
|
2010-06-11 10:35:43 +01:00
|
|
|
* Return value: the Visual or %NULL if there is no appropriate Visual for
|
|
|
|
|
* @surface.
|
2006-06-30 00:46:48 +02:00
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
2006-05-04 03:59:56 -07:00
|
|
|
Visual *
|
2010-06-11 10:35:43 +01:00
|
|
|
cairo_xlib_surface_get_visual (cairo_surface_t *surface)
|
2006-05-04 03:59:56 -07:00
|
|
|
{
|
2010-06-11 10:35:43 +01:00
|
|
|
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2010-06-11 10:35:43 +01:00
|
|
|
if (! _cairo_surface_is_xlib (surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
2006-05-04 04:01:06 -07:00
|
|
|
return NULL;
|
|
|
|
|
}
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2010-06-11 10:35:43 +01:00
|
|
|
return xlib_surface->visual;
|
2006-05-04 03:59:56 -07:00
|
|
|
}
|
|
|
|
|
|
2006-06-30 00:46:48 +02:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_get_depth:
|
|
|
|
|
* @surface: a #cairo_xlib_surface_t
|
|
|
|
|
*
|
|
|
|
|
* Get the number of bits used to represent each pixel value.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the depth of the surface in bits.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
2006-05-04 03:59:56 -07:00
|
|
|
int
|
|
|
|
|
cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
|
|
|
|
|
{
|
2006-05-04 04:01:06 -07:00
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2006-05-04 04:01:06 -07:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
2006-05-04 04:01:06 -07:00
|
|
|
return 0;
|
|
|
|
|
}
|
2006-05-04 03:59:56 -07:00
|
|
|
|
|
|
|
|
return surface->depth;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-30 00:46:48 +02:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_get_width:
|
|
|
|
|
* @surface: a #cairo_xlib_surface_t
|
|
|
|
|
*
|
|
|
|
|
* Get the width of the X Drawable underlying the surface in pixels.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the width of the surface in pixels.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
2006-06-21 15:47:03 +12:00
|
|
|
int
|
|
|
|
|
cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
|
|
|
|
|
|
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
2009-09-06 10:17:40 +01:00
|
|
|
return 0;
|
2006-06-21 15:47:03 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return surface->width;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-30 00:46:48 +02:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_get_height:
|
|
|
|
|
* @surface: a #cairo_xlib_surface_t
|
|
|
|
|
*
|
|
|
|
|
* Get the height of the X Drawable underlying the surface in pixels.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the height of the surface in pixels.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
2006-06-21 15:47:03 +12:00
|
|
|
int
|
|
|
|
|
cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
|
|
|
|
|
|
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
2009-09-06 10:17:40 +01:00
|
|
|
return 0;
|
2006-06-21 15:47:03 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return surface->height;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
enum {
|
2008-05-28 17:12:51 -04:00
|
|
|
GLYPHSET_INDEX_ARGB32,
|
|
|
|
|
GLYPHSET_INDEX_A8,
|
|
|
|
|
GLYPHSET_INDEX_A1,
|
|
|
|
|
NUM_GLYPHSETS
|
2007-12-17 01:14:27 -05:00
|
|
|
};
|
|
|
|
|
|
2008-05-01 19:46:58 +01:00
|
|
|
typedef struct _cairo_xlib_font_glyphset_free_glyphs {
|
|
|
|
|
GlyphSet glyphset;
|
|
|
|
|
int glyph_count;
|
|
|
|
|
unsigned long glyph_indices[128];
|
|
|
|
|
} cairo_xlib_font_glyphset_free_glyphs_t;
|
|
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
typedef struct _cairo_xlib_font_glyphset_info {
|
2005-08-31 15:08:02 +00:00
|
|
|
GlyphSet glyphset;
|
2006-05-01 10:17:08 -07:00
|
|
|
cairo_format_t format;
|
|
|
|
|
XRenderPictFormat *xrender_format;
|
2008-05-01 19:46:58 +01:00
|
|
|
cairo_xlib_font_glyphset_free_glyphs_t *pending_free_glyphs;
|
2007-12-17 01:14:27 -05:00
|
|
|
} cairo_xlib_font_glyphset_info_t;
|
|
|
|
|
|
|
|
|
|
typedef struct _cairo_xlib_surface_font_private {
|
2008-09-02 10:08:04 +01:00
|
|
|
cairo_scaled_font_t *scaled_font;
|
|
|
|
|
cairo_xlib_hook_t close_display_hook;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_device_t *device;
|
2008-05-01 15:44:22 +01:00
|
|
|
cairo_xlib_font_glyphset_info_t glyphset_info[NUM_GLYPHSETS];
|
2005-08-31 15:08:02 +00:00
|
|
|
} cairo_xlib_surface_font_private_t;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2008-09-02 10:08:04 +01:00
|
|
|
/* callback from CloseDisplay */
|
2007-03-13 20:17:22 +00:00
|
|
|
static void
|
2008-09-02 10:28:17 +01:00
|
|
|
_cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t *display,
|
|
|
|
|
void *data)
|
2007-03-13 20:17:22 +00:00
|
|
|
{
|
2007-04-12 21:30:39 +01:00
|
|
|
cairo_xlib_surface_font_private_t *font_private;
|
2008-09-02 10:08:04 +01:00
|
|
|
cairo_scaled_font_t *scaled_font;
|
|
|
|
|
|
|
|
|
|
font_private = cairo_container_of (data,
|
|
|
|
|
cairo_xlib_surface_font_private_t,
|
|
|
|
|
close_display_hook);
|
|
|
|
|
scaled_font = font_private->scaled_font;
|
2007-04-12 21:30:39 +01:00
|
|
|
|
|
|
|
|
CAIRO_MUTEX_LOCK (scaled_font->mutex);
|
2008-10-21 22:48:17 +01:00
|
|
|
font_private = scaled_font->surface_private;
|
2007-04-12 21:30:39 +01:00
|
|
|
scaled_font->surface_private = NULL;
|
2007-03-13 20:17:22 +00:00
|
|
|
|
|
|
|
|
_cairo_scaled_font_reset_cache (scaled_font);
|
2007-04-12 21:30:39 +01:00
|
|
|
CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
|
2007-03-13 20:17:22 +00:00
|
|
|
|
2007-04-19 12:15:04 +01:00
|
|
|
if (font_private != NULL) {
|
2007-12-17 01:14:27 -05:00
|
|
|
int i;
|
2008-05-01 15:44:22 +01:00
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
for (i = 0; i < NUM_GLYPHSETS; i++) {
|
2008-05-01 15:44:22 +01:00
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info;
|
|
|
|
|
|
|
|
|
|
glyphset_info = &font_private->glyphset_info[i];
|
|
|
|
|
if (glyphset_info->glyphset)
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderFreeGlyphSet (display->display, glyphset_info->glyphset);
|
2008-08-14 08:25:58 +01:00
|
|
|
|
|
|
|
|
if (glyphset_info->pending_free_glyphs != NULL)
|
|
|
|
|
free (glyphset_info->pending_free_glyphs);
|
2007-12-17 01:14:27 -05:00
|
|
|
}
|
2008-05-01 15:44:22 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_device_destroy (font_private->device);
|
2007-03-13 20:17:22 +00:00
|
|
|
free (font_private);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
static cairo_status_t
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_font_init (cairo_xlib_display_t *display,
|
2007-12-17 01:14:27 -05:00
|
|
|
cairo_scaled_font_t *scaled_font)
|
2005-08-31 15:08:02 +00:00
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_font_private_t *font_private;
|
2007-12-17 01:14:27 -05:00
|
|
|
int i;
|
2005-07-21 14:31:28 +00:00
|
|
|
|
2007-04-08 23:09:31 +01:00
|
|
|
font_private = malloc (sizeof (cairo_xlib_surface_font_private_t));
|
2008-11-18 17:26:55 +00:00
|
|
|
if (unlikely (font_private == NULL))
|
2007-10-04 13:15:46 +01:00
|
|
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
2007-04-08 23:09:31 +01:00
|
|
|
|
2008-09-02 10:08:04 +01:00
|
|
|
font_private->scaled_font = scaled_font;
|
2010-04-18 23:20:02 +02:00
|
|
|
font_private->device = cairo_device_reference (&display->base);
|
2008-09-02 10:08:04 +01:00
|
|
|
|
|
|
|
|
/* initialize and hook into the CloseDisplay callback */
|
|
|
|
|
font_private->close_display_hook.func =
|
|
|
|
|
_cairo_xlib_surface_remove_scaled_font;
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_add_close_display_hook (display,
|
2008-09-02 10:28:17 +01:00
|
|
|
&font_private->close_display_hook);
|
2007-03-13 20:17:22 +00:00
|
|
|
|
2005-07-21 14:31:28 +00:00
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
for (i = 0; i < NUM_GLYPHSETS; i++) {
|
|
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i];
|
|
|
|
|
switch (i) {
|
2008-05-01 15:44:22 +01:00
|
|
|
case GLYPHSET_INDEX_ARGB32: glyphset_info->format = CAIRO_FORMAT_ARGB32; break;
|
|
|
|
|
case GLYPHSET_INDEX_A8: glyphset_info->format = CAIRO_FORMAT_A8; break;
|
|
|
|
|
case GLYPHSET_INDEX_A1: glyphset_info->format = CAIRO_FORMAT_A1; break;
|
|
|
|
|
default: ASSERT_NOT_REACHED; break;
|
2007-12-17 01:14:27 -05:00
|
|
|
}
|
|
|
|
|
glyphset_info->xrender_format = NULL;
|
|
|
|
|
glyphset_info->glyphset = None;
|
2008-05-01 19:46:58 +01:00
|
|
|
glyphset_info->pending_free_glyphs = NULL;
|
2007-12-17 01:14:27 -05:00
|
|
|
}
|
|
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
scaled_font->surface_private = font_private;
|
|
|
|
|
scaled_font->surface_backend = &cairo_xlib_surface_backend;
|
2007-03-13 20:17:22 +00:00
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
2005-07-21 14:31:28 +00:00
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
static void
|
|
|
|
|
_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
|
|
|
|
{
|
2008-05-01 15:44:22 +01:00
|
|
|
cairo_xlib_surface_font_private_t *font_private;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_status_t status;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2008-05-01 15:44:22 +01:00
|
|
|
font_private = scaled_font->surface_private;
|
|
|
|
|
if (font_private != NULL) {
|
2007-04-17 12:03:07 +01:00
|
|
|
cairo_xlib_display_t *display;
|
2008-05-01 15:44:22 +01:00
|
|
|
int i;
|
2007-04-17 12:03:07 +01:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (font_private->device, &display);
|
|
|
|
|
if (status)
|
|
|
|
|
goto BAIL;
|
|
|
|
|
|
2008-09-02 10:28:17 +01:00
|
|
|
_cairo_xlib_remove_close_display_hook (display,
|
2008-09-02 10:08:04 +01:00
|
|
|
&font_private->close_display_hook);
|
2007-04-17 12:03:07 +01:00
|
|
|
|
2008-05-01 15:44:22 +01:00
|
|
|
for (i = 0; i < NUM_GLYPHSETS; i++) {
|
|
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info;
|
2007-12-17 01:14:27 -05:00
|
|
|
|
2008-05-01 15:44:22 +01:00
|
|
|
glyphset_info = &font_private->glyphset_info[i];
|
2008-05-01 19:46:58 +01:00
|
|
|
|
|
|
|
|
if (glyphset_info->pending_free_glyphs != NULL)
|
|
|
|
|
free (glyphset_info->pending_free_glyphs);
|
|
|
|
|
|
2008-05-01 15:44:22 +01:00
|
|
|
if (glyphset_info->glyphset) {
|
|
|
|
|
status = _cairo_xlib_display_queue_resource (display,
|
|
|
|
|
XRenderFreeGlyphSet,
|
|
|
|
|
glyphset_info->glyphset);
|
|
|
|
|
(void) status; /* XXX cannot propagate failure */
|
|
|
|
|
}
|
2007-04-17 12:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_device_release (&display->base);
|
|
|
|
|
BAIL:
|
|
|
|
|
cairo_device_destroy (&display->base);
|
2005-08-31 15:08:02 +00:00
|
|
|
free (font_private);
|
|
|
|
|
}
|
|
|
|
|
}
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2008-05-01 19:46:58 +01:00
|
|
|
static void
|
|
|
|
|
_cairo_xlib_render_free_glyphs (Display *dpy,
|
|
|
|
|
cairo_xlib_font_glyphset_free_glyphs_t *to_free)
|
2007-04-17 12:03:07 +01:00
|
|
|
{
|
|
|
|
|
XRenderFreeGlyphs (dpy,
|
2008-05-01 19:46:58 +01:00
|
|
|
to_free->glyphset,
|
|
|
|
|
to_free->glyph_indices,
|
|
|
|
|
to_free->glyph_count);
|
2007-04-17 12:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
static cairo_xlib_font_glyphset_info_t *
|
|
|
|
|
_cairo_xlib_scaled_glyph_get_glyphset_info (cairo_scaled_glyph_t *scaled_glyph)
|
|
|
|
|
{
|
2008-05-28 17:12:51 -04:00
|
|
|
return scaled_glyph->surface_private;
|
2007-12-17 01:14:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_cairo_xlib_scaled_glyph_set_glyphset_info (cairo_scaled_glyph_t *scaled_glyph,
|
|
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info)
|
|
|
|
|
{
|
2008-05-28 17:12:51 -04:00
|
|
|
scaled_glyph->surface_private = glyphset_info;
|
2007-12-17 01:14:27 -05:00
|
|
|
}
|
|
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
static void
|
|
|
|
|
_cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
|
|
|
|
cairo_scaled_font_t *scaled_font)
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
{
|
2008-05-01 15:44:22 +01:00
|
|
|
cairo_xlib_surface_font_private_t *font_private;
|
|
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info;
|
2005-08-31 15:08:02 +00:00
|
|
|
|
2008-05-06 14:52:02 +01:00
|
|
|
if (scaled_font->finished)
|
|
|
|
|
return;
|
|
|
|
|
|
2008-05-01 15:44:22 +01:00
|
|
|
font_private = scaled_font->surface_private;
|
|
|
|
|
glyphset_info = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph);
|
|
|
|
|
if (font_private != NULL && glyphset_info != NULL) {
|
2008-05-01 19:46:58 +01:00
|
|
|
cairo_xlib_font_glyphset_free_glyphs_t *to_free;
|
|
|
|
|
cairo_status_t status;
|
2007-04-17 12:03:07 +01:00
|
|
|
|
2008-05-01 19:46:58 +01:00
|
|
|
to_free = glyphset_info->pending_free_glyphs;
|
|
|
|
|
if (to_free != NULL &&
|
|
|
|
|
to_free->glyph_count == ARRAY_LENGTH (to_free->glyph_indices))
|
|
|
|
|
{
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
|
|
|
|
|
|
|
|
|
status = _cairo_xlib_display_acquire (font_private->device, &display);
|
|
|
|
|
if (status == CAIRO_STATUS_SUCCESS) {
|
|
|
|
|
status = _cairo_xlib_display_queue_work (display,
|
|
|
|
|
(cairo_xlib_notify_func) _cairo_xlib_render_free_glyphs,
|
|
|
|
|
to_free,
|
|
|
|
|
free);
|
|
|
|
|
cairo_device_release (&display->base);
|
|
|
|
|
}
|
2008-05-01 19:46:58 +01:00
|
|
|
/* XXX cannot propagate failure */
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-05-01 19:46:58 +01:00
|
|
|
free (to_free);
|
|
|
|
|
|
|
|
|
|
to_free = glyphset_info->pending_free_glyphs = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (to_free == NULL) {
|
|
|
|
|
to_free = malloc (sizeof (cairo_xlib_font_glyphset_free_glyphs_t));
|
2008-11-18 17:26:55 +00:00
|
|
|
if (unlikely (to_free == NULL)) {
|
2008-05-01 19:46:58 +01:00
|
|
|
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
return; /* XXX cannot propagate failure */
|
2008-05-01 15:44:22 +01:00
|
|
|
}
|
2008-05-01 19:46:58 +01:00
|
|
|
|
|
|
|
|
to_free->glyphset = glyphset_info->glyphset;
|
|
|
|
|
to_free->glyph_count = 0;
|
|
|
|
|
glyphset_info->pending_free_glyphs = to_free;
|
2007-04-17 12:03:07 +01:00
|
|
|
}
|
2008-05-01 19:46:58 +01:00
|
|
|
|
|
|
|
|
to_free->glyph_indices[to_free->glyph_count++] =
|
|
|
|
|
_cairo_scaled_glyph_index (scaled_glyph);
|
2005-08-31 15:08:02 +00:00
|
|
|
}
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
2005-07-21 14:31:28 +00:00
|
|
|
static cairo_bool_t
|
|
|
|
|
_native_byte_order_lsb (void)
|
|
|
|
|
{
|
|
|
|
|
int x = 1;
|
|
|
|
|
|
|
|
|
|
return *((char *) &x) == 1;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-23 21:53:31 +01:00
|
|
|
static int
|
|
|
|
|
_cairo_xlib_get_glyphset_index_for_format (cairo_format_t format)
|
|
|
|
|
{
|
|
|
|
|
if (format == CAIRO_FORMAT_A8)
|
|
|
|
|
return GLYPHSET_INDEX_A8;
|
|
|
|
|
if (format == CAIRO_FORMAT_A1)
|
|
|
|
|
return GLYPHSET_INDEX_A1;
|
|
|
|
|
|
|
|
|
|
assert (format == CAIRO_FORMAT_ARGB32);
|
|
|
|
|
return GLYPHSET_INDEX_ARGB32;
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
static cairo_xlib_font_glyphset_info_t *
|
|
|
|
|
_cairo_xlib_scaled_font_get_glyphset_info_for_format (cairo_scaled_font_t *scaled_font,
|
|
|
|
|
cairo_format_t format)
|
|
|
|
|
{
|
2008-05-01 15:44:22 +01:00
|
|
|
cairo_xlib_surface_font_private_t *font_private;
|
2007-12-17 01:14:27 -05:00
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info;
|
|
|
|
|
int glyphset_index;
|
|
|
|
|
|
2010-02-23 21:53:31 +01:00
|
|
|
glyphset_index = _cairo_xlib_get_glyphset_index_for_format (format);
|
2008-05-01 15:44:22 +01:00
|
|
|
font_private = scaled_font->surface_private;
|
2007-12-17 01:14:27 -05:00
|
|
|
glyphset_info = &font_private->glyphset_info[glyphset_index];
|
|
|
|
|
if (glyphset_info->glyphset == None) {
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
|
|
|
|
|
|
|
|
|
if (_cairo_xlib_display_acquire (font_private->device, &display))
|
|
|
|
|
return NULL;
|
2008-05-01 15:44:22 +01:00
|
|
|
|
|
|
|
|
glyphset_info->xrender_format =
|
|
|
|
|
_cairo_xlib_display_get_xrender_format (display,
|
|
|
|
|
glyphset_info->format);
|
2010-04-18 23:20:02 +02:00
|
|
|
glyphset_info->glyphset = XRenderCreateGlyphSet (display->display,
|
2009-09-01 23:12:43 +01:00
|
|
|
glyphset_info->xrender_format);
|
2010-04-18 23:20:02 +02:00
|
|
|
|
|
|
|
|
cairo_device_release (&display->base);
|
2007-12-17 01:14:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return glyphset_info;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-08 17:23:44 +01:00
|
|
|
static cairo_bool_t
|
|
|
|
|
_cairo_xlib_glyphset_info_has_pending_free_glyph (
|
|
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info,
|
|
|
|
|
unsigned long glyph_index)
|
|
|
|
|
{
|
|
|
|
|
if (glyphset_info->pending_free_glyphs != NULL) {
|
|
|
|
|
cairo_xlib_font_glyphset_free_glyphs_t *to_free;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
to_free = glyphset_info->pending_free_glyphs;
|
|
|
|
|
for (i = 0; i < to_free->glyph_count; i++) {
|
|
|
|
|
if (to_free->glyph_indices[i] == glyph_index) {
|
|
|
|
|
to_free->glyph_count--;
|
|
|
|
|
memmove (&to_free->glyph_indices[i],
|
|
|
|
|
&to_free->glyph_indices[i+1],
|
|
|
|
|
(to_free->glyph_count - i) * sizeof (to_free->glyph_indices[0]));
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_xlib_font_glyphset_info_t *
|
|
|
|
|
_cairo_xlib_scaled_font_get_glyphset_info_for_pending_free_glyph (
|
|
|
|
|
cairo_scaled_font_t *scaled_font,
|
|
|
|
|
unsigned long glyph_index,
|
|
|
|
|
cairo_image_surface_t *surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_font_private_t *font_private;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
font_private = scaled_font->surface_private;
|
|
|
|
|
if (font_private == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (surface != NULL) {
|
2010-02-23 21:53:31 +01:00
|
|
|
i = _cairo_xlib_get_glyphset_index_for_format (surface->format);
|
2008-05-08 17:23:44 +01:00
|
|
|
if (_cairo_xlib_glyphset_info_has_pending_free_glyph (
|
|
|
|
|
&font_private->glyphset_info[i],
|
|
|
|
|
glyph_index))
|
|
|
|
|
{
|
|
|
|
|
return &font_private->glyphset_info[i];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (i = 0; i < NUM_GLYPHSETS; i++) {
|
|
|
|
|
if (_cairo_xlib_glyphset_info_has_pending_free_glyph (
|
|
|
|
|
&font_private->glyphset_info[i],
|
|
|
|
|
glyph_index))
|
|
|
|
|
{
|
|
|
|
|
return &font_private->glyphset_info[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-06 15:41:31 -07:00
|
|
|
static cairo_status_t
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display,
|
2007-10-19 15:02:03 -04:00
|
|
|
cairo_scaled_font_t *scaled_font,
|
|
|
|
|
cairo_scaled_glyph_t **pscaled_glyph)
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
{
|
2005-06-24 15:09:41 +00:00
|
|
|
XGlyphInfo glyph_info;
|
2005-08-31 15:08:02 +00:00
|
|
|
unsigned long glyph_index;
|
2005-07-21 14:31:28 +00:00
|
|
|
unsigned char *data;
|
2006-05-01 10:17:08 -07:00
|
|
|
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
2007-10-19 15:02:03 -04:00
|
|
|
cairo_scaled_glyph_t *scaled_glyph = *pscaled_glyph;
|
2005-08-31 15:08:02 +00:00
|
|
|
cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
|
2007-10-19 15:02:03 -04:00
|
|
|
cairo_bool_t already_had_glyph_surface;
|
2007-12-17 01:14:27 -05:00
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info;
|
2007-10-19 15:02:03 -04:00
|
|
|
|
2008-05-01 19:46:58 +01:00
|
|
|
glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
|
|
|
|
|
|
2008-05-08 17:23:44 +01:00
|
|
|
/* check to see if we have a pending XRenderFreeGlyph for this glyph */
|
|
|
|
|
glyphset_info = _cairo_xlib_scaled_font_get_glyphset_info_for_pending_free_glyph (scaled_font, glyph_index, glyph_surface);
|
|
|
|
|
if (glyphset_info != NULL) {
|
|
|
|
|
_cairo_xlib_scaled_glyph_set_glyphset_info (scaled_glyph, glyphset_info);
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 15:02:03 -04:00
|
|
|
if (!glyph_surface) {
|
|
|
|
|
status = _cairo_scaled_glyph_lookup (scaled_font,
|
2008-05-01 19:46:58 +01:00
|
|
|
glyph_index,
|
2007-10-19 15:02:03 -04:00
|
|
|
CAIRO_SCALED_GLYPH_INFO_METRICS |
|
|
|
|
|
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
|
|
|
|
pscaled_glyph);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2007-10-19 15:02:03 -04:00
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
scaled_glyph = *pscaled_glyph;
|
|
|
|
|
glyph_surface = scaled_glyph->surface;
|
|
|
|
|
already_had_glyph_surface = FALSE;
|
|
|
|
|
} else {
|
|
|
|
|
already_had_glyph_surface = TRUE;
|
|
|
|
|
}
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
if (scaled_font->surface_private == NULL) {
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_font_init (display, scaled_font);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2005-08-31 15:08:02 +00:00
|
|
|
return status;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
}
|
2004-11-05 10:57:50 +00:00
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
glyphset_info = _cairo_xlib_scaled_font_get_glyphset_info_for_format (scaled_font,
|
|
|
|
|
glyph_surface->format);
|
|
|
|
|
|
2008-05-23 19:04:13 -04:00
|
|
|
/* XRenderAddGlyph does not handle a glyph surface larger than the extended maximum XRequest size. */
|
|
|
|
|
{
|
|
|
|
|
int len = cairo_format_stride_for_width (glyphset_info->format, glyph_surface->width) * glyph_surface->height;
|
2010-04-18 23:20:02 +02:00
|
|
|
int max_request_size = (XExtendedMaxRequestSize (display->display) ? XExtendedMaxRequestSize (display->display)
|
|
|
|
|
: XMaxRequestSize (display->display)) * 4 -
|
2008-05-23 19:04:13 -04:00
|
|
|
sz_xRenderAddGlyphsReq -
|
|
|
|
|
sz_xGlyphInfo -
|
|
|
|
|
8;
|
|
|
|
|
if (len >= max_request_size)
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("glyph too large for XRequest");
|
2008-05-23 19:04:13 -04:00
|
|
|
}
|
|
|
|
|
|
2007-10-19 15:02:03 -04:00
|
|
|
/* If the glyph surface has zero height or width, we create
|
|
|
|
|
* a clear 1x1 surface, to avoid various X server bugs.
|
|
|
|
|
*/
|
2008-04-02 14:53:25 +01:00
|
|
|
if (glyph_surface->width == 0 || glyph_surface->height == 0) {
|
2007-10-19 15:02:03 -04:00
|
|
|
cairo_surface_t *tmp_surface;
|
|
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1);
|
2008-10-16 14:37:42 +01:00
|
|
|
status = tmp_surface->status;
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-04-02 14:53:25 +01:00
|
|
|
goto BAIL;
|
|
|
|
|
|
2007-10-19 15:02:03 -04:00
|
|
|
tmp_surface->device_transform = glyph_surface->base.device_transform;
|
|
|
|
|
tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
|
|
|
|
|
|
|
|
|
|
glyph_surface = (cairo_image_surface_t *) tmp_surface;
|
|
|
|
|
}
|
|
|
|
|
|
2006-05-01 10:17:08 -07:00
|
|
|
/* If the glyph format does not match the font format, then we
|
|
|
|
|
* create a temporary surface for the glyph image with the font's
|
|
|
|
|
* format.
|
|
|
|
|
*/
|
2007-12-17 01:14:27 -05:00
|
|
|
if (glyph_surface->format != glyphset_info->format) {
|
2009-09-21 03:31:22 +01:00
|
|
|
cairo_surface_pattern_t pattern;
|
2006-05-01 10:17:08 -07:00
|
|
|
cairo_surface_t *tmp_surface;
|
|
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
tmp_surface = cairo_image_surface_create (glyphset_info->format,
|
2006-05-01 10:17:08 -07:00
|
|
|
glyph_surface->width,
|
|
|
|
|
glyph_surface->height);
|
2008-10-16 14:37:42 +01:00
|
|
|
status = tmp_surface->status;
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2008-04-02 14:53:25 +01:00
|
|
|
goto BAIL;
|
|
|
|
|
|
2007-10-19 15:02:03 -04:00
|
|
|
tmp_surface->device_transform = glyph_surface->base.device_transform;
|
|
|
|
|
tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
|
|
|
|
|
|
2009-09-21 03:31:22 +01:00
|
|
|
_cairo_pattern_init_for_surface (&pattern, &glyph_surface->base);
|
|
|
|
|
status = _cairo_surface_paint (tmp_surface,
|
|
|
|
|
CAIRO_OPERATOR_SOURCE, &pattern.base,
|
|
|
|
|
NULL);
|
|
|
|
|
_cairo_pattern_fini (&pattern.base);
|
2006-05-01 10:17:08 -07:00
|
|
|
|
|
|
|
|
glyph_surface = (cairo_image_surface_t *) tmp_surface;
|
|
|
|
|
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2006-05-01 10:17:08 -07:00
|
|
|
goto BAIL;
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-10 00:12:51 -07:00
|
|
|
/* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
|
Fix device_offset misuse in all glyph surface uses
Seems like all over the code, we have been using negated device_offset
values for glyph surfaces. Here is all the math(!):
A device_transform converts from device space (a conceptual space) to
surface space. For simple cases of translation only, it's called a
device_offset and is public API (cairo_surface_[gs]et_device_offset).
A possibly better name for those functions could have been
cairo_surface_[gs]et_origing. So, that's what they do: they set where
the device-space origin (0,0) is in the surface. If the origin is inside
the surface, device_offset values are positive. It may look like this:
Device space:
(-x,-y) <-- negative numbers
+----------------+
| . |
| . |
|......(0,0) <---|-- device-space origin
| |
| |
+----------------+
(width-x,height-y)
Surface space:
(0,0) <-- surface-space origin
+---------------+
| . |
| . |
|......(x,y) <--|-- device_offset
| |
| |
+---------------+
(width,height)
In other words: device_offset is the coordinates of the device-space
origin relative to the top-left of the surface.
We use device offsets in a couple of places:
- Public API: To let toolkits like Gtk+ give user a surface that
only represents part of the final destination (say, the expose
area), but has the same device space as the destination. In these
cases device_offset is typically negative. Example:
application window
+---------------+
| . |
| (x,y). |
|......+---+ |
| | | <--|-- expose area
| +---+ |
+---------------+
In this case, the user of cairo API can set the device_space on
the expose area to (-x,-y) to move the device space origin to that
of the application window, such that drawing in the expose area
surface and painting it in the application window has the same
effect as drawing in the application window directly. Gtk+ has
been using this feature.
- Glyph surfaces: In most font rendering systems, glyph surfaces
have an origin at (0,0) and a bounding box that is typically
represented as (x_bearing,y_bearing,width,height). Depending on
which way y progresses in the system, y_bearing may typically be
negative (for systems similar to cairo, with origin at top left),
or be positive (in systems like PDF with origin at bottom left).
No matter which is the case, it is important to note that
(x_bearing,y_bearing) is the coordinates of top-left of the glyph
relative to the glyph origin. That is, for example:
Scaled-glyph space:
(x_bearing,y_bearing) <-- negative numbers
+----------------+
| . |
| . |
|......(0,0) <---|-- glyph origin
| |
| |
+----------------+
(width+x_bearing,height+y_bearing)
Note the similarity of the origin to the device space. That is
exactly how we use the device_offset to represent scaled glyphs:
to use the device-space origin as the glyph origin.
Now compare the scaled-glyph space to device-space and surface-space
and convince yourself that:
(x_bearing,y_bearing) = (-x,-y) = - device_offset
That's right. If you are not convinced yet, contrast the definition
of the two:
"(x_bearing,y_bearing) is the coordinates of top-left of the
glyph relative to the glyph origin."
"In other words: device_offset is the coordinates of the
device-space origin relative to the top-left of the surface."
and note that glyph origin = device-space origin.
So, that was the bug. Fixing it removed lots of wonders and magic
negation signs.
The way I discovered the bug was that in the user-font API, to make
rendering the glyph from meta-surface to an image-surface work I had
to do:
cairo_surface_set_device_offset (surface, -x_bearing, -y_bearing);
_cairo_meta_surface_replay (meta_surface, surface);
cairo_surface_set_device_offset (surface, x_bearing, y_bearing);
This suggested that the use of device_offset for glyph origin is
different from its use for rendering with meta-surface. This reminded
me of the large comment in the xlib backend blaming XRender for having
weird glyph space, and of a similar problem I had in the PS backend
for bitmap glyph positioning (see d47388ad759b0a1a0869655a87d9b5eb6ae2445d)
...those are all fixed now.
2007-02-05 20:46:48 -05:00
|
|
|
glyph_info.x = _cairo_lround (glyph_surface->base.device_transform.x0);
|
|
|
|
|
glyph_info.y = _cairo_lround (glyph_surface->base.device_transform.y0);
|
2005-08-31 15:08:02 +00:00
|
|
|
glyph_info.width = glyph_surface->width;
|
|
|
|
|
glyph_info.height = glyph_surface->height;
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
glyph_info.xOff = scaled_glyph->x_advance;
|
|
|
|
|
glyph_info.yOff = scaled_glyph->y_advance;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
data = glyph_surface->data;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
/* flip formats around */
|
2010-02-23 21:53:31 +01:00
|
|
|
switch (_cairo_xlib_get_glyphset_index_for_format (scaled_glyph->surface->format)) {
|
|
|
|
|
case GLYPHSET_INDEX_A1:
|
2005-07-21 14:31:28 +00:00
|
|
|
/* local bitmaps are always stored with bit == byte */
|
2010-04-18 23:20:02 +02:00
|
|
|
if (_native_byte_order_lsb() != (BitmapBitOrder (display->display) == LSBFirst)) {
|
2005-08-31 15:08:02 +00:00
|
|
|
int c = glyph_surface->stride * glyph_surface->height;
|
2005-07-21 14:31:28 +00:00
|
|
|
unsigned char *d;
|
|
|
|
|
unsigned char *new, *n;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2005-07-21 14:31:28 +00:00
|
|
|
new = malloc (c);
|
2006-05-01 10:17:08 -07:00
|
|
|
if (!new) {
|
2007-10-04 13:15:46 +01:00
|
|
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
2006-05-01 10:17:08 -07:00
|
|
|
goto BAIL;
|
|
|
|
|
}
|
2005-07-21 14:31:28 +00:00
|
|
|
n = new;
|
|
|
|
|
d = data;
|
2009-06-02 18:07:31 +01:00
|
|
|
do {
|
2005-07-21 14:31:28 +00:00
|
|
|
char b = *d++;
|
|
|
|
|
b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
|
|
|
|
|
b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
|
|
|
|
|
b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
|
|
|
|
|
*n++ = b;
|
2009-06-02 18:07:31 +01:00
|
|
|
} while (--c);
|
2005-07-21 14:31:28 +00:00
|
|
|
data = new;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-02-23 21:53:31 +01:00
|
|
|
case GLYPHSET_INDEX_A8:
|
2005-07-21 14:31:28 +00:00
|
|
|
break;
|
2010-02-23 21:53:31 +01:00
|
|
|
case GLYPHSET_INDEX_ARGB32:
|
2010-04-18 23:20:02 +02:00
|
|
|
if (_native_byte_order_lsb() != (ImageByteOrder (display->display) == LSBFirst)) {
|
2009-06-02 18:07:31 +01:00
|
|
|
unsigned int c = glyph_surface->stride * glyph_surface->height / 4;
|
|
|
|
|
const uint32_t *d;
|
|
|
|
|
uint32_t *new, *n;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2009-06-02 18:07:31 +01:00
|
|
|
new = malloc (4 * c);
|
2008-11-18 17:26:55 +00:00
|
|
|
if (unlikely (new == NULL)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
2006-05-01 10:17:08 -07:00
|
|
|
goto BAIL;
|
|
|
|
|
}
|
2005-07-21 14:31:28 +00:00
|
|
|
n = new;
|
2009-06-02 18:07:31 +01:00
|
|
|
d = (uint32_t *) data;
|
|
|
|
|
do {
|
2010-03-31 08:21:17 +01:00
|
|
|
*n++ = bswap_32 (*d);
|
|
|
|
|
d++;
|
2009-06-02 18:07:31 +01:00
|
|
|
} while (--c);
|
|
|
|
|
data = (uint8_t *) new;
|
2005-07-21 14:31:28 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT_NOT_REACHED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* XXX assume X server wants pixman padding. Xft assumes this as well */
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XRenderAddGlyphs (display->display, glyphset_info->glyphset,
|
2008-04-02 14:53:25 +01:00
|
|
|
&glyph_index, &glyph_info, 1,
|
2005-07-21 14:31:28 +00:00
|
|
|
(char *) data,
|
2005-08-31 15:08:02 +00:00
|
|
|
glyph_surface->stride * glyph_surface->height);
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
if (data != glyph_surface->data)
|
2005-07-21 14:31:28 +00:00
|
|
|
free (data);
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2008-05-01 19:46:58 +01:00
|
|
|
_cairo_xlib_scaled_glyph_set_glyphset_info (scaled_glyph, glyphset_info);
|
|
|
|
|
|
2006-05-01 10:17:08 -07:00
|
|
|
BAIL:
|
|
|
|
|
if (glyph_surface != scaled_glyph->surface)
|
|
|
|
|
cairo_surface_destroy (&glyph_surface->base);
|
|
|
|
|
|
2007-10-19 15:02:03 -04:00
|
|
|
/* if the scaled glyph didn't already have a surface attached
|
|
|
|
|
* to it, release the created surface now that we have it
|
|
|
|
|
* uploaded to the X server. If the surface has already been
|
|
|
|
|
* there (eg. because image backend requested it), leave it in
|
|
|
|
|
* the cache
|
|
|
|
|
*/
|
|
|
|
|
if (!already_had_glyph_surface)
|
|
|
|
|
_cairo_scaled_glyph_set_surface (scaled_glyph, scaled_font, NULL);
|
|
|
|
|
|
2006-05-01 10:17:08 -07:00
|
|
|
return status;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
typedef void (*cairo_xrender_composite_text_func_t)
|
|
|
|
|
(Display *dpy,
|
|
|
|
|
int op,
|
|
|
|
|
Picture src,
|
|
|
|
|
Picture dst,
|
|
|
|
|
_Xconst XRenderPictFormat *maskFormat,
|
|
|
|
|
int xSrc,
|
|
|
|
|
int ySrc,
|
|
|
|
|
int xDst,
|
|
|
|
|
int yDst,
|
|
|
|
|
_Xconst XGlyphElt8 *elts,
|
|
|
|
|
int nelt);
|
|
|
|
|
|
2008-01-28 20:49:44 -05:00
|
|
|
/* Build a struct of the same size of #cairo_glyph_t that can be used both as
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
* an input glyph with double coordinates, and as "working" glyph with
|
|
|
|
|
* integer from-current-point offsets. */
|
2008-05-28 17:04:09 -04:00
|
|
|
typedef union {
|
2008-05-28 17:12:51 -04:00
|
|
|
cairo_glyph_t d;
|
2008-05-28 17:04:09 -04:00
|
|
|
unsigned long index;
|
2008-05-28 17:12:51 -04:00
|
|
|
struct {
|
|
|
|
|
unsigned long index;
|
|
|
|
|
int x;
|
|
|
|
|
int y;
|
|
|
|
|
} i;
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
} cairo_xlib_glyph_t;
|
|
|
|
|
|
2008-01-28 20:49:44 -05:00
|
|
|
/* compile-time assert that #cairo_xlib_glyph_t is the same size as #cairo_glyph_t */
|
2008-05-28 13:10:07 -04:00
|
|
|
COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t));
|
2007-12-17 01:14:27 -05:00
|
|
|
|
2008-09-30 23:19:01 +01:00
|
|
|
/* Start a new element for the first glyph,
|
|
|
|
|
* or for any glyph that has unexpected position,
|
|
|
|
|
* or if current element has too many glyphs
|
|
|
|
|
* (Xrender limits each element to 252 glyphs, we limit them to 128)
|
|
|
|
|
*
|
|
|
|
|
* These same conditions need to be mirrored between
|
|
|
|
|
* _cairo_xlib_surface_emit_glyphs and _emit_glyph_chunks
|
|
|
|
|
*/
|
|
|
|
|
#define _start_new_glyph_elt(count, glyph) \
|
|
|
|
|
(((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y)
|
|
|
|
|
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
static cairo_status_t
|
2010-04-18 23:20:02 +02:00
|
|
|
_emit_glyphs_chunk (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *dst,
|
2008-09-30 17:41:51 -04:00
|
|
|
cairo_xlib_glyph_t *glyphs,
|
|
|
|
|
int num_glyphs,
|
|
|
|
|
cairo_scaled_font_t *scaled_font,
|
|
|
|
|
cairo_operator_t op,
|
|
|
|
|
cairo_xlib_surface_t *src,
|
|
|
|
|
cairo_surface_attributes_t *attributes,
|
|
|
|
|
/* info for this chunk */
|
|
|
|
|
int num_elts,
|
|
|
|
|
int width,
|
|
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info)
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
{
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
/* Which XRenderCompositeText function to use */
|
|
|
|
|
cairo_xrender_composite_text_func_t composite_text_func;
|
2008-09-30 17:26:46 -04:00
|
|
|
int size;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
/* Element buffer stuff */
|
2008-09-30 13:33:25 +01:00
|
|
|
XGlyphElt8 *elts;
|
2008-09-30 17:26:46 -04:00
|
|
|
XGlyphElt8 stack_elts[CAIRO_STACK_ARRAY_LENGTH (XGlyphElt8)];
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
/* Reuse the input glyph array for output char generation */
|
|
|
|
|
char *char8 = (char *) glyphs;
|
|
|
|
|
unsigned short *char16 = (unsigned short *) glyphs;
|
|
|
|
|
unsigned int *char32 = (unsigned int *) glyphs;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
int i;
|
|
|
|
|
int nelt; /* Element index */
|
|
|
|
|
int n; /* Num output glyphs in current element */
|
|
|
|
|
int j; /* Num output glyphs so far */
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
switch (width) {
|
|
|
|
|
case 1:
|
|
|
|
|
/* don't cast the 8-variant, to catch possible mismatches */
|
|
|
|
|
composite_text_func = XRenderCompositeText8;
|
2008-09-30 17:26:46 -04:00
|
|
|
size = sizeof (char);
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText16;
|
2008-09-30 17:26:46 -04:00
|
|
|
size = sizeof (unsigned short);
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
case 4:
|
|
|
|
|
composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText32;
|
2008-09-30 17:26:46 -04:00
|
|
|
size = sizeof (unsigned int);
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
/* Allocate element array */
|
2008-09-30 17:26:46 -04:00
|
|
|
if (num_elts <= ARRAY_LENGTH (stack_elts)) {
|
|
|
|
|
elts = stack_elts;
|
|
|
|
|
} else {
|
2007-06-19 13:15:21 -07:00
|
|
|
elts = _cairo_malloc_ab (num_elts, sizeof (XGlyphElt8));
|
2008-11-18 17:26:55 +00:00
|
|
|
if (unlikely (elts == NULL))
|
2007-10-04 13:15:46 +01:00
|
|
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fill them in */
|
|
|
|
|
nelt = 0;
|
|
|
|
|
n = 0;
|
|
|
|
|
j = 0;
|
|
|
|
|
for (i = 0; i < num_glyphs; i++) {
|
2008-09-30 17:26:46 -04:00
|
|
|
|
2008-09-30 23:19:01 +01:00
|
|
|
/* Start a new element for first output glyph,
|
2008-09-30 17:55:01 -04:00
|
|
|
* or for any glyph that has unexpected position,
|
2008-09-30 23:19:01 +01:00
|
|
|
* or if current element has too many glyphs.
|
2008-09-30 17:55:01 -04:00
|
|
|
*
|
2008-09-30 23:19:01 +01:00
|
|
|
* These same conditions are mirrored in _cairo_xlib_surface_emit_glyphs()
|
2008-09-30 17:55:01 -04:00
|
|
|
*/
|
2008-09-30 23:19:01 +01:00
|
|
|
if (_start_new_glyph_elt (j, &glyphs[i])) {
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
if (j) {
|
2008-09-30 17:26:46 -04:00
|
|
|
elts[nelt].nchars = n;
|
|
|
|
|
nelt++;
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
n = 0;
|
|
|
|
|
}
|
2008-09-30 17:26:46 -04:00
|
|
|
elts[nelt].chars = char8 + size * j;
|
2007-12-17 01:14:27 -05:00
|
|
|
elts[nelt].glyphset = glyphset_info->glyphset;
|
2008-05-28 17:04:09 -04:00
|
|
|
elts[nelt].xOff = glyphs[i].i.x;
|
|
|
|
|
elts[nelt].yOff = glyphs[i].i.y;
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (width) {
|
|
|
|
|
case 1: char8 [j] = (char) glyphs[i].index; break;
|
|
|
|
|
case 2: char16[j] = (unsigned short) glyphs[i].index; break;
|
|
|
|
|
default:
|
|
|
|
|
case 4: char32[j] = (unsigned int) glyphs[i].index; break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
n++;
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-30 17:26:46 -04:00
|
|
|
if (n) {
|
|
|
|
|
elts[nelt].nchars = n;
|
|
|
|
|
nelt++;
|
|
|
|
|
}
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
|
2008-09-30 23:19:01 +01:00
|
|
|
/* Check that we agree with _cairo_xlib_surface_emit_glyphs() on the
|
|
|
|
|
* expected number of xGlyphElts. */
|
|
|
|
|
assert (nelt == num_elts);
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
composite_text_func (display->display,
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
_render_operator (op),
|
|
|
|
|
src->src_picture,
|
|
|
|
|
dst->dst_picture,
|
2007-12-17 01:14:27 -05:00
|
|
|
glyphset_info->xrender_format,
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
attributes->x_offset + elts[0].xOff,
|
|
|
|
|
attributes->y_offset + elts[0].yOff,
|
|
|
|
|
elts[0].xOff, elts[0].yOff,
|
|
|
|
|
(XGlyphElt8 *) elts, nelt);
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
if (elts != stack_elts)
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
free (elts);
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2005-08-31 15:08:02 +00:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
2008-09-30 17:46:06 -04:00
|
|
|
|
|
|
|
|
/* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have
|
|
|
|
|
* enough room for padding */
|
|
|
|
|
#define _cairo_sz_xGlyphElt (sz_xGlyphElt + 4)
|
|
|
|
|
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
static cairo_status_t
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_emit_glyphs (cairo_xlib_display_t *display,
|
|
|
|
|
cairo_xlib_surface_t *dst,
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
cairo_xlib_glyph_t *glyphs,
|
|
|
|
|
int num_glyphs,
|
|
|
|
|
cairo_scaled_font_t *scaled_font,
|
|
|
|
|
cairo_operator_t op,
|
|
|
|
|
cairo_xlib_surface_t *src,
|
2008-05-23 19:57:48 -04:00
|
|
|
cairo_surface_attributes_t *attributes,
|
|
|
|
|
int *remaining_glyphs)
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
{
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
int i;
|
|
|
|
|
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
|
|
|
|
cairo_scaled_glyph_t *scaled_glyph;
|
|
|
|
|
cairo_fixed_t x = 0, y = 0;
|
2007-12-17 01:14:27 -05:00
|
|
|
cairo_xlib_font_glyphset_info_t *glyphset_info = NULL, *this_glyphset_info;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
unsigned long max_index = 0;
|
|
|
|
|
int width = 1;
|
|
|
|
|
int num_elts = 0;
|
2008-09-30 17:26:46 -04:00
|
|
|
int num_out_glyphs = 0;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
int max_request_size = XMaxRequestSize (display->display) * 4
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
- MAX (sz_xRenderCompositeGlyphs8Req,
|
|
|
|
|
MAX(sz_xRenderCompositeGlyphs16Req,
|
|
|
|
|
sz_xRenderCompositeGlyphs32Req));
|
|
|
|
|
int request_size = 0;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
_cairo_xlib_surface_ensure_dst_picture (display, dst);
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
for (i = 0; i < num_glyphs; i++) {
|
|
|
|
|
int this_x, this_y;
|
2008-09-30 17:26:46 -04:00
|
|
|
int old_width;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
status = _cairo_scaled_glyph_lookup (scaled_font,
|
|
|
|
|
glyphs[i].index,
|
|
|
|
|
CAIRO_SCALED_GLYPH_INFO_METRICS,
|
|
|
|
|
&scaled_glyph);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (unlikely (status))
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
return status;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2008-05-28 17:04:09 -04:00
|
|
|
this_x = _cairo_lround (glyphs[i].d.x);
|
|
|
|
|
this_y = _cairo_lround (glyphs[i].d.y);
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
/* Glyph skipping:
|
|
|
|
|
*
|
2007-10-19 15:02:03 -04:00
|
|
|
* We skip any glyphs that have troublesome coordinates. We want
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
* to make sure that (glyph2.x - (glyph1.x + glyph1.width)) fits in
|
|
|
|
|
* a signed 16bit integer, otherwise it will overflow in the render
|
|
|
|
|
* protocol.
|
|
|
|
|
* To ensure this, we'll make sure that (glyph2.x - glyph1.x) fits in
|
|
|
|
|
* a signed 15bit integer. The trivial option would be to allow
|
|
|
|
|
* coordinates -8192..8192, but that's kinda dull. It probably will
|
|
|
|
|
* take a decade or so to get monitors 8192x4096 or something. A
|
|
|
|
|
* negative value of -8192 on the other hand, is absolutely useless.
|
|
|
|
|
* Note that we do want to allow some negative positions. The glyph
|
|
|
|
|
* may start off the screen but part of it make it to the screen.
|
2008-05-23 20:46:36 -04:00
|
|
|
* Anyway, we will allow positions in the range -4096..122887. That
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
* will buy us a few more years before this stops working.
|
2008-05-23 20:57:21 -04:00
|
|
|
*
|
|
|
|
|
* Update: upon seeing weird glyphs, we just return and let fallback
|
|
|
|
|
* code do the job.
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
*/
|
2008-05-23 20:57:21 -04:00
|
|
|
if (((this_x+4096)|(this_y+4096))&~0x3fffu)
|
|
|
|
|
break;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
/* Send unsent glyphs to the server */
|
2007-12-17 01:55:15 -05:00
|
|
|
if (_cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph) == NULL) {
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_add_glyph (display,
|
2007-12-17 01:14:27 -05:00
|
|
|
scaled_font,
|
|
|
|
|
&scaled_glyph);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status)) {
|
2008-05-23 20:43:08 -04:00
|
|
|
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
|
|
|
|
/* Break so we flush glyphs so far and let fallback code
|
|
|
|
|
* handle the rest */
|
|
|
|
|
break;
|
|
|
|
|
|
2007-12-17 01:14:27 -05:00
|
|
|
return status;
|
2008-05-23 19:57:48 -04:00
|
|
|
}
|
2007-12-17 01:14:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this_glyphset_info = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph);
|
|
|
|
|
if (!glyphset_info)
|
|
|
|
|
glyphset_info = this_glyphset_info;
|
|
|
|
|
|
2008-09-30 17:40:56 -04:00
|
|
|
/* The invariant here is that we can always flush the glyphs
|
|
|
|
|
* accumulated before this one, using old_width, and they
|
|
|
|
|
* would fit in the request.
|
|
|
|
|
*/
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
old_width = width;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
/* Update max glyph index */
|
|
|
|
|
if (glyphs[i].index > max_index) {
|
|
|
|
|
max_index = glyphs[i].index;
|
|
|
|
|
if (max_index >= 65536)
|
|
|
|
|
width = 4;
|
|
|
|
|
else if (max_index >= 256)
|
|
|
|
|
width = 2;
|
2008-09-30 17:26:46 -04:00
|
|
|
if (width != old_width)
|
|
|
|
|
request_size += (width - old_width) * num_out_glyphs;
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
}
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
/* If we will pass the max request size by adding this glyph,
|
2008-09-30 17:26:46 -04:00
|
|
|
* flush current glyphs. Note that we account for a
|
|
|
|
|
* possible element being added below.
|
2007-12-17 01:14:27 -05:00
|
|
|
*
|
|
|
|
|
* Also flush if changing glyphsets, as Xrender limits one mask
|
|
|
|
|
* format per request, so we can either break up, or use a
|
2007-12-17 01:55:15 -05:00
|
|
|
* wide-enough mask format. We do the former. One reason to
|
|
|
|
|
* prefer the latter is the fact that Xserver ADDs all glyphs
|
|
|
|
|
* to the mask first, and then composes that to final surface,
|
|
|
|
|
* though it's not a big deal.
|
2007-12-17 01:14:27 -05:00
|
|
|
*/
|
2008-09-30 17:46:06 -04:00
|
|
|
if (request_size + width > max_request_size - _cairo_sz_xGlyphElt ||
|
2008-09-30 17:26:46 -04:00
|
|
|
(this_glyphset_info != glyphset_info)) {
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _emit_glyphs_chunk (display, dst, glyphs, i,
|
2008-09-30 17:41:51 -04:00
|
|
|
scaled_font, op, src, attributes,
|
|
|
|
|
num_elts, old_width, glyphset_info);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (unlikely (status))
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
glyphs += i;
|
|
|
|
|
num_glyphs -= i;
|
|
|
|
|
i = 0;
|
|
|
|
|
max_index = glyphs[i].index;
|
|
|
|
|
width = max_index < 256 ? 1 : max_index < 65536 ? 2 : 4;
|
2008-09-30 17:26:46 -04:00
|
|
|
request_size = 0;
|
|
|
|
|
num_elts = 0;
|
|
|
|
|
num_out_glyphs = 0;
|
|
|
|
|
x = y = 0;
|
2008-09-30 13:33:25 +01:00
|
|
|
glyphset_info = this_glyphset_info;
|
2008-09-30 17:26:46 -04:00
|
|
|
}
|
2008-09-30 13:33:25 +01:00
|
|
|
|
2008-09-30 17:26:46 -04:00
|
|
|
/* Convert absolute glyph position to relative-to-current-point
|
|
|
|
|
* position */
|
|
|
|
|
glyphs[i].i.x = this_x - x;
|
|
|
|
|
glyphs[i].i.y = this_y - y;
|
|
|
|
|
|
2008-09-30 17:55:01 -04:00
|
|
|
/* Start a new element for the first glyph,
|
|
|
|
|
* or for any glyph that has unexpected position,
|
2008-09-30 23:19:01 +01:00
|
|
|
* or if current element has too many glyphs.
|
2008-09-30 17:55:01 -04:00
|
|
|
*
|
2008-09-30 23:19:01 +01:00
|
|
|
* These same conditions are mirrored in _emit_glyphs_chunk().
|
2008-09-30 17:55:01 -04:00
|
|
|
*/
|
2008-09-30 23:19:01 +01:00
|
|
|
if (_start_new_glyph_elt (num_out_glyphs, &glyphs[i])) {
|
2008-09-30 17:26:46 -04:00
|
|
|
num_elts++;
|
2008-09-30 17:46:06 -04:00
|
|
|
request_size += _cairo_sz_xGlyphElt;
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
}
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
2008-09-30 17:26:46 -04:00
|
|
|
/* adjust current-position */
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
x = this_x + scaled_glyph->x_advance;
|
|
|
|
|
y = this_y + scaled_glyph->y_advance;
|
2008-09-30 17:26:46 -04:00
|
|
|
|
|
|
|
|
num_out_glyphs++;
|
|
|
|
|
request_size += width;
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
}
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (num_elts) {
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _emit_glyphs_chunk (display, dst, glyphs, i,
|
2008-09-30 17:41:51 -04:00
|
|
|
scaled_font, op, src, attributes,
|
|
|
|
|
num_elts, width, glyphset_info);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
}
|
2008-05-23 20:57:21 -04:00
|
|
|
|
2008-05-23 20:43:08 -04:00
|
|
|
*remaining_glyphs = num_glyphs - i;
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (*remaining_glyphs != 0 && status == CAIRO_STATUS_SUCCESS)
|
2008-05-23 20:57:21 -04:00
|
|
|
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
[Xlib] Rewrite an optimized cairo_xlib_show_glyphs()
The old implementation was a very naive one that used to generate one XRender
glyph element per glyph. That is, position glyphs individually. This was
raised here:
http://lists.freedesktop.org/archives/cairo/2006-December/008835.html
The new implmentation is a free rewriting of the Xft logic, that is,
compressing glyphs with "natural" advance into elements, but with various
optimizations and improvements.
In short, it works like this: glyphs are looped over, skipping those that are
not desired, and computing offset from "current position". Whenever a glyph
has non-zero offsets from the current position, a new element should be
started. All these are used to compute the request size in the render
protocol. Whenever the request size may exceed the max request size, or at
the end, glyphs are flushed. For this to work, we now set non-zero glyph
advances when sending glyphs to the server.
Notable optimizations and improvements include:
- Reusing the input glyph array (with double glyph positions) as a working
array to compute glyph offsets.
- Reusing the input glyph array as the output glyph-index array to be passed
to XRender.
- Marking glyphs to be skipped as so, avoiding a copy of the glyph array,
which is what the old code was doing.
- Skip glyphs with positions "out-of-range". That is, those with positions
that would cause an overflow in Xrender's glyph offset calculations.
On my Fedora desktop on Pentium 4, and on a Nokia 770, it shows a 6% speedup on
the timetext test.
2006-12-11 03:31:10 -05:00
|
|
|
|
|
|
|
|
return status;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
}
|
|
|
|
|
|
2008-10-21 22:48:17 +01:00
|
|
|
static cairo_bool_t
|
|
|
|
|
_cairo_xlib_surface_owns_font (cairo_xlib_surface_t *dst,
|
|
|
|
|
cairo_scaled_font_t *scaled_font)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_font_private_t *font_private;
|
|
|
|
|
|
|
|
|
|
font_private = scaled_font->surface_private;
|
|
|
|
|
if ((scaled_font->surface_backend != NULL &&
|
|
|
|
|
scaled_font->surface_backend != &cairo_xlib_surface_backend) ||
|
2010-04-18 23:20:02 +02:00
|
|
|
(font_private != NULL && font_private->device != dst->base.device))
|
2008-10-21 22:48:17 +01:00
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-19 16:29:04 +00:00
|
|
|
static cairo_int_status_t
|
2006-03-08 21:08:57 -08:00
|
|
|
_cairo_xlib_surface_show_glyphs (void *abstract_dst,
|
|
|
|
|
cairo_operator_t op,
|
2008-10-22 19:24:44 +01:00
|
|
|
const cairo_pattern_t *src_pattern,
|
2007-08-31 16:53:21 +01:00
|
|
|
cairo_glyph_t *glyphs,
|
2006-03-08 21:08:57 -08:00
|
|
|
int num_glyphs,
|
2008-05-23 19:57:48 -04:00
|
|
|
cairo_scaled_font_t *scaled_font,
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
cairo_clip_t *clip,
|
|
|
|
|
int *remaining_glyphs)
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
{
|
2006-06-22 22:32:57 -07:00
|
|
|
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
2006-03-08 21:08:57 -08:00
|
|
|
cairo_xlib_surface_t *dst = (cairo_xlib_surface_t*) abstract_dst;
|
|
|
|
|
composite_operation_t operation;
|
|
|
|
|
cairo_surface_attributes_t attributes;
|
|
|
|
|
cairo_xlib_surface_t *src = NULL;
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
cairo_region_t *clip_region = NULL;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2006-03-08 21:08:57 -08:00
|
|
|
|
2008-10-10 14:00:32 +01:00
|
|
|
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst))
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("XRender does not support CompositeText");
|
2005-03-03 17:40:04 +00:00
|
|
|
|
2006-03-08 21:08:57 -08:00
|
|
|
/* Just let unbounded operators go through the fallback code
|
|
|
|
|
* instead of trying to do the fixups here */
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (! _cairo_operator_bounded_by_mask (op))
|
|
|
|
|
return UNSUPPORTED ("unsupported unbounded op");
|
2006-03-08 21:08:57 -08:00
|
|
|
|
|
|
|
|
/* Render <= 0.10 seems to have a bug with PictOpSrc and glyphs --
|
|
|
|
|
* the solid source seems to be multiplied by the glyph mask, and
|
|
|
|
|
* then the entire thing is copied to the destination surface,
|
|
|
|
|
* including the fully transparent "background" of the rectangular
|
|
|
|
|
* glyph surface. */
|
|
|
|
|
if (op == CAIRO_OPERATOR_SOURCE &&
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
! CAIRO_SURFACE_RENDER_AT_LEAST(dst, 0, 11))
|
|
|
|
|
{
|
|
|
|
|
return UNSUPPORTED ("known bug in Render");
|
|
|
|
|
}
|
2006-03-08 21:08:57 -08:00
|
|
|
|
|
|
|
|
/* We can only use our code if we either have no clip or
|
|
|
|
|
* have a real native clip region set. If we're using
|
|
|
|
|
* fallback clip masking, we have to go through the full
|
|
|
|
|
* fallback path.
|
|
|
|
|
*/
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (clip != NULL) {
|
|
|
|
|
status = _cairo_clip_get_region (clip, &clip_region);
|
|
|
|
|
assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
|
|
|
|
|
if (status)
|
|
|
|
|
return status;
|
|
|
|
|
}
|
2006-03-08 21:08:57 -08:00
|
|
|
|
|
|
|
|
operation = _categorize_composite_operation (dst, op, src_pattern, TRUE);
|
2005-06-20 15:48:46 +00:00
|
|
|
if (operation == DO_UNSUPPORTED)
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("unsupported op");
|
2006-03-08 21:08:57 -08:00
|
|
|
|
2008-10-21 22:48:17 +01:00
|
|
|
if (! _cairo_xlib_surface_owns_font (dst, scaled_font))
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
return UNSUPPORTED ("unowned font");
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (dst->base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
X_DEBUG ((display->display, "show_glyphs (dst=%x)", (unsigned int) dst->drawable));
|
2009-09-29 03:02:40 +01:00
|
|
|
|
2009-09-11 14:56:17 +01:00
|
|
|
if (clip_region != NULL &&
|
|
|
|
|
cairo_region_num_rectangles (clip_region) == 1)
|
|
|
|
|
{
|
|
|
|
|
cairo_rectangle_int_t glyph_extents;
|
|
|
|
|
const cairo_rectangle_int_t *clip_extents;
|
|
|
|
|
|
|
|
|
|
/* Can we do without the clip?
|
|
|
|
|
* Around 50% of the time the clip is redundant (firefox).
|
|
|
|
|
*/
|
|
|
|
|
_cairo_scaled_font_glyph_approximate_extents (scaled_font,
|
|
|
|
|
glyphs, num_glyphs,
|
|
|
|
|
&glyph_extents);
|
|
|
|
|
|
|
|
|
|
clip_extents = &clip->path->extents;
|
|
|
|
|
if (clip_extents->x <= glyph_extents.x &&
|
|
|
|
|
clip_extents->y <= glyph_extents.y &&
|
|
|
|
|
clip_extents->x + clip_extents->width >= glyph_extents.x + glyph_extents.width &&
|
|
|
|
|
clip_extents->y + clip_extents->height >= glyph_extents.y + glyph_extents.height)
|
|
|
|
|
{
|
|
|
|
|
clip_region = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
status = _cairo_xlib_surface_set_clip_region (dst, clip_region);
|
|
|
|
|
if (unlikely (status))
|
2010-04-18 23:20:02 +02:00
|
|
|
goto BAIL0;
|
2005-08-31 15:08:02 +00:00
|
|
|
|
2006-06-22 22:32:57 -07:00
|
|
|
/* After passing all those tests, we're now committed to rendering
|
|
|
|
|
* these glyphs or to fail trying. We first upload any glyphs to
|
|
|
|
|
* the X server that it doesn't have already, then we draw
|
2008-10-21 22:48:17 +01:00
|
|
|
* them.
|
|
|
|
|
*/
|
2006-06-22 22:32:57 -07:00
|
|
|
|
2006-03-08 21:08:57 -08:00
|
|
|
/* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
|
|
|
|
|
* the mask (the glyphs). This code below was executed as a side effect
|
|
|
|
|
* of going through the _clip_and_composite fallback code for old_show_glyphs,
|
|
|
|
|
* so PictOpClear was never used with CompositeText before.
|
|
|
|
|
*/
|
|
|
|
|
if (op == CAIRO_OPERATOR_CLEAR) {
|
2010-01-22 16:19:31 +00:00
|
|
|
src_pattern = &_cairo_pattern_white.base;
|
2006-03-08 21:08:57 -08:00
|
|
|
op = CAIRO_OPERATOR_DEST_OUT;
|
|
|
|
|
}
|
|
|
|
|
|
2006-03-27 13:49:58 -08:00
|
|
|
if (src_pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
|
|
|
|
|
status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
|
|
|
|
|
0, 0, 1, 1,
|
2009-05-28 14:16:58 +01:00
|
|
|
CAIRO_PATTERN_ACQUIRE_NONE,
|
2006-03-27 13:49:58 -08:00
|
|
|
(cairo_surface_t **) &src,
|
|
|
|
|
&attributes);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2007-04-09 17:37:30 -07:00
|
|
|
goto BAIL0;
|
2006-03-27 13:49:58 -08:00
|
|
|
} else {
|
2008-01-22 15:32:11 -08:00
|
|
|
cairo_rectangle_int_t glyph_extents;
|
2006-03-27 13:49:58 -08:00
|
|
|
|
|
|
|
|
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
|
|
|
|
|
glyphs,
|
|
|
|
|
num_glyphs,
|
2009-07-28 15:58:54 +01:00
|
|
|
&glyph_extents,
|
|
|
|
|
NULL);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2007-03-29 09:11:21 +01:00
|
|
|
goto BAIL0;
|
2006-03-27 13:49:58 -08:00
|
|
|
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
if (clip != NULL) {
|
|
|
|
|
if (! _cairo_rectangle_intersect (&glyph_extents,
|
|
|
|
|
_cairo_clip_get_extents (clip)))
|
|
|
|
|
{
|
|
|
|
|
goto BAIL0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_acquire_pattern_surface (display,
|
|
|
|
|
dst, src_pattern,
|
2009-07-31 13:17:24 +01:00
|
|
|
glyph_extents.x,
|
|
|
|
|
glyph_extents.y,
|
|
|
|
|
glyph_extents.width,
|
|
|
|
|
glyph_extents.height,
|
|
|
|
|
&src, &attributes);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2007-03-29 09:11:21 +01:00
|
|
|
goto BAIL0;
|
2006-03-27 13:49:58 -08:00
|
|
|
}
|
|
|
|
|
|
2008-10-10 14:00:32 +01:00
|
|
|
operation = _recategorize_composite_operation (dst, op, src,
|
|
|
|
|
&attributes, TRUE);
|
2005-06-20 15:48:46 +00:00
|
|
|
if (operation == DO_UNSUPPORTED) {
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
status = UNSUPPORTED ("unsupported op");
|
2007-03-29 09:11:21 +01:00
|
|
|
goto BAIL1;
|
2005-06-20 15:48:46 +00:00
|
|
|
}
|
2006-03-08 21:08:57 -08:00
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_set_attributes (display, src, &attributes, 0, 0);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2007-03-29 09:11:21 +01:00
|
|
|
goto BAIL1;
|
2006-03-08 21:08:57 -08:00
|
|
|
|
2008-10-21 22:48:17 +01:00
|
|
|
_cairo_scaled_font_freeze_cache (scaled_font);
|
|
|
|
|
if (_cairo_xlib_surface_owns_font (dst, scaled_font)) {
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_surface_emit_glyphs (display,
|
|
|
|
|
dst,
|
2008-10-21 22:48:17 +01:00
|
|
|
(cairo_xlib_glyph_t *) glyphs,
|
|
|
|
|
num_glyphs,
|
|
|
|
|
scaled_font,
|
|
|
|
|
op,
|
|
|
|
|
src,
|
|
|
|
|
&attributes,
|
|
|
|
|
remaining_glyphs);
|
Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of
the operation state, is cumbersome and a hindrance to providing true proxy
surface support. For example, the clip must be copied from the surface
onto the fallback image, but this was forgotten causing undue hassle in
each backend. Another example is the contortion the meta surface
endures to ensure the clip is correctly recorded. By contrast passing the
clip along with the operation is quite simple and enables us to write
generic handlers for providing surface wrappers. (And in the future, we
should be able to write more esoteric wrappers, e.g. automatic 2x FSAA,
trivially.)
In brief, instead of the surface automatically applying the clip before
calling the backend, the backend can call into a generic helper to apply
clipping. For raster surfaces, clip regions are handled automatically as
part of the composite interface. For vector surfaces, a clip helper is
introduced to replay and callback into an intersect_clip_path() function
as necessary.
Whilst this is not primarily a performance related change (the change
should just move the computation of the clip from the moment it is applied
by the user to the moment it is required by the backend), it is important
to track any potential regression:
ppc:
Speedups
========
image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup
▌
image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup
▎
image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup
▏
image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup
▏
Slowdowns
=========
image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown
▏
2009-07-23 15:32:13 +01:00
|
|
|
} else {
|
|
|
|
|
status = UNSUPPORTED ("unowned font");
|
|
|
|
|
}
|
2008-10-21 22:48:17 +01:00
|
|
|
_cairo_scaled_font_thaw_cache (scaled_font);
|
2005-08-31 15:08:02 +00:00
|
|
|
|
2007-03-29 09:11:21 +01:00
|
|
|
BAIL1:
|
2006-03-08 21:08:57 -08:00
|
|
|
if (src)
|
|
|
|
|
_cairo_pattern_release_surface (src_pattern, &src->base, &attributes);
|
2007-03-29 09:11:21 +01:00
|
|
|
BAIL0:
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_device_release (&display->base);
|
2006-06-22 22:38:17 -07:00
|
|
|
|
2005-01-27 19:57:31 +00:00
|
|
|
return status;
|
Add cairo_cache.c
Rewrite using temporary glyph arrays
New file.
Remove old glyph cache code. (_cairo_font_scale) (_cairo_font_transform): Remove font-transforming code. (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_cache_key_t): New structure type. (_font_cache_hash) (_font_cache_keys_equal) (_font_cache_create_entry) (_font_cache_destroy_entry) (_font_cache_destroy_cache): New font cache code. (_global_font_cache) (_lock_global_font_cache) (_unlock_global_font_cache) (_get_global_font_cache): New global font cache. (_cairo_font_text_to_glyphs) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal) (_image_glyph_cache_create_entry) (_image_glyph_cache_destroy_entry) (_image_glyph_cache_destroy_cache): New glyph cache code. (_global_image_glyph_cache) (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache): New global glyph cache. (_cairo_font_cache_backend): New structure. (_cairo_image_cache_backend): Likewise. (_cairo_font_create): Reimplement in terms of font cache. (_cairo_font_init): Remove matrix and glyph cache related code. (_cairo_font_copy): Likewise. (_cairo_font_show_glyphs): Delegate to surface when possible. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Rename to as cairo_unscaled_font_XXX, and add scale parameter.
New structure types. (_create_from_face) (_reference_font_val) (_destroy_font_val) (_create_from_library_and_pattern): New functions. (_ft_font_cache_hash) (_ft_font_cache_keys_equal) (_ft_font_cache_create_entry) (_ft_font_cache_destroy_entry) (_ft_font_cache_destroy_cache): New ft font cache code. (_global_ft_cache) (_lock_global_ft_cache) (_unlock_global_ft_cache) (_get_global_ft_cache): New global ft font cache. (_ft_font_cache_backend): New structure. (_cairo_ft_font_create): Rewrite to use cache. (_cairo_ft_font_destroy): Likewise. (_cairo_ft_font_copy): Remove. (_install_font_matrix): Rename as _install_font_scale. (_utf8_to_glyphs): Rename as _cairo_ft_font_text_to_glyphs. (_cairo_ft_font_text_to_glyphs): Use cache for metrics. (_cairo_ft_font_extents): Accept size, use scaled metrics. (_cairo_ft_font_glyph_extents) (_cairo_ft_font_glyph_bbox) (_cairo_ft_font_show_glyphs) (_cairo_ft_font_glyph_path): Modify to use size, cache. (_cairo_ft_font_text_extents) (_cairo_ft_font_text_bbox) (_cairo_ft_font_show_text) (_cairo_ft_font_text_path): Remove text-API code. (cairo_ft_font_create) (cairo_ft_font_create_for_ft_face) (cairo_ft_font_face) (cairo_ft_font_pattern): Rewrite using ft_font_val_t.
Just reference font. (_cairo_gstate_fini): Finalize font matrix. (_cairo_gstate_default_matrix): Initialize font matrix. (_cairo_gstate_clip): Re-enable clipping rectangle. (_cairo_gstate_select_font) (_cairo_gstate_set_font): Set font matrix to identity. (_cairo_gstate_scale_font): Scale font matrix, not font. (_cairo_gstate_transform_font): Transform font matrix, not font. (_cairo_gstate_set_font_transform): Install as font matrix, not in font. (_build_font_scale): New helper function. (_cairo_gstate_text_to_glyphs): New function. (_cairo_gstate_current_font_extents) (_cairo_gstate_glyph_extents) (_cairo_gstate_show_glyphs) (_cairo_gstate_glyph_path): Rewrite using font matrix and size. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text): Remove text-API code.
Minor bug fix. (_cairo_xlib_surface_show_glyphs): New function. (_cairo_xlib_surface_backend): Add reference to new function. (glyphset_cache_t) (glyphset_cache_entry_t): New structure types. (_next_xlib_glyph): New helper function. (_xlib_glyphset_cache_create_value) (_xlib_glyphset_cache_destroy_cache) (_xlib_glyphset_cache_destroy_value) (_xlib_glyphset_cache_backend): New glyphset cache code. (_xlib_glyphset_caches) (_lock_xlib_glyphset_caches) (_unlock_xlib_glyphset_caches) (_get_glyphset_cache): New global glyphset cache.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
Add NULL entry for show_glyphs.
New structure type. (cairo_cache_entry_base_t) (cairo_cache_arrangement_t) (cairo_cache_t): New structure types. (_cairo_cache_init) (_cairo_cache_reference) (_cairo_cache_destroy) (_cairo_cache_lookup) (_cairo_hash_string): New cache functions. (CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT) (CAIRO_FONT_CACHE_NUM_FONTS_DEFAULT) (CAIRO_FT_CACHE_NUM_FONTS_DEFAULT): New constants. (cairo_font_scale_t) (cairo_glyph_cache_key_t) (cairo_image_glyph_cache_entry_t): New structure types. (_cairo_lock_global_image_glyph_cache) (_cairo_unlock_global_image_glyph_cache) (_cairo_get_global_image_glyph_cache) (_cairo_glyph_cache_hash) (_cairo_glyph_cache_keys_equal): New functions for glyph caches. (cairo_font_backend_t): Remove text-API calls, add scale params, remove copy call. (cairo_surface_backend_t): Add show_glyphs entry. (cairo_glyph_surface_t) (cairo_glyph_surface_node_t): Remove old glyph cache structures. (cairo_unscaled_font_t): New structure type. (cairo_font): Remove glyph cache member, add pointer to unscaled. (cairo_gstate): Add font_matrix member, change to hold unscaled. (_cairo_gstate_set_font_transform) (_cairo_gstate_current_font_transform) (_cairo_gstate_text_to_glyphs): New functions. (_cairo_gstate_text_path (_cairo_gstate_text_extents) (_cairo_gstate_show_text) (_cairo_font_text_extents) (_cairo_font_text_bbox) (_cairo_font_show_text) (_cairo_font_text_path): Remove text-API code. (_cairo_font_glyph_extents) (_cairo_font_glyph_bbox) (_cairo_font_glyph_path) (_cairo_font_font_extents) (_cairo_font_show_glyphs): Add scale parameter.
2004-10-08 12:09:49 +00:00
|
|
|
}
|