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
|
|
|
|
2023-09-23 14:18:44 +01:00
|
|
|
/**
|
|
|
|
|
* CAIRO_HAS_XLIB_XCB_FUNCTIONS:
|
|
|
|
|
*
|
|
|
|
|
* Defined if Cairo has support for XCB integration with Xlib.
|
|
|
|
|
* This macro can be used to conditionally compile backend-specific code.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.10
|
|
|
|
|
**/
|
|
|
|
|
|
2011-06-16 08:47:56 +02:00
|
|
|
#if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
|
|
|
|
|
|
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"
|
2011-07-30 17:28:21 +01:00
|
|
|
|
|
|
|
|
#include "cairo-compositor-private.h"
|
2006-03-08 21:08:57 -08:00
|
|
|
#include "cairo-clip-private.h"
|
2012-08-13 01:34:12 +01:00
|
|
|
#include "cairo-damage-private.h"
|
2010-04-23 19:45:26 +01:00
|
|
|
#include "cairo-default-context-private.h"
|
2010-01-18 16:58:40 +00:00
|
|
|
#include "cairo-error-private.h"
|
2011-08-04 00:19:42 +01:00
|
|
|
#include "cairo-image-surface-private.h"
|
2012-04-19 11:59:54 +01:00
|
|
|
#include "cairo-list-inline.h"
|
2011-07-14 18:35:32 +01:00
|
|
|
#include "cairo-pattern-private.h"
|
2013-08-15 14:28:44 +00:00
|
|
|
#include "cairo-pixman-private.h"
|
2011-07-14 18:35:32 +01:00
|
|
|
#include "cairo-region-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"
|
2005-05-13 17:54:43 +00:00
|
|
|
|
2008-01-14 18:09:32 +00:00
|
|
|
#include <X11/Xutil.h> /* for XDestroyImage */
|
|
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
#include <X11/extensions/XShm.h>
|
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
|
#include <sys/shm.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
|
|
|
#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.
|
2012-02-16 00:31:47 +01:00
|
|
|
**/
|
2010-07-08 13:05:18 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* CAIRO_HAS_XLIB_SURFACE:
|
|
|
|
|
*
|
|
|
|
|
* Defined if the Xlib surface backend is available.
|
|
|
|
|
* This macro can be used to conditionally compile backend-specific code.
|
doc: Add "since" tag to documentation
The following Python script was used to compute "Since: 1.X" tags,
based on the first version where a symbol became officially supported.
This script requires a concatenation of the the cairo public headers
for the officially supported beckends to be available as
"../../includes/1.X.0.h".
from sys import argv
import re
syms = {}
def stripcomments(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return ""
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
for minor in range(12,-2,-2):
version = "1.%d" % minor
names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read()))
for s in names: syms[s] = version
for filename in argv[1:]:
is_public = False
lines = open(filename, "r").read().split("\n")
newlines = []
for i in range(len(lines)):
if lines[i] == "/**":
last_sym = lines[i+1][2:].strip().replace(":", "")
is_public = last_sym.lower().startswith("cairo")
elif is_public and lines[i] == " **/":
if last_sym in syms:
v = syms[last_sym]
if re.search("Since", newlines[-1]): newlines = newlines[:-1]
if newlines[-1].strip() != "*": newlines.append(" *")
newlines.append(" * Since: %s" % v)
else:
print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym)
newlines.append(lines[i])
out = open(filename, "w")
out.write("\n".join(newlines))
out.close()
2012-03-27 11:48:19 +02:00
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
2012-02-16 00:31:47 +01:00
|
|
|
**/
|
2010-07-08 13:05:18 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SECTION:cairo-xlib-xrender
|
2012-04-13 20:36:03 +02:00
|
|
|
* @Title: XLib-XRender Backend
|
2010-07-08 13:05:18 +02:00
|
|
|
* @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.
|
2012-02-16 00:31:47 +01:00
|
|
|
**/
|
2010-07-08 13:05:18 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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.
|
doc: Add "since" tag to documentation
The following Python script was used to compute "Since: 1.X" tags,
based on the first version where a symbol became officially supported.
This script requires a concatenation of the the cairo public headers
for the officially supported beckends to be available as
"../../includes/1.X.0.h".
from sys import argv
import re
syms = {}
def stripcomments(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return ""
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
for minor in range(12,-2,-2):
version = "1.%d" % minor
names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read()))
for s in names: syms[s] = version
for filename in argv[1:]:
is_public = False
lines = open(filename, "r").read().split("\n")
newlines = []
for i in range(len(lines)):
if lines[i] == "/**":
last_sym = lines[i+1][2:].strip().replace(":", "")
is_public = last_sym.lower().startswith("cairo")
elif is_public and lines[i] == " **/":
if last_sym in syms:
v = syms[last_sym]
if re.search("Since", newlines[-1]): newlines = newlines[:-1]
if newlines[-1].strip() != "*": newlines.append(" *")
newlines.append(" * Since: %s" % v)
else:
print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym)
newlines.append(lines[i])
out = open(filename, "w")
out.write("\n".join(newlines))
out.close()
2012-03-27 11:48:19 +02:00
|
|
|
*
|
|
|
|
|
* Since: 1.6
|
2012-02-16 00:31:47 +01:00
|
|
|
**/
|
2010-07-08 13:05:18 +02:00
|
|
|
|
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-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
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
{
|
2012-02-23 13:40:59 +00:00
|
|
|
cairo_content_t content;
|
2006-05-24 17:05:51 -07:00
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
2012-02-23 13:40:59 +00:00
|
|
|
content = 0;
|
|
|
|
|
if (xrender_format->direct.alphaMask)
|
|
|
|
|
content |= CAIRO_CONTENT_ALPHA;
|
|
|
|
|
if (xrender_format->direct.redMask |
|
|
|
|
|
xrender_format->direct.greenMask |
|
|
|
|
|
xrender_format->direct.blueMask)
|
|
|
|
|
content |= CAIRO_CONTENT_COLOR;
|
|
|
|
|
|
|
|
|
|
return content;
|
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
|
|
|
|
2011-07-14 21:19:54 +01:00
|
|
|
if (width == 0 || height == 0)
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2011-07-30 17:28:21 +01:00
|
|
|
xrender_format = NULL;
|
|
|
|
|
if (src->xrender_format &&
|
|
|
|
|
_xrender_format_to_content (src->xrender_format) == content)
|
2006-05-18 15:36:43 -07:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
xrender_format = src->xrender_format;
|
|
|
|
|
}
|
|
|
|
|
if (xrender_format == NULL) {
|
|
|
|
|
xrender_format =
|
|
|
|
|
_cairo_xlib_display_get_xrender_format (display,
|
|
|
|
|
_cairo_format_from_content (content));
|
|
|
|
|
}
|
|
|
|
|
if (xrender_format) {
|
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,
|
2011-07-30 17:28:21 +01:00
|
|
|
width, height, xrender_format->depth);
|
2009-09-20 18:46:19 +01:00
|
|
|
|
|
|
|
|
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 *)
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_xlib_surface_create_internal (src->screen, pix, visual,
|
2009-09-20 18:46:19 +01:00
|
|
|
xrender_format,
|
|
|
|
|
width, height,
|
|
|
|
|
xrender_format->depth);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Screen *screen = src->screen->screen;
|
|
|
|
|
int depth;
|
|
|
|
|
|
2012-03-03 23:43:56 +01:00
|
|
|
/* No compatible XRenderFormat, see if we can make an ordinary pixmap,
|
2009-09-20 18:46:19 +01:00
|
|
|
* 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);
|
2006-05-18 15:36:43 -07:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (likely (surface->base.status == CAIRO_STATUS_SUCCESS))
|
|
|
|
|
surface->owns_pixmap = TRUE;
|
|
|
|
|
else
|
2010-04-18 23:20:02 +02:00
|
|
|
XFreePixmap (display->display, pix);
|
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
|
|
|
}
|
|
|
|
|
|
2012-09-13 15:25:49 +01:00
|
|
|
static void
|
|
|
|
|
_cairo_xlib_surface_discard_shm (cairo_xlib_surface_t *surface)
|
|
|
|
|
{
|
|
|
|
|
if (surface->shm == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Force the flush for an external surface */
|
|
|
|
|
if (!surface->owns_pixmap)
|
|
|
|
|
cairo_surface_flush (surface->shm);
|
|
|
|
|
|
|
|
|
|
cairo_surface_finish (surface->shm);
|
|
|
|
|
cairo_surface_destroy (surface->shm);
|
|
|
|
|
surface->shm = NULL;
|
2012-09-13 22:50:11 +01:00
|
|
|
|
|
|
|
|
_cairo_damage_destroy (surface->base.damage);
|
|
|
|
|
surface->base.damage = NULL;
|
2012-09-13 22:56:57 +01:00
|
|
|
|
|
|
|
|
surface->fallback = 0;
|
2012-09-13 15:25:49 +01: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;
|
|
|
|
|
|
2011-08-14 13:47:14 +01:00
|
|
|
cairo_list_del (&surface->link);
|
|
|
|
|
|
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
|
|
|
|
2013-04-24 12:07:47 +02:00
|
|
|
X_DEBUG ((display->display, "finish (drawable=%x)", (unsigned int) surface->drawable));
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (surface->embedded_source.picture)
|
|
|
|
|
XRenderFreePicture (display->display, surface->embedded_source.picture);
|
|
|
|
|
if (surface->picture)
|
|
|
|
|
XRenderFreePicture (display->display, surface->picture);
|
2012-09-08 16:39:05 +01:00
|
|
|
|
2012-09-13 15:25:49 +01:00
|
|
|
_cairo_xlib_surface_discard_shm (surface);
|
2012-09-08 16:39:05 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (surface->owns_pixmap)
|
|
|
|
|
XFreePixmap (display->display, surface->drawable);
|
2010-04-18 23:20:02 +02:00
|
|
|
|
|
|
|
|
cairo_device_release (&display->base);
|
2003-10-31 10:41:37 +00:00
|
|
|
|
2007-04-17 12:03:07 +01:00
|
|
|
return status;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_status_t
|
2010-04-18 23:20:02 +02:00
|
|
|
_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;
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
2011-03-08 12:05:48 +02:00
|
|
|
int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
|
2005-08-31 15:09:35 +00:00
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
|
2012-01-17 12:37:48 +00:00
|
|
|
static int bits_per_pixel(cairo_xlib_surface_t *surface)
|
|
|
|
|
{
|
|
|
|
|
if (surface->depth > 16)
|
|
|
|
|
return 32;
|
|
|
|
|
else if (surface->depth > 8)
|
|
|
|
|
return 16;
|
|
|
|
|
else if (surface->depth > 1)
|
|
|
|
|
return 8;
|
|
|
|
|
else
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
pixman_format_code_t
|
|
|
|
|
_pixman_format_for_xlib_surface (cairo_xlib_surface_t *surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_format_masks_t masks;
|
|
|
|
|
pixman_format_code_t format;
|
|
|
|
|
|
|
|
|
|
masks.bpp = bits_per_pixel (surface);
|
|
|
|
|
masks.alpha_mask = surface->a_mask;
|
|
|
|
|
masks.red_mask = surface->r_mask;
|
|
|
|
|
masks.green_mask = surface->g_mask;
|
|
|
|
|
masks.blue_mask = surface->b_mask;
|
|
|
|
|
if (! _pixman_format_from_masks (&masks, &format))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return format;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-22 00:36:03 +01:00
|
|
|
static cairo_surface_t *
|
2006-05-04 03:43:34 -07:00
|
|
|
_get_image_surface (cairo_xlib_surface_t *surface,
|
2012-08-13 01:34:12 +01:00
|
|
|
const cairo_rectangle_int_t *extents,
|
|
|
|
|
int try_shm)
|
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;
|
2007-08-17 10:29:37 -07:00
|
|
|
pixman_format_code_t pixman_format;
|
2010-04-18 23:20:02 +02:00
|
|
|
cairo_xlib_display_t *display;
|
2003-09-30 18:56:22 +00:00
|
|
|
|
2011-07-22 00:36:03 +01:00
|
|
|
assert (extents->x >= 0);
|
|
|
|
|
assert (extents->y >= 0);
|
|
|
|
|
assert (extents->x + extents->width <= surface->width);
|
|
|
|
|
assert (extents->y + extents->height <= surface->height);
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2012-02-02 02:06:45 +00:00
|
|
|
if (surface->base.is_clear ||
|
|
|
|
|
(surface->base.serial == 0 && surface->owns_pixmap))
|
|
|
|
|
{
|
2012-08-13 01:34:12 +01:00
|
|
|
pixman_format = _pixman_format_for_xlib_surface (surface);
|
|
|
|
|
if (pixman_format)
|
2011-10-27 18:09:23 +02:00
|
|
|
{
|
|
|
|
|
return _cairo_image_surface_create_with_pixman_format (NULL,
|
|
|
|
|
pixman_format,
|
|
|
|
|
extents->width,
|
|
|
|
|
extents->height,
|
|
|
|
|
0);
|
|
|
|
|
}
|
2011-07-30 17:28:21 +01:00
|
|
|
}
|
|
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
if (surface->shm) {
|
|
|
|
|
cairo_image_surface_t *src = (cairo_image_surface_t *) surface->shm;
|
|
|
|
|
cairo_surface_t *dst;
|
|
|
|
|
cairo_surface_pattern_t pattern;
|
|
|
|
|
|
|
|
|
|
dst = cairo_image_surface_create (src->format,
|
|
|
|
|
extents->width, extents->height);
|
|
|
|
|
if (unlikely (dst->status))
|
|
|
|
|
return dst;
|
|
|
|
|
|
|
|
|
|
_cairo_pattern_init_for_surface (&pattern, &src->base);
|
|
|
|
|
cairo_matrix_init_translate (&pattern.base.matrix,
|
|
|
|
|
extents->x, extents->y);
|
|
|
|
|
status = _cairo_surface_paint (dst, CAIRO_OPERATOR_SOURCE, &pattern.base, NULL);
|
|
|
|
|
_cairo_pattern_fini (&pattern.base);
|
|
|
|
|
if (unlikely (status)) {
|
|
|
|
|
cairo_surface_destroy (dst);
|
|
|
|
|
dst = _cairo_surface_create_in_error (status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dst;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
|
|
|
|
if (status)
|
2011-07-22 00:36:03 +01:00
|
|
|
return _cairo_surface_create_in_error (status);
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
pixman_format = _pixman_format_for_xlib_surface (surface);
|
|
|
|
|
if (try_shm && pixman_format) {
|
|
|
|
|
image = (cairo_image_surface_t *)
|
2012-08-17 21:33:54 +01:00
|
|
|
_cairo_xlib_surface_create_shm__image (surface, pixman_format,
|
|
|
|
|
extents->width, extents->height);
|
2012-08-13 01:34:12 +01:00
|
|
|
if (image && image->base.status == CAIRO_STATUS_SUCCESS) {
|
|
|
|
|
cairo_xlib_error_func_t old_handler;
|
|
|
|
|
XImage shm_image;
|
|
|
|
|
Bool success;
|
|
|
|
|
|
|
|
|
|
_cairo_xlib_shm_surface_get_ximage (&image->base, &shm_image);
|
|
|
|
|
|
2017-03-07 10:05:43 +01:00
|
|
|
XSync (display->display, False);
|
2012-08-13 01:34:12 +01:00
|
|
|
old_handler = XSetErrorHandler (_noop_error_handler);
|
|
|
|
|
success = XShmGetImage (display->display,
|
|
|
|
|
surface->drawable,
|
|
|
|
|
&shm_image,
|
|
|
|
|
extents->x, extents->y,
|
|
|
|
|
AllPlanes);
|
|
|
|
|
XSetErrorHandler (old_handler);
|
|
|
|
|
|
2012-08-24 17:39:08 +01:00
|
|
|
if (success) {
|
|
|
|
|
cairo_device_release (&display->base);
|
2012-08-13 01:34:12 +01:00
|
|
|
return &image->base;
|
2012-08-24 17:39:08 +01:00
|
|
|
}
|
2012-08-13 01:34:12 +01:00
|
|
|
|
|
|
|
|
cairo_surface_destroy (&image->base);
|
xlib: Fix double free in _get_image_surface()
If XShmGetImage() fails, the code tries to continue with its normal,
non-shared-memory path. However, the image variable, which was previously set to
NULL, now points to an already-destroyed surface, causing a double-free when the
function cleans up after itself (actually, its an assertion failure because the
reference count of the surface is zero, but technically this is still a double
free).
Fix this by setting image=NULL after destroying the surface that this refers to,
to make sure this surface will not be destroyed again.
While we are here (multiple changes in a single commit are bad...), also fix the
cleanup done in bail. In practice, &image->base should be safe when image==NULL,
because this just adds some offset to the pointer (the offset here is actually
zero, so this doesn't do anything at all). However, the C standard does not
require this to be safe, so let's handle this case specially.
Note that anything that is fixed by this change is still buggy, because the only
reason why XShmGetImage() could fail would be BadDrawable, meaning that the
target we draw to does not exist or was already destroyed. This patch will
likely just cause X11 errors elsewhere and drawing to (possible) invalid
drawables is not supported by cairo anyway. This means that if SHM fails, the
following fallback code has a high chance of failing, too.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=91967
Signed-off-by: Uli Schlachter <psychon@znc.in>
2016-06-18 15:08:52 +02:00
|
|
|
image = NULL;
|
2012-08-13 01:34:12 +01:00
|
|
|
}
|
|
|
|
|
}
|
2005-05-13 17:54:43 +00:00
|
|
|
|
2011-07-22 00:36:03 +01:00
|
|
|
if (surface->use_pixmap == 0) {
|
2005-05-17 06:05:13 +00:00
|
|
|
cairo_xlib_error_func_t old_handler;
|
|
|
|
|
|
2017-03-07 10:05:43 +01:00
|
|
|
XSync (display->display, False);
|
2005-05-17 06:05:13 +00:00
|
|
|
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,
|
2011-07-22 00:36:03 +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;
|
2011-07-22 00:36:03 +01:00
|
|
|
} else {
|
2005-05-17 06:05:13 +00:00
|
|
|
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,
|
2011-07-22 00:36:03 +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) {
|
2012-02-02 01:46:56 +00:00
|
|
|
XGCValues gcv;
|
|
|
|
|
|
|
|
|
|
gcv.subwindow_mode = IncludeInferiors;
|
|
|
|
|
XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
XCopyArea (display->display, surface->drawable, pixmap, gc,
|
2011-07-22 00:36:03 +01:00
|
|
|
extents->x, extents->y,
|
|
|
|
|
extents->width, extents->height,
|
2008-10-23 14:34:30 +01:00
|
|
|
0, 0);
|
2005-03-15 16:25:30 +00:00
|
|
|
|
2012-02-02 01:46:56 +00:00
|
|
|
gcv.subwindow_mode = ClipByChildren;
|
|
|
|
|
XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
|
|
|
|
|
|
2010-04-18 23:20:02 +02:00
|
|
|
ximage = XGetImage (display->display,
|
2007-03-16 19:35:02 +00:00
|
|
|
pixmap,
|
|
|
|
|
0, 0,
|
2011-07-22 00:36:03 +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
|
|
|
|
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.
|
|
|
|
|
*/
|
2012-08-13 01:34:12 +01:00
|
|
|
if (pixman_format &&
|
|
|
|
|
ximage->bitmap_unit == 32 && ximage->bitmap_pad == 32 &&
|
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->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;
|
2011-07-22 00:36:03 +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 = (
|
2021-03-31 12:20:34 +02:00
|
|
|
(uint32_t)_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)) {
|
xlib: Fix double free in _get_image_surface()
If XShmGetImage() fails, the code tries to continue with its normal,
non-shared-memory path. However, the image variable, which was previously set to
NULL, now points to an already-destroyed surface, causing a double-free when the
function cleans up after itself (actually, its an assertion failure because the
reference count of the surface is zero, but technically this is still a double
free).
Fix this by setting image=NULL after destroying the surface that this refers to,
to make sure this surface will not be destroyed again.
While we are here (multiple changes in a single commit are bad...), also fix the
cleanup done in bail. In practice, &image->base should be safe when image==NULL,
because this just adds some offset to the pointer (the offset here is actually
zero, so this doesn't do anything at all). However, the C standard does not
require this to be safe, so let's handle this case specially.
Note that anything that is fixed by this change is still buggy, because the only
reason why XShmGetImage() could fail would be BadDrawable, meaning that the
target we draw to does not exist or was already destroyed. This patch will
likely just cause X11 errors elsewhere and drawing to (possible) invalid
drawables is not supported by cairo anyway. This means that if SHM fails, the
following fallback code has a high chance of failing, too.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=91967
Signed-off-by: Uli Schlachter <psychon@znc.in>
2016-06-18 15:08:52 +02:00
|
|
|
if (image)
|
|
|
|
|
cairo_surface_destroy (&image->base);
|
2011-07-22 00:36:03 +01:00
|
|
|
return _cairo_surface_create_in_error (status);
|
2008-03-25 17:50:37 +04:30
|
|
|
}
|
2011-07-22 00:36:03 +01:00
|
|
|
|
|
|
|
|
return &image->base;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
void
|
|
|
|
|
_cairo_xlib_surface_set_precision (cairo_xlib_surface_t *surface,
|
2010-06-11 11:16:42 +01:00
|
|
|
cairo_antialias_t antialias)
|
|
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_display_t *display = surface->display;
|
2010-06-11 11:16:42 +01:00
|
|
|
int precision;
|
|
|
|
|
|
2011-05-27 15:59:37 +01:00
|
|
|
if (display->force_precision != -1)
|
|
|
|
|
precision = display->force_precision;
|
|
|
|
|
else switch (antialias) {
|
|
|
|
|
default:
|
2010-06-11 11:16:42 +01:00
|
|
|
case CAIRO_ANTIALIAS_DEFAULT:
|
|
|
|
|
case CAIRO_ANTIALIAS_GRAY:
|
2011-05-27 15:59:37 +01:00
|
|
|
case CAIRO_ANTIALIAS_NONE:
|
2011-08-30 14:24:12 +01:00
|
|
|
case CAIRO_ANTIALIAS_FAST:
|
|
|
|
|
case CAIRO_ANTIALIAS_GOOD:
|
2010-06-11 11:16:42 +01:00
|
|
|
precision = PolyModeImprecise;
|
|
|
|
|
break;
|
2011-08-30 14:24:12 +01:00
|
|
|
case CAIRO_ANTIALIAS_BEST:
|
2010-06-19 11:15:13 +01:00
|
|
|
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;
|
2011-07-30 17:28:21 +01:00
|
|
|
XRenderChangePicture (display->display, surface->picture,
|
2010-06-11 11:16:42 +01:00
|
|
|
CPPolyMode, &pa);
|
|
|
|
|
|
|
|
|
|
surface->precision = precision;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
void
|
|
|
|
|
_cairo_xlib_surface_ensure_picture (cairo_xlib_surface_t *surface)
|
2005-05-26 11:35:44 +00:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_display_t *display = surface->display;
|
|
|
|
|
XRenderPictureAttributes pa;
|
|
|
|
|
int mask = 0;
|
2008-10-28 17:38:09 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (surface->picture)
|
|
|
|
|
return;
|
2009-06-18 14:32:53 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (display->force_precision != -1)
|
|
|
|
|
pa.poly_mode = display->force_precision;
|
|
|
|
|
else
|
|
|
|
|
pa.poly_mode = PolyModeImprecise;
|
|
|
|
|
if (pa.poly_mode)
|
|
|
|
|
mask |= CPPolyMode;
|
|
|
|
|
|
|
|
|
|
surface->precision = pa.poly_mode;
|
|
|
|
|
surface->picture = XRenderCreatePicture (display->display,
|
|
|
|
|
surface->drawable,
|
|
|
|
|
surface->xrender_format,
|
|
|
|
|
mask, &pa);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cairo_status_t
|
|
|
|
|
_cairo_xlib_surface_draw_image (cairo_xlib_surface_t *surface,
|
|
|
|
|
cairo_image_surface_t *image,
|
|
|
|
|
int src_x,
|
|
|
|
|
int src_y,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
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;
|
2011-03-08 12:05:48 +02:00
|
|
|
int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
|
2013-01-02 22:27:55 +00:00
|
|
|
cairo_surface_t *shm_image = NULL;
|
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;
|
2013-01-02 22:27:55 +00:00
|
|
|
cairo_bool_t own_data = FALSE;
|
2011-06-25 20:02:47 +01:00
|
|
|
cairo_bool_t is_rgb_image;
|
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;
|
2012-08-13 01:34:12 +01:00
|
|
|
ximage.obdata = NULL;
|
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;
|
|
|
|
|
|
2011-06-25 20:02:47 +01:00
|
|
|
is_rgb_image = _pixman_format_to_masks (image->pixman_format, &image_masks);
|
|
|
|
|
|
|
|
|
|
if (is_rgb_image &&
|
|
|
|
|
(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))
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
ximage.bits_per_pixel = image_masks.bpp;
|
|
|
|
|
ximage.bytes_per_line = image->stride;
|
|
|
|
|
ximage.data = (char *)image->data;
|
2013-01-02 22:27:55 +00:00
|
|
|
if (image->base.device != surface->base.device) {
|
|
|
|
|
/* If PutImage will break the image up into chunks, prefer to
|
|
|
|
|
* send it all in one pass with ShmPutImage. For larger images,
|
|
|
|
|
* it is further advantageous to reduce the number of copies,
|
|
|
|
|
* albeit at the expense of more SHM bookkeeping.
|
|
|
|
|
*/
|
|
|
|
|
int max_request_size = XExtendedMaxRequestSize (display->display);
|
|
|
|
|
if (max_request_size == 0)
|
|
|
|
|
max_request_size = XMaxRequestSize (display->display);
|
|
|
|
|
if (max_request_size > 8192)
|
|
|
|
|
max_request_size = 8192;
|
2013-01-23 15:04:26 +00:00
|
|
|
if (width * height * 4 > max_request_size) {
|
2013-01-02 22:27:55 +00:00
|
|
|
shm_image = _cairo_xlib_surface_create_shm__image (surface,
|
|
|
|
|
image->pixman_format,
|
2013-01-23 15:04:26 +00:00
|
|
|
width, height);
|
2013-01-02 22:27:55 +00:00
|
|
|
if (shm_image && shm_image->status == CAIRO_STATUS_SUCCESS) {
|
|
|
|
|
cairo_image_surface_t *clone = (cairo_image_surface_t *) shm_image;
|
2013-01-23 15:04:26 +00:00
|
|
|
pixman_image_composite32 (PIXMAN_OP_SRC,
|
|
|
|
|
image->pixman_image, NULL, clone->pixman_image,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
0, 0,
|
|
|
|
|
0, 0,
|
|
|
|
|
width, height);
|
2013-01-02 22:27:55 +00:00
|
|
|
ximage.obdata = _cairo_xlib_shm_surface_get_obdata (shm_image);
|
|
|
|
|
ximage.data = (char *)clone->data;
|
|
|
|
|
ximage.bytes_per_line = clone->stride;
|
2013-01-23 15:04:26 +00:00
|
|
|
ximage.width = width;
|
|
|
|
|
ximage.height = height;
|
|
|
|
|
src_x = src_y = 0;
|
2013-01-02 22:27:55 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else
|
2012-08-13 01:34:12 +01:00
|
|
|
ximage.obdata = _cairo_xlib_shm_surface_get_obdata (&image->base);
|
2011-06-25 20:02:47 +01:00
|
|
|
|
|
|
|
|
ret = XInitImage (&ximage);
|
|
|
|
|
assert (ret != 0);
|
|
|
|
|
}
|
2012-04-20 17:30:22 +01:00
|
|
|
else if (surface->visual == NULL || surface->visual->class == TrueColor)
|
2009-09-24 23:42:05 +02:00
|
|
|
{
|
|
|
|
|
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;
|
2012-01-17 12:37:48 +00:00
|
|
|
image_masks.bpp = bits_per_pixel (surface);
|
2009-09-24 23:42:05 +02:00
|
|
|
ret = _pixman_format_from_masks (&image_masks, &intermediate_format);
|
|
|
|
|
assert (ret);
|
|
|
|
|
|
2013-01-02 22:27:55 +00:00
|
|
|
shm_image = _cairo_xlib_surface_create_shm__image (surface,
|
|
|
|
|
intermediate_format,
|
|
|
|
|
width, height);
|
|
|
|
|
if (shm_image && shm_image->status == CAIRO_STATUS_SUCCESS) {
|
|
|
|
|
cairo_image_surface_t *clone = (cairo_image_surface_t *) shm_image;
|
|
|
|
|
|
|
|
|
|
pixman_image_composite32 (PIXMAN_OP_SRC,
|
|
|
|
|
image->pixman_image,
|
|
|
|
|
NULL,
|
|
|
|
|
clone->pixman_image,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
0, 0,
|
|
|
|
|
0, 0,
|
|
|
|
|
width, height);
|
|
|
|
|
|
|
|
|
|
ximage.data = (char *) clone->data;
|
|
|
|
|
ximage.obdata = _cairo_xlib_shm_surface_get_obdata (&clone->base);
|
|
|
|
|
ximage.bytes_per_line = clone->stride;
|
|
|
|
|
} else {
|
|
|
|
|
pixman_image = pixman_image_create_bits (intermediate_format,
|
|
|
|
|
width, height, NULL, 0);
|
|
|
|
|
if (pixman_image == NULL) {
|
|
|
|
|
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
|
|
|
|
goto BAIL;
|
|
|
|
|
}
|
2009-09-24 23:42:05 +02:00
|
|
|
|
2013-01-02 22:27:55 +00:00
|
|
|
pixman_image_composite32 (PIXMAN_OP_SRC,
|
|
|
|
|
image->pixman_image,
|
|
|
|
|
NULL,
|
|
|
|
|
pixman_image,
|
|
|
|
|
src_x, src_y,
|
|
|
|
|
0, 0,
|
|
|
|
|
0, 0,
|
|
|
|
|
width, height);
|
|
|
|
|
|
|
|
|
|
ximage.data = (char *) pixman_image_get_data (pixman_image);
|
|
|
|
|
ximage.bytes_per_line = pixman_image_get_stride (pixman_image);
|
|
|
|
|
}
|
2009-09-24 23:42:05 +02:00
|
|
|
|
2012-02-22 15:49:34 +00:00
|
|
|
ximage.width = width;
|
|
|
|
|
ximage.height = height;
|
2009-09-24 23:42:05 +02:00
|
|
|
ximage.bits_per_pixel = image_masks.bpp;
|
|
|
|
|
|
|
|
|
|
ret = XInitImage (&ximage);
|
|
|
|
|
assert (ret != 0);
|
2012-02-22 15:04:45 +00:00
|
|
|
|
|
|
|
|
src_x = src_y = 0;
|
2009-09-24 23:42:05 +02: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
|
|
|
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
|
|
|
|
2012-01-17 12:37:48 +00:00
|
|
|
ximage.bits_per_pixel = bits_per_pixel(surface);
|
2008-03-19 14:23:35 -07:00
|
|
|
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)) {
|
|
|
|
|
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
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
if (ximage.obdata)
|
|
|
|
|
XShmPutImage (display->display, surface->drawable, gc, &ximage,
|
2013-01-29 03:00:46 +00:00
|
|
|
src_x, src_y, dst_x, dst_y, width, height, True);
|
2012-08-13 01:34:12 +01:00
|
|
|
else
|
|
|
|
|
XPutImage (display->display, surface->drawable, gc, &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);
|
2013-01-02 22:27:55 +00:00
|
|
|
if (shm_image)
|
|
|
|
|
cairo_surface_destroy (shm_image);
|
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
|
|
|
}
|
|
|
|
|
|
2012-02-09 13:01:17 +00:00
|
|
|
static cairo_surface_t *
|
|
|
|
|
_cairo_xlib_surface_source(void *abstract_surface,
|
|
|
|
|
cairo_rectangle_int_t *extents)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
|
2012-04-27 22:13:01 +01:00
|
|
|
if (extents) {
|
|
|
|
|
extents->x = extents->y = 0;
|
|
|
|
|
extents->width = surface->width;
|
|
|
|
|
extents->height = surface->height;
|
|
|
|
|
}
|
2012-02-09 13:01:17 +00:00
|
|
|
|
|
|
|
|
return &surface->base;
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
2011-07-22 00:36:03 +01:00
|
|
|
cairo_rectangle_int_t extents;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
*image_extra = NULL;
|
|
|
|
|
*image_out = (cairo_image_surface_t *)
|
2012-08-17 20:57:04 +01:00
|
|
|
_cairo_xlib_surface_get_shm (abstract_surface, FALSE);
|
2012-08-13 01:34:12 +01:00
|
|
|
if (*image_out)
|
|
|
|
|
return (*image_out)->base.status;
|
|
|
|
|
|
2011-07-22 00:36:03 +01:00
|
|
|
extents.x = extents.y = 0;
|
|
|
|
|
extents.width = surface->width;
|
2011-07-27 18:30:37 +02:00
|
|
|
extents.height = surface->height;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
*image_out = (cairo_image_surface_t*)
|
|
|
|
|
_get_image_surface (surface, &extents, TRUE);
|
2011-07-22 00:36:03 +01:00
|
|
|
return (*image_out)->base.status;
|
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;
|
2011-07-22 00:36:03 +01:00
|
|
|
cairo_rectangle_int_t extents;
|
2008-11-25 20:15:15 +01:00
|
|
|
|
2011-07-22 00:36:03 +01:00
|
|
|
extents.x = extents.y = 0;
|
|
|
|
|
extents.width = surface->width;
|
2011-08-20 12:01:09 +01:00
|
|
|
extents.height = surface->height;
|
2008-11-25 20:15:15 +01:00
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
return _get_image_surface (surface, &extents, FALSE);
|
2008-11-25 20:15:15 +01:00
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2012-08-13 01:34:12 +01:00
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
|
|
|
|
|
if (&image->base == surface->shm)
|
|
|
|
|
return;
|
|
|
|
|
|
2005-01-31 08:50:22 +00:00
|
|
|
cairo_surface_destroy (&image->base);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-10 20:15:04 +02:00
|
|
|
static cairo_image_surface_t *
|
2011-07-22 00:36:03 +01:00
|
|
|
_cairo_xlib_surface_map_to_image (void *abstract_surface,
|
|
|
|
|
const cairo_rectangle_int_t *extents)
|
|
|
|
|
{
|
2012-08-13 01:34:12 +01:00
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
2011-07-22 00:36:03 +01:00
|
|
|
cairo_surface_t *image;
|
|
|
|
|
|
2012-08-17 20:57:04 +01:00
|
|
|
image = _cairo_xlib_surface_get_shm (abstract_surface, FALSE);
|
2012-08-13 01:34:12 +01:00
|
|
|
if (image) {
|
|
|
|
|
assert (surface->base.damage);
|
|
|
|
|
surface->fallback++;
|
|
|
|
|
return _cairo_image_surface_map_to_image (image, extents);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image = _get_image_surface (abstract_surface, extents, TRUE);
|
2012-02-22 15:13:26 +00:00
|
|
|
cairo_surface_set_device_offset (image, -extents->x, -extents->y);
|
2011-07-22 00:36:03 +01:00
|
|
|
|
2012-04-10 20:15:04 +02:00
|
|
|
return (cairo_image_surface_t *) image;
|
2011-07-22 00:36:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_int_status_t
|
|
|
|
|
_cairo_xlib_surface_unmap_image (void *abstract_surface,
|
|
|
|
|
cairo_image_surface_t *image)
|
|
|
|
|
{
|
2012-08-13 01:34:12 +01:00
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
2012-01-11 17:17:15 +01:00
|
|
|
cairo_int_status_t status;
|
|
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
if (surface->shm) {
|
|
|
|
|
cairo_rectangle_int_t r;
|
|
|
|
|
|
|
|
|
|
assert (surface->fallback);
|
|
|
|
|
assert (surface->base.damage);
|
|
|
|
|
|
|
|
|
|
r.x = image->base.device_transform_inverse.x0;
|
|
|
|
|
r.y = image->base.device_transform_inverse.y0;
|
|
|
|
|
r.width = image->width;
|
|
|
|
|
r.height = image->height;
|
|
|
|
|
|
|
|
|
|
TRACE ((stderr, "%s: adding damage (%d,%d)x(%d,%d)\n",
|
|
|
|
|
__FUNCTION__, r.x, r.y, r.width, r.height));
|
|
|
|
|
surface->shm->damage =
|
|
|
|
|
_cairo_damage_add_rectangle (surface->shm->damage, &r);
|
|
|
|
|
|
|
|
|
|
return _cairo_image_surface_unmap_image (surface->shm, image);
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-11 17:17:15 +01:00
|
|
|
status = _cairo_xlib_surface_draw_image (abstract_surface, image,
|
|
|
|
|
0, 0,
|
|
|
|
|
image->width, image->height,
|
|
|
|
|
image->base.device_transform_inverse.x0,
|
|
|
|
|
image->base.device_transform_inverse.y0);
|
|
|
|
|
|
|
|
|
|
cairo_surface_finish (&image->base);
|
|
|
|
|
cairo_surface_destroy (&image->base);
|
|
|
|
|
|
|
|
|
|
return status;
|
2011-07-22 00:36:03 +01:00
|
|
|
}
|
|
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_xlib_surface_flush (void *abstract_surface,
|
|
|
|
|
unsigned flags)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
cairo_int_status_t status;
|
|
|
|
|
|
|
|
|
|
if (flags)
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
status = _cairo_xlib_surface_put_shm (surface);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
surface->fallback >>= 1;
|
2012-09-13 22:50:11 +01:00
|
|
|
if (surface->shm && _cairo_xlib_shm_surface_is_idle (surface->shm))
|
|
|
|
|
_cairo_xlib_surface_discard_shm (surface);
|
2012-08-13 01:34:12 +01:00
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
static cairo_bool_t
|
|
|
|
|
_cairo_xlib_surface_get_extents (void *abstract_surface,
|
|
|
|
|
cairo_rectangle_int_t *rectangle)
|
2005-01-31 08:50:22 +00:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
|
|
|
|
|
rectangle->x = 0;
|
|
|
|
|
rectangle->y = 0;
|
|
|
|
|
|
|
|
|
|
rectangle->width = surface->width;
|
|
|
|
|
rectangle->height = surface->height;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
2005-01-31 08:50:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_xlib_surface_get_font_options (void *abstract_surface,
|
|
|
|
|
cairo_font_options_t *options)
|
2005-01-31 08:50:22 +00:00
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = abstract_surface;
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
*options = *_cairo_xlib_screen_get_font_options (surface->screen);
|
|
|
|
|
}
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
static inline cairo_int_status_t
|
|
|
|
|
get_compositor (cairo_xlib_surface_t **surface,
|
|
|
|
|
const cairo_compositor_t **compositor)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *s = *surface;
|
|
|
|
|
cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;;
|
|
|
|
|
|
|
|
|
|
if (s->fallback) {
|
|
|
|
|
assert (s->base.damage != NULL);
|
|
|
|
|
assert (s->shm != NULL);
|
|
|
|
|
assert (s->shm->damage != NULL);
|
|
|
|
|
if (! _cairo_xlib_shm_surface_is_active (s->shm)) {
|
|
|
|
|
*surface = (cairo_xlib_surface_t *) s->shm;
|
|
|
|
|
*compositor = ((cairo_image_surface_t *) s->shm)->compositor;
|
|
|
|
|
s->fallback++;
|
|
|
|
|
} else {
|
|
|
|
|
status = _cairo_xlib_surface_put_shm (s);
|
|
|
|
|
s->fallback = 0;
|
|
|
|
|
*compositor = s->compositor;
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
*compositor = s->compositor;
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
2011-07-30 17:28:21 +01:00
|
|
|
|
|
|
|
|
static cairo_int_status_t
|
|
|
|
|
_cairo_xlib_surface_paint (void *_surface,
|
|
|
|
|
cairo_operator_t op,
|
|
|
|
|
const cairo_pattern_t *source,
|
|
|
|
|
const cairo_clip_t *clip)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = _surface;
|
2012-08-13 01:34:12 +01:00
|
|
|
const cairo_compositor_t *compositor;
|
|
|
|
|
cairo_int_status_t status;
|
|
|
|
|
|
|
|
|
|
status = get_compositor (&surface, &compositor);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
return _cairo_compositor_paint (compositor, &surface->base,
|
|
|
|
|
op, source,
|
2011-07-30 17:28:21 +01:00
|
|
|
clip);
|
2005-01-31 08:50:22 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
static cairo_int_status_t
|
|
|
|
|
_cairo_xlib_surface_mask (void *_surface,
|
|
|
|
|
cairo_operator_t op,
|
|
|
|
|
const cairo_pattern_t *source,
|
|
|
|
|
const cairo_pattern_t *mask,
|
|
|
|
|
const cairo_clip_t *clip)
|
2005-07-20 18:52:31 +00:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_surface_t *surface = _surface;
|
2012-08-13 01:34:12 +01:00
|
|
|
const cairo_compositor_t *compositor;
|
|
|
|
|
cairo_int_status_t status;
|
|
|
|
|
|
|
|
|
|
status = get_compositor (&surface, &compositor);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
return _cairo_compositor_mask (compositor, &surface->base,
|
|
|
|
|
op, source, mask,
|
2011-07-30 17:28:21 +01:00
|
|
|
clip);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_int_status_t
|
|
|
|
|
_cairo_xlib_surface_stroke (void *_surface,
|
|
|
|
|
cairo_operator_t op,
|
|
|
|
|
const cairo_pattern_t *source,
|
|
|
|
|
const cairo_path_fixed_t *path,
|
|
|
|
|
const cairo_stroke_style_t *style,
|
|
|
|
|
const cairo_matrix_t *ctm,
|
|
|
|
|
const cairo_matrix_t *ctm_inverse,
|
|
|
|
|
double tolerance,
|
|
|
|
|
cairo_antialias_t antialias,
|
|
|
|
|
const cairo_clip_t *clip)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = _surface;
|
2012-08-13 01:34:12 +01:00
|
|
|
const cairo_compositor_t *compositor;
|
|
|
|
|
cairo_int_status_t status;
|
|
|
|
|
|
|
|
|
|
status = get_compositor (&surface, &compositor);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
return _cairo_compositor_stroke (compositor, &surface->base,
|
|
|
|
|
op, source,
|
2011-07-30 17:28:21 +01:00
|
|
|
path, style, ctm, ctm_inverse,
|
|
|
|
|
tolerance, antialias,
|
|
|
|
|
clip);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_int_status_t
|
|
|
|
|
_cairo_xlib_surface_fill (void *_surface,
|
|
|
|
|
cairo_operator_t op,
|
|
|
|
|
const cairo_pattern_t *source,
|
|
|
|
|
const cairo_path_fixed_t *path,
|
|
|
|
|
cairo_fill_rule_t fill_rule,
|
|
|
|
|
double tolerance,
|
|
|
|
|
cairo_antialias_t antialias,
|
|
|
|
|
const cairo_clip_t *clip)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = _surface;
|
2012-08-13 01:34:12 +01:00
|
|
|
const cairo_compositor_t *compositor;
|
|
|
|
|
cairo_int_status_t status;
|
|
|
|
|
|
|
|
|
|
status = get_compositor (&surface, &compositor);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
return _cairo_compositor_fill (compositor, &surface->base,
|
|
|
|
|
op, source,
|
2011-07-30 17:28:21 +01:00
|
|
|
path, fill_rule, tolerance, antialias,
|
|
|
|
|
clip);
|
2005-07-20 18:52:31 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
static cairo_int_status_t
|
|
|
|
|
_cairo_xlib_surface_glyphs (void *_surface,
|
|
|
|
|
cairo_operator_t op,
|
|
|
|
|
const cairo_pattern_t *source,
|
|
|
|
|
cairo_glyph_t *glyphs,
|
|
|
|
|
int num_glyphs,
|
|
|
|
|
cairo_scaled_font_t *scaled_font,
|
|
|
|
|
const cairo_clip_t *clip)
|
2011-06-25 20:02:47 +01:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_surface_t *surface = _surface;
|
2012-08-13 01:34:12 +01:00
|
|
|
const cairo_compositor_t *compositor;
|
|
|
|
|
cairo_int_status_t status;
|
|
|
|
|
|
|
|
|
|
status = get_compositor (&surface, &compositor);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return status;
|
|
|
|
|
|
|
|
|
|
return _cairo_compositor_glyphs (compositor, &surface->base,
|
|
|
|
|
op, source,
|
2011-07-30 17:28:21 +01:00
|
|
|
glyphs, num_glyphs, scaled_font,
|
|
|
|
|
clip);
|
|
|
|
|
}
|
2011-06-25 20:02:47 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
static const cairo_surface_backend_t cairo_xlib_surface_backend = {
|
|
|
|
|
CAIRO_SURFACE_TYPE_XLIB,
|
|
|
|
|
_cairo_xlib_surface_finish,
|
2011-06-25 20:02:47 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_default_context_create,
|
2011-06-25 20:02:47 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_xlib_surface_create_similar,
|
2012-08-13 01:34:12 +01:00
|
|
|
_cairo_xlib_surface_create_similar_shm,
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_xlib_surface_map_to_image,
|
|
|
|
|
_cairo_xlib_surface_unmap_image,
|
2011-06-25 20:02:47 +01:00
|
|
|
|
2012-02-09 13:01:17 +00:00
|
|
|
_cairo_xlib_surface_source,
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_xlib_surface_acquire_source_image,
|
|
|
|
|
_cairo_xlib_surface_release_source_image,
|
|
|
|
|
_cairo_xlib_surface_snapshot,
|
2011-06-25 20:02:47 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
NULL, /* copy_page */
|
|
|
|
|
NULL, /* show_page */
|
2011-06-25 20:02:47 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_xlib_surface_get_extents,
|
|
|
|
|
_cairo_xlib_surface_get_font_options,
|
2011-06-25 20:02:47 +01:00
|
|
|
|
2012-08-13 01:34:12 +01:00
|
|
|
_cairo_xlib_surface_flush,
|
2011-07-30 17:28:21 +01:00
|
|
|
NULL, /* mark_dirty_rectangle */
|
2011-06-25 20:02:47 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_xlib_surface_paint,
|
|
|
|
|
_cairo_xlib_surface_mask,
|
|
|
|
|
_cairo_xlib_surface_stroke,
|
|
|
|
|
_cairo_xlib_surface_fill,
|
|
|
|
|
NULL, /* fill-stroke */
|
|
|
|
|
_cairo_xlib_surface_glyphs,
|
|
|
|
|
};
|
2011-06-25 20:02:47 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
/**
|
|
|
|
|
* _cairo_surface_is_xlib:
|
|
|
|
|
* @surface: a #cairo_surface_t
|
|
|
|
|
*
|
|
|
|
|
* Checks if a surface is a #cairo_xlib_surface_t
|
|
|
|
|
*
|
|
|
|
|
* 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;
|
2011-06-25 20:02:47 +01:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
static cairo_surface_t *
|
|
|
|
|
_cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
|
|
|
|
|
Drawable drawable,
|
|
|
|
|
Visual *visual,
|
|
|
|
|
XRenderPictFormat *xrender_format,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
int depth)
|
2005-01-31 08:50:22 +00:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_surface_t *surface;
|
|
|
|
|
cairo_xlib_display_t *display;
|
2007-04-08 23:09:31 +01:00
|
|
|
cairo_status_t status;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (depth == 0) {
|
|
|
|
|
if (xrender_format) {
|
|
|
|
|
depth = xrender_format->depth;
|
|
|
|
|
|
|
|
|
|
/* XXX find matching visual for core/dithering fallbacks? */
|
|
|
|
|
} else if (visual) {
|
|
|
|
|
Screen *scr = screen->screen;
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (visual == DefaultVisualOfScreen (scr)) {
|
|
|
|
|
depth = DefaultDepthOfScreen (scr);
|
|
|
|
|
} else {
|
|
|
|
|
int j, k;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-04-08 23:09:31 +01:00
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (depth == 0)
|
|
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
|
2005-01-31 08:50:22 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
found:
|
|
|
|
|
;
|
2005-01-31 08:50:22 +00:00
|
|
|
}
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2024-06-21 10:03:52 +09:30
|
|
|
surface = _cairo_calloc (sizeof (cairo_xlib_surface_t));
|
2011-07-30 17:28:21 +01:00
|
|
|
if (unlikely (surface == NULL))
|
|
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
2008-06-13 21:37:45 -04:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
status = _cairo_xlib_display_acquire (screen->device, &display);
|
|
|
|
|
if (unlikely (status)) {
|
|
|
|
|
free (surface);
|
|
|
|
|
return _cairo_surface_create_in_error (_cairo_error (status));
|
|
|
|
|
}
|
2008-06-13 21:37:45 -04:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
surface->display = display;
|
|
|
|
|
if (CAIRO_RENDER_HAS_CREATE_PICTURE (display)) {
|
|
|
|
|
if (!xrender_format) {
|
|
|
|
|
if (visual) {
|
|
|
|
|
xrender_format = XRenderFindVisualFormat (display->display, visual);
|
|
|
|
|
} else if (depth == 1) {
|
|
|
|
|
xrender_format =
|
|
|
|
|
_cairo_xlib_display_get_xrender_format (display,
|
|
|
|
|
CAIRO_FORMAT_A1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-04-18 23:20:02 +02:00
|
|
|
|
|
|
|
|
cairo_device_release (&display->base);
|
2008-06-13 21:37:45 -04:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_surface_init (&surface->base,
|
|
|
|
|
&cairo_xlib_surface_backend,
|
|
|
|
|
screen->device,
|
2015-09-21 21:35:05 +09:30
|
|
|
_xrender_format_to_content (xrender_format),
|
|
|
|
|
FALSE); /* is_vector */
|
2008-06-13 21:37:45 -04:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
surface->screen = screen;
|
|
|
|
|
surface->compositor = display->compositor;
|
2012-08-13 01:34:12 +01:00
|
|
|
surface->shm = NULL;
|
|
|
|
|
surface->fallback = 0;
|
2008-10-16 12:33:22 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
surface->drawable = drawable;
|
|
|
|
|
surface->owns_pixmap = FALSE;
|
|
|
|
|
surface->use_pixmap = 0;
|
|
|
|
|
surface->width = width;
|
|
|
|
|
surface->height = height;
|
2008-06-13 21:37:45 -04:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
surface->picture = None;
|
|
|
|
|
surface->precision = PolyModePrecise;
|
2008-06-13 21:37:45 -04:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
surface->embedded_source.picture = None;
|
2008-12-17 20:34:45 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
surface->visual = visual;
|
|
|
|
|
surface->xrender_format = xrender_format;
|
|
|
|
|
surface->depth = depth;
|
2003-10-31 10:41:37 +00:00
|
|
|
|
2011-07-30 17:28:21 +01: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.
|
2008-09-17 15:14:16 -04:00
|
|
|
*/
|
2011-07-30 17:28:21 +01:00
|
|
|
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;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_list_add (&surface->link, &screen->surfaces);
|
2003-09-30 18:56:22 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return &surface->base;
|
2003-09-30 18:56:22 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
static Screen *
|
|
|
|
|
_cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
|
2003-09-30 18:56:22 +00:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
int s, d, v;
|
2005-03-03 17:40:04 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
for (s = 0; s < ScreenCount (dpy); s++) {
|
|
|
|
|
Screen *screen;
|
2006-06-06 15:25:49 -07:00
|
|
|
|
2011-07-30 17:28:21 +01: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
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
for (d = 0; d < screen->ndepths; d++) {
|
|
|
|
|
Depth *depth;
|
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
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
depth = &screen->depths[d];
|
|
|
|
|
for (v = 0; v < depth->nvisuals; v++)
|
|
|
|
|
if (visual == &depth->visuals[v])
|
|
|
|
|
return screen;
|
|
|
|
|
}
|
2005-03-03 17:40:04 +00:00
|
|
|
}
|
2009-09-11 14:59:58 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return NULL;
|
2009-10-16 16:48:54 +01:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
static cairo_bool_t valid_size (int width, int height)
|
2009-10-16 16:48:54 +01:00
|
|
|
{
|
2012-04-25 20:41:16 +01:00
|
|
|
/* Note: the minimum surface size allowed in the X protocol is 1x1.
|
|
|
|
|
* However, as we historically did not check the minimum size we
|
|
|
|
|
* allowed applications to lie and set the correct size later (one hopes).
|
2017-11-09 09:43:02 -05:00
|
|
|
* To preserve compatibility we must allow applications to use
|
2012-04-25 20:41:16 +01:00
|
|
|
* 0x0 surfaces.
|
|
|
|
|
*/
|
|
|
|
|
return (width >= 0 && width <= XLIB_COORD_MAX &&
|
|
|
|
|
height >= 0 && height <= XLIB_COORD_MAX);
|
2009-09-11 14:59:58 +01:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_create:
|
|
|
|
|
* @dpy: an X Display
|
|
|
|
|
* @drawable: an X Drawable, (a Pixmap or a Window)
|
|
|
|
|
* @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.
|
|
|
|
|
*
|
|
|
|
|
* Creates an Xlib surface that draws to the given drawable.
|
|
|
|
|
* The way that colors are represented in the drawable is specified
|
|
|
|
|
* by the provided visual.
|
|
|
|
|
*
|
|
|
|
|
* Note: If @drawable is a Window, then the function
|
|
|
|
|
* cairo_xlib_surface_set_size() must be called whenever the size of the
|
|
|
|
|
* window changes.
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the newly created surface
|
doc: Add "since" tag to documentation
The following Python script was used to compute "Since: 1.X" tags,
based on the first version where a symbol became officially supported.
This script requires a concatenation of the the cairo public headers
for the officially supported beckends to be available as
"../../includes/1.X.0.h".
from sys import argv
import re
syms = {}
def stripcomments(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return ""
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
for minor in range(12,-2,-2):
version = "1.%d" % minor
names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read()))
for s in names: syms[s] = version
for filename in argv[1:]:
is_public = False
lines = open(filename, "r").read().split("\n")
newlines = []
for i in range(len(lines)):
if lines[i] == "/**":
last_sym = lines[i+1][2:].strip().replace(":", "")
is_public = last_sym.lower().startswith("cairo")
elif is_public and lines[i] == " **/":
if last_sym in syms:
v = syms[last_sym]
if re.search("Since", newlines[-1]): newlines = newlines[:-1]
if newlines[-1].strip() != "*": newlines.append(" *")
newlines.append(" * Since: %s" % v)
else:
print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym)
newlines.append(lines[i])
out = open(filename, "w")
out.write("\n".join(newlines))
out.close()
2012-03-27 11:48:19 +02:00
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
2011-07-30 17:28:21 +01:00
|
|
|
**/
|
|
|
|
|
cairo_surface_t *
|
|
|
|
|
cairo_xlib_surface_create (Display *dpy,
|
|
|
|
|
Drawable drawable,
|
|
|
|
|
Visual *visual,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
2009-09-11 14:59:58 +01:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
Screen *scr;
|
|
|
|
|
cairo_xlib_screen_t *screen;
|
|
|
|
|
cairo_status_t status;
|
2009-09-11 14:59:58 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! valid_size (width, height)) {
|
|
|
|
|
/* you're lying, and you know it! */
|
|
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
|
|
|
|
}
|
2009-10-16 16:48:54 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
scr = _cairo_xlib_screen_from_visual (dpy, visual);
|
|
|
|
|
if (scr == NULL)
|
|
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
|
2005-03-03 17:40:04 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
status = _cairo_xlib_screen_get (dpy, scr, &screen);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status))
|
2011-07-30 17:28:21 +01:00
|
|
|
return _cairo_surface_create_in_error (status);
|
2005-03-03 17:40:04 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
X_DEBUG ((dpy, "create (drawable=%x)", (unsigned int) drawable));
|
2009-10-16 16:48:54 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return _cairo_xlib_surface_create_internal (screen, drawable,
|
|
|
|
|
visual, NULL,
|
|
|
|
|
width, height, 0);
|
2005-03-03 17:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_create_for_bitmap:
|
|
|
|
|
* @dpy: an X Display
|
|
|
|
|
* @bitmap: an X Drawable, (a depth-1 Pixmap)
|
|
|
|
|
* @screen: the X Screen associated with @bitmap
|
|
|
|
|
* @width: the current width of @bitmap.
|
|
|
|
|
* @height: the current height of @bitmap.
|
|
|
|
|
*
|
|
|
|
|
* Creates an Xlib surface that draws to the given bitmap.
|
|
|
|
|
* This will be drawn to as a %CAIRO_FORMAT_A1 object.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the newly created surface
|
doc: Add "since" tag to documentation
The following Python script was used to compute "Since: 1.X" tags,
based on the first version where a symbol became officially supported.
This script requires a concatenation of the the cairo public headers
for the officially supported beckends to be available as
"../../includes/1.X.0.h".
from sys import argv
import re
syms = {}
def stripcomments(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return ""
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
for minor in range(12,-2,-2):
version = "1.%d" % minor
names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read()))
for s in names: syms[s] = version
for filename in argv[1:]:
is_public = False
lines = open(filename, "r").read().split("\n")
newlines = []
for i in range(len(lines)):
if lines[i] == "/**":
last_sym = lines[i+1][2:].strip().replace(":", "")
is_public = last_sym.lower().startswith("cairo")
elif is_public and lines[i] == " **/":
if last_sym in syms:
v = syms[last_sym]
if re.search("Since", newlines[-1]): newlines = newlines[:-1]
if newlines[-1].strip() != "*": newlines.append(" *")
newlines.append(" * Since: %s" % v)
else:
print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym)
newlines.append(lines[i])
out = open(filename, "w")
out.write("\n".join(newlines))
out.close()
2012-03-27 11:48:19 +02:00
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
2011-07-30 17:28:21 +01:00
|
|
|
**/
|
|
|
|
|
cairo_surface_t *
|
|
|
|
|
cairo_xlib_surface_create_for_bitmap (Display *dpy,
|
|
|
|
|
Pixmap bitmap,
|
|
|
|
|
Screen *scr,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
2005-06-20 15:48:46 +00:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_screen_t *screen;
|
|
|
|
|
cairo_status_t status;
|
2005-07-20 18:52:31 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! valid_size (width, height))
|
|
|
|
|
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
2005-06-20 15:48:46 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
status = _cairo_xlib_screen_get (dpy, scr, &screen);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return _cairo_surface_create_in_error (status);
|
2005-06-20 15:48:46 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
X_DEBUG ((dpy, "create_for_bitmap (drawable=%x)", (unsigned int) bitmap));
|
2005-07-15 13:45:19 +00:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return _cairo_xlib_surface_create_internal (screen, bitmap,
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
width, height, 1);
|
2005-07-15 13:45:19 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
|
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_create_with_xrender_format:
|
|
|
|
|
* @dpy: an X Display
|
|
|
|
|
* @drawable: an X Drawable, (a Pixmap or a Window)
|
|
|
|
|
* @screen: the X Screen associated with @drawable
|
|
|
|
|
* @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-07-15 13:45:19 +00:00
|
|
|
*
|
2011-07-30 17:28:21 +01:00
|
|
|
* Creates an Xlib surface that draws to the given drawable.
|
|
|
|
|
* The way that colors are represented in the drawable is specified
|
|
|
|
|
* by the provided picture format.
|
2005-06-20 15:48:46 +00:00
|
|
|
*
|
2011-07-30 17:28:21 +01:00
|
|
|
* Note: If @drawable is a Window, then the function
|
|
|
|
|
* cairo_xlib_surface_set_size() must be called whenever the size of the
|
|
|
|
|
* window changes.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the newly created surface
|
doc: Add "since" tag to documentation
The following Python script was used to compute "Since: 1.X" tags,
based on the first version where a symbol became officially supported.
This script requires a concatenation of the the cairo public headers
for the officially supported beckends to be available as
"../../includes/1.X.0.h".
from sys import argv
import re
syms = {}
def stripcomments(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return ""
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
for minor in range(12,-2,-2):
version = "1.%d" % minor
names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read()))
for s in names: syms[s] = version
for filename in argv[1:]:
is_public = False
lines = open(filename, "r").read().split("\n")
newlines = []
for i in range(len(lines)):
if lines[i] == "/**":
last_sym = lines[i+1][2:].strip().replace(":", "")
is_public = last_sym.lower().startswith("cairo")
elif is_public and lines[i] == " **/":
if last_sym in syms:
v = syms[last_sym]
if re.search("Since", newlines[-1]): newlines = newlines[:-1]
if newlines[-1].strip() != "*": newlines.append(" *")
newlines.append(" * Since: %s" % v)
else:
print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym)
newlines.append(lines[i])
out = open(filename, "w")
out.write("\n".join(newlines))
out.close()
2012-03-27 11:48:19 +02:00
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
2011-07-30 17:28:21 +01:00
|
|
|
**/
|
|
|
|
|
cairo_surface_t *
|
|
|
|
|
cairo_xlib_surface_create_with_xrender_format (Display *dpy,
|
|
|
|
|
Drawable drawable,
|
|
|
|
|
Screen *scr,
|
|
|
|
|
XRenderPictFormat *format,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
2005-06-20 15:48:46 +00:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_screen_t *screen;
|
|
|
|
|
cairo_status_t status;
|
2007-08-30 10:16:00 +02:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! valid_size (width, height))
|
|
|
|
|
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);
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
X_DEBUG ((dpy, "create_with_xrender_format (drawable=%x)", (unsigned int) drawable));
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return _cairo_xlib_surface_create_internal (screen, drawable,
|
|
|
|
|
_visual_for_xrender_format (scr, format),
|
|
|
|
|
format, width, height, 0);
|
2006-05-04 03:59:56 -07:00
|
|
|
}
|
|
|
|
|
|
2006-06-30 00:46:48 +02:00
|
|
|
/**
|
2011-07-30 17:28:21 +01:00
|
|
|
* cairo_xlib_surface_get_xrender_format:
|
|
|
|
|
* @surface: an xlib surface
|
2006-06-30 00:46:48 +02:00
|
|
|
*
|
2011-07-30 17:28:21 +01: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.
|
2006-06-30 00:46:48 +02:00
|
|
|
*
|
2011-07-30 17:28:21 +01:00
|
|
|
* Return value: the XRenderPictFormat* associated with @surface,
|
|
|
|
|
* or %NULL if the surface is not an xlib surface
|
|
|
|
|
* or if the X Render extension is not available.
|
2006-06-30 00:46:48 +02:00
|
|
|
*
|
2011-07-30 17:28:21 +01:00
|
|
|
* Since: 1.6
|
2006-06-30 00:46:48 +02:00
|
|
|
**/
|
2011-07-30 17:28:21 +01:00
|
|
|
XRenderPictFormat *
|
|
|
|
|
cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
|
2006-05-04 03:59:56 -07:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
/* Throw an error for a non-xlib surface */
|
|
|
|
|
if (! _cairo_surface_is_xlib (surface)) {
|
2007-10-04 13:15:46 +01:00
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
2011-07-30 17:28:21 +01:00
|
|
|
return NULL;
|
2006-05-04 04:01:06 -07:00
|
|
|
}
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return xlib_surface->xrender_format;
|
2006-05-04 03:59:56 -07:00
|
|
|
}
|
2011-07-30 17:28:21 +01:00
|
|
|
#endif
|
2006-05-04 03:59:56 -07:00
|
|
|
|
2006-06-30 00:46:48 +02:00
|
|
|
/**
|
2011-07-30 17:28:21 +01: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-30 00:46:48 +02:00
|
|
|
*
|
2011-07-30 17:28:21 +01: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.)
|
2006-06-30 00:46:48 +02:00
|
|
|
*
|
2011-07-30 17:28:21 +01:00
|
|
|
* A Pixmap can never change size, so it is never necessary to call
|
|
|
|
|
* this function on a surface created for a Pixmap.
|
doc: Add "since" tag to documentation
The following Python script was used to compute "Since: 1.X" tags,
based on the first version where a symbol became officially supported.
This script requires a concatenation of the the cairo public headers
for the officially supported beckends to be available as
"../../includes/1.X.0.h".
from sys import argv
import re
syms = {}
def stripcomments(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return ""
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
for minor in range(12,-2,-2):
version = "1.%d" % minor
names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read()))
for s in names: syms[s] = version
for filename in argv[1:]:
is_public = False
lines = open(filename, "r").read().split("\n")
newlines = []
for i in range(len(lines)):
if lines[i] == "/**":
last_sym = lines[i+1][2:].strip().replace(":", "")
is_public = last_sym.lower().startswith("cairo")
elif is_public and lines[i] == " **/":
if last_sym in syms:
v = syms[last_sym]
if re.search("Since", newlines[-1]): newlines = newlines[:-1]
if newlines[-1].strip() != "*": newlines.append(" *")
newlines.append(" * Since: %s" % v)
else:
print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym)
newlines.append(lines[i])
out = open(filename, "w")
out.write("\n".join(newlines))
out.close()
2012-03-27 11:48:19 +02:00
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
2006-06-30 00:46:48 +02:00
|
|
|
**/
|
2011-07-30 17:28:21 +01:00
|
|
|
void
|
|
|
|
|
cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
2006-06-21 15:47:03 +12:00
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2012-08-13 01:34:12 +01:00
|
|
|
cairo_status_t status;
|
2006-06-21 15:47:03 +12:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (unlikely (abstract_surface->status))
|
|
|
|
|
return;
|
|
|
|
|
if (unlikely (abstract_surface->finished)) {
|
|
|
|
|
_cairo_surface_set_error (abstract_surface,
|
|
|
|
|
_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
|
|
|
|
|
return;
|
2006-06-21 15:47:03 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
2011-07-30 17:28:21 +01:00
|
|
|
_cairo_surface_set_error (abstract_surface,
|
|
|
|
|
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
|
2008-05-06 14:52:02 +01:00
|
|
|
return;
|
2005-07-21 14:31:28 +00:00
|
|
|
}
|
2008-05-01 19:46:58 +01:00
|
|
|
|
2012-09-13 15:25:49 +01:00
|
|
|
if (surface->width == width && surface->height == height)
|
|
|
|
|
return;
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! valid_size (width, height)) {
|
|
|
|
|
_cairo_surface_set_error (abstract_surface,
|
|
|
|
|
_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2007-10-19 15:02:03 -04:00
|
|
|
|
2012-09-13 17:00:24 +01:00
|
|
|
status = _cairo_surface_flush (abstract_surface, 0);
|
2012-08-13 01:34:12 +01:00
|
|
|
if (unlikely (status)) {
|
|
|
|
|
_cairo_surface_set_error (abstract_surface, status);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-13 15:25:49 +01:00
|
|
|
_cairo_xlib_surface_discard_shm (surface);
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
surface->width = width;
|
|
|
|
|
surface->height = 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
|
|
|
}
|
2012-09-13 15:25:49 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_set_drawable:
|
|
|
|
|
* @surface: a #cairo_surface_t for the XLib backend
|
|
|
|
|
* @drawable: the new drawable for the surface
|
|
|
|
|
* @width: the width of the new drawable
|
|
|
|
|
* @height: the height of the new drawable
|
2008-09-30 23:19:01 +01:00
|
|
|
*
|
2011-07-30 17:28:21 +01: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.
|
doc: Add "since" tag to documentation
The following Python script was used to compute "Since: 1.X" tags,
based on the first version where a symbol became officially supported.
This script requires a concatenation of the the cairo public headers
for the officially supported beckends to be available as
"../../includes/1.X.0.h".
from sys import argv
import re
syms = {}
def stripcomments(text):
def replacer(match):
s = match.group(0)
if s.startswith('/'):
return ""
else:
return s
pattern = re.compile(
r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
re.DOTALL | re.MULTILINE
)
return re.sub(pattern, replacer, text)
for minor in range(12,-2,-2):
version = "1.%d" % minor
names = re.split('([A-Za-z0-9_]+)', stripcomments(open("../../includes/%s.0.h" % version).read()))
for s in names: syms[s] = version
for filename in argv[1:]:
is_public = False
lines = open(filename, "r").read().split("\n")
newlines = []
for i in range(len(lines)):
if lines[i] == "/**":
last_sym = lines[i+1][2:].strip().replace(":", "")
is_public = last_sym.lower().startswith("cairo")
elif is_public and lines[i] == " **/":
if last_sym in syms:
v = syms[last_sym]
if re.search("Since", newlines[-1]): newlines = newlines[:-1]
if newlines[-1].strip() != "*": newlines.append(" *")
newlines.append(" * Since: %s" % v)
else:
print "%s (%d): Cannot determine the version in which '%s' was introduced" % (filename, i, last_sym)
newlines.append(lines[i])
out = open(filename, "w")
out.write("\n".join(newlines))
out.close()
2012-03-27 11:48:19 +02:00
|
|
|
*
|
|
|
|
|
* Since: 1.0
|
2011-07-30 17:28:21 +01:00
|
|
|
**/
|
|
|
|
|
void
|
|
|
|
|
cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
|
|
|
|
|
Drawable drawable,
|
|
|
|
|
int width,
|
|
|
|
|
int 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
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
|
|
|
|
|
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
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (unlikely (abstract_surface->status))
|
|
|
|
|
return;
|
|
|
|
|
if (unlikely (abstract_surface->finished)) {
|
|
|
|
|
status = _cairo_surface_set_error (abstract_surface,
|
|
|
|
|
_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
|
|
|
|
|
return;
|
[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
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
|
|
|
|
status = _cairo_surface_set_error (abstract_surface,
|
|
|
|
|
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
|
|
|
|
|
return;
|
[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
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! valid_size (width, height)) {
|
|
|
|
|
status = _cairo_surface_set_error (abstract_surface,
|
|
|
|
|
_cairo_error (CAIRO_STATUS_INVALID_SIZE));
|
|
|
|
|
return;
|
2008-09-30 17:26:46 -04: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
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
/* XXX: and what about this case? */
|
|
|
|
|
if (surface->owns_pixmap)
|
|
|
|
|
return;
|
2008-09-30 17:46:06 -04:00
|
|
|
|
2012-09-13 17:00:24 +01:00
|
|
|
status = _cairo_surface_flush (abstract_surface, 0);
|
2012-08-13 01:34:12 +01:00
|
|
|
if (unlikely (status)) {
|
|
|
|
|
_cairo_surface_set_error (abstract_surface, status);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-13 12:40:49 +01:00
|
|
|
if (surface->drawable != drawable) {
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_display_t *display;
|
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
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
|
|
|
|
if (unlikely (status))
|
|
|
|
|
return;
|
2011-01-07 00:19:55 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
X_DEBUG ((display->display, "set_drawable (drawable=%x)", (unsigned int) drawable));
|
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
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (surface->picture != None) {
|
|
|
|
|
XRenderFreePicture (display->display, surface->picture);
|
2008-11-18 15:38:37 +00:00
|
|
|
if (unlikely (status)) {
|
2011-07-30 17:28:21 +01:00
|
|
|
status = _cairo_surface_set_error (&surface->base, status);
|
|
|
|
|
return;
|
2008-05-23 19:57:48 -04:00
|
|
|
}
|
2008-09-30 13:33:25 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
surface->picture = None;
|
[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
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_device_release (&display->base);
|
2008-09-30 17:26:46 -04:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
surface->drawable = drawable;
|
[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
|
|
|
}
|
2012-08-13 01:34:12 +01:00
|
|
|
|
2012-09-13 15:25:49 +01:00
|
|
|
if (surface->width != width || surface->height != height) {
|
|
|
|
|
_cairo_xlib_surface_discard_shm (surface);
|
|
|
|
|
|
|
|
|
|
surface->width = width;
|
|
|
|
|
surface->height = height;
|
|
|
|
|
}
|
2011-07-30 17:28:21 +01: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
|
|
|
|
2011-07-30 17:28:21 +01: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
|
|
|
|
|
**/
|
|
|
|
|
Display *
|
|
|
|
|
cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
|
|
|
|
|
{
|
|
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
|
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
|
|
|
|
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
|
|
|
}
|
2008-05-23 20:57:21 -04:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return ((cairo_xlib_display_t *) abstract_surface->device)->display;
|
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
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01: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
|
|
|
|
|
**/
|
|
|
|
|
Drawable
|
|
|
|
|
cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
|
2008-10-21 22:48:17 +01:00
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2008-10-21 22:48:17 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
|
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
|
|
|
|
return 0;
|
2008-10-21 22:48:17 +01:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return surface->drawable;
|
2008-10-21 22:48:17 +01:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01: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
|
|
|
|
|
**/
|
|
|
|
|
Screen *
|
|
|
|
|
cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
|
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
|
|
|
{
|
2011-07-30 17:28:21 +01:00
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2006-03-08 21:08:57 -08:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
|
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2006-03-08 21:08:57 -08:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return surface->screen->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
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
/**
|
|
|
|
|
* cairo_xlib_surface_get_visual:
|
|
|
|
|
* @surface: a #cairo_xlib_surface_t
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* Return value: the Visual or %NULL if there is no appropriate Visual for
|
|
|
|
|
* @surface.
|
|
|
|
|
*
|
|
|
|
|
* Since: 1.2
|
|
|
|
|
**/
|
|
|
|
|
Visual *
|
|
|
|
|
cairo_xlib_surface_get_visual (cairo_surface_t *surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
|
2010-04-18 23:20:02 +02:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! _cairo_surface_is_xlib (surface)) {
|
|
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2009-09-29 03:02:40 +01:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return xlib_surface->visual;
|
|
|
|
|
}
|
2005-08-31 15:08:02 +00:00
|
|
|
|
2011-07-30 17:28:21 +01: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
|
|
|
|
|
**/
|
|
|
|
|
int
|
|
|
|
|
cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2006-06-22 22:32:57 -07:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
|
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
|
|
|
|
return 0;
|
2006-03-08 21:08:57 -08:00
|
|
|
}
|
|
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return surface->depth;
|
|
|
|
|
}
|
2006-03-27 13:49:58 -08:00
|
|
|
|
2011-07-30 17:28:21 +01: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
|
|
|
|
|
**/
|
|
|
|
|
int
|
|
|
|
|
cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2006-03-27 13:49:58 -08:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
|
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
|
|
|
|
return 0;
|
2005-06-20 15:48:46 +00:00
|
|
|
}
|
2006-03-08 21:08:57 -08:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
return surface->width;
|
|
|
|
|
}
|
2005-08-31 15:08:02 +00:00
|
|
|
|
2011-07-30 17:28:21 +01: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
|
|
|
|
|
**/
|
|
|
|
|
int
|
|
|
|
|
cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
|
|
|
|
|
{
|
|
|
|
|
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
|
2006-06-22 22:38:17 -07:00
|
|
|
|
2011-07-30 17:28:21 +01:00
|
|
|
if (! _cairo_surface_is_xlib (abstract_surface)) {
|
|
|
|
|
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 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
|
|
|
}
|
2011-06-16 08:47:56 +02:00
|
|
|
|
|
|
|
|
#endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */
|