Merge branch 'master' of ssh+git://git.cairographics.org/git/cairo

This commit is contained in:
Michael Emmel 2007-01-23 22:22:20 -08:00
commit bb02b4e5ec
97 changed files with 2313 additions and 457 deletions

93
NEWS
View file

@ -1,3 +1,96 @@
Snapshot 1.3.12 (2007-01-20 Carl Worth <cworth@cworth.org>)
===========================================================
The relentless march toward the cairo 1.4 release continues, (even if
slightly late out of the starting blocks in 2007). This is the sixth
development snapshot in the 1.3 series. It comes 4 weeks after the
1.3.10 snapshot.
Performance
-----------
As usual, this snapshot has some fun performance improvements to show
off:
image-rgba long-lines-uncropped-100 470.08 -> 4.95: 94.91x speedup
███████████████████████████████████████████████
image-rgb long-lines-uncropped-100 461.60 -> 4.96: 93.02x speedup
██████████████████████████████████████████████
This 100x improvement, (and yes, that's 100x, not 100%), in the image
backend occurs when drawing large shapes where only a fraction of the
shape actually appears in the final result, (the rest being outside
the bounds of the destination surface). Many applications should see
speedups here, and the actual amount of speedup depends on the ratio
of non-visible to visible portions of geometry.
[Note: There remains a similar performance bug when drawing mostly
non-visible objects with the xlib backend. This is due to a similar
bug in the X server itself, but we hope a future cairo snapshot will
workaround that bug to get a similar speedup with the xlib backend.]
image-rgba unaligned_clip-100 0.09 -> 0.06: 1.67x speedup
image-rgb unaligned_clip-100 0.09 -> 0.06: 1.66x speedup
This speedup is due to further MMX optimization by Soeren Sandmann for
a case commonly hit when rendering PDF files, (and thanks to Jeff
Muizelaar for writing code to extract the test case for us).
There's another MMX optimization in this snapshot (without a fancy
speedup chart) by Dan Williams which improves compositing performance
specifically for the OLPC machine.
Thanks to Adrian Johnson, cairo's PDF output is now much more
efficient in the way it encodes text output. By reducing redundant
information and adding compression to text output streams, Adrian
achieved a ~25x improvement in the efficiency of encoding text in PDF
files, (was ~45 bytes per glyph and is now ~1.6 bytes per glyph).
Bug fixes
---------
In addition to those performance improvements, this snapshot includes
several bug fixes:
* A huge number of bug fixes for cairo-atsui text rendering, (for mac
OS X). These bugs affect font selection, glyph positioning, glyph
rendering, etc. One noteworthy bug fixes is that
cairo_select_font_face will no longer arbitrarily select bold nor
italic when not requested, (at least not when using a standard CSS2
font family name such as "serif", "sans-serif", "monospace", etc.).
All these fixes are thanks to Brian Ewins who continues to do a
great job as the new cairo-atsui maintainer.
* Fix PDF output so that images that are scaled down no longer
mysteriously repeat (Carl Worth).
* Fix segfault on Mac OS X dues to attempt to measure extents of a
zero-length string (Behdad Esfahbod).
* Fix text extents to not include the size of initial/trailing
non-inked characters (Behdad Esfahbod).
API tweaks
----------
Three functions have had API changes to improve consistency. Note that
the API functions being changed here are all functions that were
introduced as new functions during these 1.3.x snapshots. As always,
there will not be any API changes to functions included in a major
release (1.2.x, 1.4.x, etc.) of cairo.
The changes are as follows:
* Rename of cairo_copy_clip_rectangles to cairo_copy_clip_rectangle_list.
* Change cairo_get_dash_count to return an int rather than accepting a
pointer to an int for the return value.
* Change cairo_get_dash to have a void return type rather than
returning cairo_status_t.
It's possible there will be one more round of changes to these
functions, (and perhaps cairo_get_color_stop as well), as we seek to
establish a unifying convention for returning lists of values.
Snapshot 1.3.10 (2006-12-23 Carl Worth <cworth@cworth.org>)
===========================================================
Santa Claus is coming just a little bit early this year, and he's

24
ROADMAP
View file

@ -36,6 +36,13 @@ cairo-1.4 (January 2006): Better performance
- New rasterization
- Finer-grained fallbacks for PS/PDF
cairo 1.3.14
============
Bugs to fix:
"issue with rotated image sources" from Benjamin Otte on mailing list
"Problem with linear gradients and reflect mode post-rewrite" from T Rowley on list
8801 text rendering lacking locking in multithreaded apps
cairo 1.3.6
===========
✓ Bankers' rounding bug in _cairo_lround (https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=217819)
@ -65,23 +72,6 @@ cairo 1.4.0 ideas (think performance!)
✓ New tessellator
Look into using alloca instead of malloc when copying glyphs/path/etc to edit
and use in one function and deallocate upon return.
Look into generating EPS. That may be done using a new constructor for the
PS backend, or better, using an API similar to
cairo_svg_surface_restrict_to_version. The PDF backend needs a restrict_to
API at some point too.
Look into the glyph cache. Moreover, make sure we are reusing scaled fonts
enough.
User-font API---a couple of threads of interest:
http://lists.freedesktop.org/archives/cairo/2006-May/006893.html
http://lists.freedesktop.org/archives/cairo/2006-May/006888.html
Polling API (cairo_get_serial and cairo_changed)
Bugs to fix
-----------
CAIRO_EXTEND_PAD is not implemented for surface patterns

40
TODO
View file

@ -75,20 +75,36 @@ Other changes (this text used to be in RODMAP)
cairo_arc_to
see http://lists.freedesktop.org/archives/cairo/2005-August/004801.html
or see arc_to branch in bedhad's repository
User-font API---a couple of threads of interest:
http://lists.freedesktop.org/archives/cairo/2006-May/006893.html
http://lists.freedesktop.org/archives/cairo/2006-May/006888.html
Polling API (cairo_get_serial and cairo_changed)
PS/PDF improvements
1. Make image fallbacks finer-grained than a whole page
2. Ensure that PDF text output is "selectable"
2. Ensure that PDF text output is "selectable". see this thread:
http://lists.freedesktop.org/archives/cairo/2007-January/009059.html
3. Fix extend modes in PDF
4. Fix encoding "issues" reported here:
http://lists.freedesktop.org/archives/cairo/2006-December/008985.html
5. Use glyph advances to generate more compact PS/PDF
6. Look into generating EPS. That may be done using a new constructor
for the PS backend, or better, using an API similar to
cairo_svg_surface_restrict_to_version. The PDF backend needs a
restrict_to API at some point too.
Xlib backend
1. xlib backend requires xrender to compile, while it can perform without
xrender at run time. Make it compile without it. see
http://lists.freedesktop.org/archives/cairo/2006-October/008075.html
2. Cache patterns (maybe solid ones only). see
http://lists.freedesktop.org/archives/cairo/2006-December/008916.html
Quartz backend (maintainer needed!)
1. Mark Quartz backend as supported:
a. Incorporate into test suite
b. Correct output for the entire suite
Misc
1. xlib backend requires xrender to compile, while it can perform without
xrender at run time. Make it compile without it.
Some known bugs (this text used to be in BUGS)
==============================================
XXX: Many of these bugs are likely no longer valid. We should
@ -145,10 +161,22 @@ cairo_scale (cr, 0, 0);
Text drawn with vertical metrics cannot currently use TrueType
subsetting for PDF/PS output as the code doesn't write out the necessary
VHEA or VMTX entries to the TrueType font objects. As a result, cairo uses
Type3 fonts which generates slightly different outlines.
Type3 fonts which generates slightly different outlines. Type1 has the same
problem.
--
Text transformations is a mess in PS/PDF backends. Many combinations of
rotated/scaled ctm, rotated/scaled font_matrix, and subsetting code used
(Type1/Type3/TrueType) are broken.
--
Move docs inline. see
http://lists.freedesktop.org/archives/cairo/2006-July/007431.html
--
Look into the glyph cache. Moreover, make sure we are reusing scaled fonts
enough.

View file

@ -84,10 +84,10 @@ double d = 909042349670368103374704789055050114762116927356156320147971208440534
]])], [
if strings -a conftest.$ac_objext | grep noonsees >/dev/null ; then
if strings - conftest.$ac_objext | grep noonsees >/dev/null ; then
ax_cv_c_float_words_bigendian=yes
fi
if strings -a conftest.$ac_objext | grep seesnoon >/dev/null ; then
if strings - conftest.$ac_objext | grep seesnoon >/dev/null ; then
if test "$ax_cv_c_float_words_bigendian" = unknown; then
ax_cv_c_float_words_bigendian=no
else

View file

@ -5,7 +5,7 @@ dnl An odd micro number indicates in-progress development, (eg. from git/cvs)
dnl An even micro number indicates a released version.
m4_define(cairo_version_major, 1)
m4_define(cairo_version_minor, 3)
m4_define(cairo_version_micro, 11)
m4_define(cairo_version_micro, 13)
AC_INIT([cairo],
cairo_version_major.cairo_version_minor.cairo_version_micro,
@ -231,7 +231,8 @@ dnl ===========================================================================
CAIRO_BACKEND_ENABLE(xlib, Xlib, xlib, XLIB_SURFACE, auto, [
xlib_REQUIRES="x11"
PKG_CHECK_MODULES(xlib, $xlib_REQUIRES, ,
[xlib_REQUIRES=""
[AC_MSG_RESULT(no)
xlib_REQUIRES=""
AC_PATH_XTRA
if test "x$no_x" = xyes; then
use_xlib="no (requires X development libraries)"
@ -253,7 +254,8 @@ CAIRO_BACKEND_ENABLE(xlib_xrender, Xlib Xrender, xlib-xrender, XLIB_XRENDER_SURF
xlib_xrender_BASE=cairo-xlib
xlib_xrender_REQUIRES="xrender >= 0.6"
PKG_CHECK_MODULES(xlib_xrender, $xlib_xrender_REQUIRES, ,
[xlib_xrender_REQUIRES=""
[AC_MSG_RESULT(no)
xlib_xrender_REQUIRES=""
AC_CHECK_HEADER(X11/extensions/Xrender.h,
[xlib_xrender_NONPKGCONFIG_LIBS="-lXrender"],
[use_xlib_xrender="no (requires Xrender http://freedesktop.org/Software/xlibs)"])])
@ -264,7 +266,7 @@ dnl ===========================================================================
CAIRO_BACKEND_ENABLE(xcb, XCB, xcb, XCB_SURFACE, no, [
xcb_REQUIRES="xcb >= 0.9.92 xcb-render >= 0.9.92 xcb-renderutil"
PKG_CHECK_MODULES(xcb, $xcb_REQUIRES, , [
PKG_CHECK_MODULES(xcb, $xcb_REQUIRES, , [AC_MSG_RESULT(no)
use_xcb="no (requires XCB http://xcb.freedesktop.org)"])
])
@ -351,7 +353,7 @@ CAIRO_BACKEND_ENABLE(png, PNG, png, PNG_FUNCTIONS, yes, [
fi
if test "x$use_png" = "xyes" ; then
PKG_CHECK_MODULES(png, $png_REQUIRES)
PKG_CHECK_MODULES(png, $png_REQUIRES, , AC_MSG_RESULT(no))
else
AC_MSG_WARN([Could not find libpng in the pkg-config search path])
fi
@ -368,19 +370,19 @@ dnl ===========================================================================
GLITZ_MIN_VERSION=0.5.1
CAIRO_BACKEND_ENABLE(glitz, glitz, glitz, GLITZ_SURFACE, no, [
glitz_REQUIRES="glitz >= $GLITZ_MIN_VERSION"
PKG_CHECK_MODULES(glitz, $glitz_REQUIRES, , [
PKG_CHECK_MODULES(glitz, $glitz_REQUIRES, , [AC_MSG_RESULT(no)
use_glitz="no (requires glitz http://freedesktop.org/Software/glitz)"])
])
if test "x$use_glitz" = "xyes";then
PKG_CHECK_MODULES(GLITZ_AGL, glitz-agl >= $GLITZ_MIN_VERSION,
[have_glitz_agl=yes], [have_glitz_agl=no; echo $MYSTUFF_PKG_ERRORS])
[have_glitz_agl=yes], [have_glitz_agl=no; AC_MSG_RESULT(no)])
PKG_CHECK_MODULES(GLITZ_EGL, glitz-egl >= $GLITZ_MIN_VERSION,
[have_glitz_egl=yes], [have_glitz_egl=no; echo $MYSTUFF_PKG_ERRORS])
[have_glitz_egl=yes], [have_glitz_egl=no; AC_MSG_RESULT(no)])
PKG_CHECK_MODULES(GLITZ_GLX, glitz-glx >= $GLITZ_MIN_VERSION,
[have_glitz_glx=yes], [have_glitz_glx=no; echo $MYSTUFF_PKG_ERRORS])
[have_glitz_glx=yes], [have_glitz_glx=no; AC_MSG_RESULT(no)])
PKG_CHECK_MODULES(GLITZ_WGL, glitz-wgl >= $GLITZ_MIN_VERSION,
[have_glitz_wgl=yes], [have_glitz_wgl=no; echo $MYSTUFF_PKG_ERRORS])
[have_glitz_wgl=yes], [have_glitz_wgl=no; AC_MSG_RESULT(no)])
if test "x$have_glitz_agl" = "xyes";then
AC_DEFINE(CAIRO_CAN_TEST_GLITZ_AGL_SURFACE, 1, [define if glitz backend can be tested against agl])
@ -405,7 +407,7 @@ dnl ===========================================================================
CAIRO_BACKEND_ENABLE(directfb, directfb, directfb, DIRECTFB_SURFACE, no, [
directfb_REQUIRES=directfb
PKG_CHECK_MODULES(directfb, $directfb_REQUIRES, ,
PKG_CHECK_MODULES(directfb, $directfb_REQUIRES, , AC_MSG_RESULT(no)
[use_directfb="no (requires directfb http://www.directfb.org)"])
])
@ -435,11 +437,13 @@ CAIRO_BACKEND_ENABLE(ft, FreeType font, freetype, FT_FONT, auto, [
ft_REQUIRES="fontconfig"
PKG_CHECK_MODULES(FONTCONFIG, $ft_REQUIRES,
[_CHECK_FUNCS_WITH_FLAGS(FcFini, $ft_CFLAGS, $ft_LIBS)],
[use_ft="no (requires fontconfig"])
[AC_MSG_RESULT(no); use_ft="no (requires fontconfig"])
if test "x$use_ft" = "xyes"; then
PKG_CHECK_MODULES(FREETYPE, freetype2 >= $FREETYPE_MIN_VERSION,
[freetype_pkgconfig=yes], [freetype_pkgconfig=no])
[freetype_pkgconfig=yes],
[AC_MSG_RESULT(no)
freetype_pkgconfig=no])
if test "x$freetype_pkgconfig" = "xyes"; then
ft_REQUIRES="freetype2 >= $FREETYPE_MIN_VERSION $ft_REQUIRES"
@ -517,7 +521,10 @@ POPPLER_VERSION_REQUIRED=0.4.1
test_pdf=no
if test "x$use_pdf" = "xyes"; then
poppler_DEPENDENCY="poppler-glib >= $POPPLER_VERSION_REQUIRED"
PKG_CHECK_MODULES(POPPLER, $poppler_DEPENDENCY pango gtk+-2.0, [test_pdf=yes], [test_pdf="no (requires $poppler_DEPENDENCY)"])
PKG_CHECK_MODULES(POPPLER, $poppler_DEPENDENCY pango gtk+-2.0,
[test_pdf=yes],
[AC_MSG_RESULT(no)
test_pdf="no (requires $poppler_DEPENDENCY)"])
if test "x$test_pdf" = "xyes"; then
AC_DEFINE([CAIRO_CAN_TEST_PDF_SURFACE], 1, [Define to 1 if the PDF backend can be tested (need poppler and other dependencies for pdf2png)])
else
@ -542,7 +549,10 @@ CAIRO_BACKEND_ENABLE(svg, SVG, svg, SVG_SURFACE, auto, [
LIBRSVG_VERSION_REQUIRED=2.15.0
if test "x$use_svg" = "xyes"; then
librsvg_DEPENDENCY="librsvg-2.0 >= $LIBRSVG_VERSION_REQUIRED"
PKG_CHECK_MODULES(LIBRSVG, $librsvg_DEPENDENCY gdk-2.0, [test_svg=yes], [test_svg="no (requires $librsvg_DEPENDENCY)"])
PKG_CHECK_MODULES(LIBRSVG, $librsvg_DEPENDENCY gdk-2.0,
[test_svg=yes],
[AC_MSG_RESULT(no)
test_svg="no (requires $librsvg_DEPENDENCY)"])
if test "x$test_svg" = "xyes"; then
AC_DEFINE([CAIRO_CAN_TEST_SVG_SURFACE], 1, [Define to 1 if the SVG backend can be tested])
else

View file

@ -8,14 +8,14 @@ Compile-time and run-time version checks.
<para>
Cairo has a three-part version number scheme. In this scheme, we use
even vs. odd numbers to distinguish fixed points in the software
vs. in-progress development, (such as from CVS instead of a tar file,
vs. in-progress development, (such as from git instead of a tar file,
or as a "snapshot" tar file as opposed to a "release" tar file).
</para>
<para>
<informalexample><programlisting>
_____ Major. Always 1, until we invent a new scheme.
/ ___ Minor. Even/Odd = Release/Snapshot (tar files) or Branch/Head (CVS)
| / _ Micro. Even/Odd = Tar-file/CVS
/ ___ Minor. Even/Odd = Release/Snapshot (tar files) or Branch/Head (git)
| / _ Micro. Even/Odd = Tar-file/git
| | /
1.0.0
</programlisting></informalexample>
@ -33,7 +33,7 @@ Snapshots
---------
1.1.2 - A snapshot (working toward the 1.2.0 release)
In-progress development (eg. from CVS)
In-progress development (eg. from git)
--------------------------------------
1.0.1 - Development on a maintenance branch (toward 1.0.2 release)
1.1.1 - Development on head (toward 1.1.2 snapshot and 1.2.0 release)
@ -157,7 +157,7 @@ at compile-time, in the form of "X.Y.Z".
<!-- ##### MACRO CAIRO_VERSION_ENCODE ##### -->
<para>
This macro encodes the given cairo version into an integer. The numbers
returned by %CAIRO_VERSION and pango_version() are encoded using this macro.
returned by %CAIRO_VERSION and cairo_version() are encoded using this macro.
Two encoded version numbers can be compared as integers. The encoding ensures
that later versions compare greater than earlier versions.
</para>

View file

@ -233,7 +233,6 @@ The cairo drawing context
</para>
@cr:
@count:
@Returns:
@ -245,7 +244,6 @@ The cairo drawing context
@cr:
@dashes:
@offset:
@Returns:
<!-- ##### ENUM cairo_fill_rule_t ##### -->
@ -483,15 +481,6 @@ The cairo drawing context
@rectangle_list:
<!-- ##### FUNCTION cairo_copy_clip_rectangles ##### -->
<para>
</para>
@cr:
@Returns:
<!-- ##### FUNCTION cairo_fill ##### -->
<para>

View file

@ -21,18 +21,20 @@ cairo_perf_SOURCES = \
cairo-stats.h \
box-outline.c \
fill.c \
long-lines.c \
mosaic.c \
mosaic.h \
paint.c \
pattern_create_radial.c \
stroke.c \
subimage_copy.c \
tessellate.c \
pattern_create_radial.c \
unaligned-clip.c \
text.c \
world-map.c \
world-map.h \
zrusin.c \
zrusin-another.h \
mosaic.c \
mosaic.h
zrusin-another.h
if CAIRO_HAS_WIN32_SURFACE
cairo_perf_SOURCES += cairo-perf-win32.c

View file

@ -31,6 +31,9 @@ usage() {
echo " $argv0 HEAD -- stroke" >&2
echo "" >&2
echo "The performance results are cached in .perf next to the .git directory." >&2
echo "" >&2
echo "Set CAIRO_AUTOGEN_OPTIONS to pass options to autogen for both" >&2
echo "builds." >&2
exit 1
}
@ -131,7 +134,7 @@ run_cairo_perf_if_not_cached() {
git checkout tmp-cairo-perf-diff
git reset --hard $sha
if [ ! -e Makefile ]; then
CFLAGS="-O2" ./autogen.sh
CFLAGS="-O2" ./autogen.sh $CAIRO_AUTOGEN_OPTIONS
fi
make CFLAGS="-O2" || (rm config.cache && make CFLAGS="-O2")
for file in $boilerplate_files; do

View file

@ -129,6 +129,15 @@ typedef enum {
TEST_REPORT_STATUS_ERROR
} test_report_status_t;
typedef struct _cairo_perf_diff_files_args {
char const *old_filename;
char const *new_filename;
double min_change;
int use_utf;
int print_change_bars;
int use_ms;
} cairo_perf_diff_files_args_t;
/* Ad-hoc parsing, macros with a strong dependence on the calling
* context, and plenty of other ugliness is here. But at least it's
* not perl... */
@ -429,46 +438,55 @@ cairo_perf_report_sort_and_compute_stats (cairo_perf_report_t *report)
#define CHANGE_BAR_WIDTH 70
static void
print_change_bar (double change, double max_change)
print_change_bar (double change, double max_change, int use_utf)
{
int units_per_cell = (int) ceil (max_change / CHANGE_BAR_WIDTH);
static char const *ascii_boxes[8] = {
"****","***" ,"***", "**",
"**", "*", "*", ""
};
static char const *utf_boxes[8] = {
"", "", "", "",
"", "", "", ""
};
char const **boxes = use_utf ? utf_boxes : ascii_boxes;
/* For a 1.0x speedup we want a zero-size bar to show "no
* change". */
change -= 1.0;
while (change > units_per_cell) {
printf("");
printf(boxes[0]);
change -= units_per_cell;
}
change /= units_per_cell;
if (change > 7.5/8.0)
printf("");
printf(boxes[0]);
else if (change > 6.5/8.0)
printf("");
printf(boxes[1]);
else if (change > 5.5/8.0)
printf("");
printf(boxes[2]);
else if (change > 4.5/8.0)
printf("");
printf(boxes[3]);
else if (change > 3.5/8.0)
printf("");
printf(boxes[4]);
else if (change > 2.5/8.0)
printf("");
printf(boxes[5]);
else if (change > 1.5/8.0)
printf("");
printf(boxes[6]);
else if (change > 0.5/8.0)
printf("");
printf(boxes[7]);
printf ("\n");
}
#define MAX(a,b) ((a) > (b) ? (a) : (b))
static void
cairo_perf_report_diff (cairo_perf_report_t *old,
cairo_perf_report_t *new,
double min_change)
cairo_perf_report_diff (cairo_perf_report_t *old,
cairo_perf_report_t *new,
cairo_perf_diff_files_args_t const *args)
{
int i, i_old, i_new;
test_report_t *o, *n;
@ -476,7 +494,7 @@ cairo_perf_report_diff (cairo_perf_report_t *old,
test_diff_t *diff, *diffs;
int num_diffs = 0;
int printed_speedup = 0, printed_slowdown = 0;
double change, max_change;
double min_change = args->min_change, change, max_change;
diffs = xmalloc (MAX (old->tests_count, new->tests_count) * sizeof (test_diff_t));
@ -516,7 +534,14 @@ cairo_perf_report_diff (cairo_perf_report_t *old,
diffs[num_diffs].old = o;
diffs[num_diffs].new = n;
diffs[num_diffs].speedup = (double) o->stats.min_ticks / n->stats.min_ticks;
if (args->use_ms) {
diffs[num_diffs].speedup =
(double) (o->stats.min_ticks / o->stats.ticks_per_ms)
/ (n->stats.min_ticks / n->stats.ticks_per_ms);
} else {
diffs[num_diffs].speedup =
(double) o->stats.min_ticks / n->stats.min_ticks;
}
num_diffs++;
i_old++;
@ -577,7 +602,8 @@ cairo_perf_report_diff (cairo_perf_report_t *old,
else
printf ("slowdown\n");
print_change_bar (change, max_change);
if (args->print_change_bars)
print_change_bar (change, max_change, args->use_utf);
}
free (diffs);
@ -586,42 +612,91 @@ cairo_perf_report_diff (cairo_perf_report_t *old,
static void
usage (const char *argv0)
{
fprintf (stderr, "Usage: %s file1 file2 [minimum_significant_change[%%]]\n", argv0);
char const *basename = strrchr(argv0, '/');
basename = basename ? basename+1 : argv0;
fprintf (stderr,
"Usage: %s [--no-utf] [--no-bars] file1 file2 [minimum_significant_change[%%]]\n\n",
basename);
fprintf (stderr,
"Computes significant performance differences for cairo performance reports.\n"
"Each file should be the output of the cairo-perf program (or \"make perf\").\n"
"The third argument is used to supress all changes below some threshold.\n"
"The default value of 5%% ignores any speeedup or slowdown of 5%% or less,\n"
"A value of 0 will cause all output to be reported.\n");
"A value of 0 will cause all output to be reported.\n"
"\n"
"--no-utf Use ascii stars instead of utf-8 change bars.\n"
" Four stars are printed per factor of speedup.\n"
"--no-bars Don't display change bars at all.\n"
"--use-ms Use milliseconds to calculate differences.\n"
" (instead of ticks which are hardware dependant)\n"
);
exit(1);
}
static void
parse_args(int argc,
char const **argv,
cairo_perf_diff_files_args_t *args)
{
#define is_yesno_opt(opt) !(strcmp ("--no-" opt, argv[i]) && strcmp ("--" opt, argv[i]))
int i;
int have_minchange = 0;
for (i=1; i<argc; i++) {
if (is_yesno_opt("utf")) {
args->use_utf = 0 != strncmp ("--no-", argv[i], 4);
}
else if (is_yesno_opt("bars")) {
args->print_change_bars = 0 != strncmp ("--no-", argv[i], 4);
}
else if (strcmp(argv[i], "--use-ms") == 0) {
args->use_ms = 1;
}
else if (!args->old_filename) {
args->old_filename = argv[i];
}
else if (!args->new_filename) {
args->new_filename = argv[i];
}
else if (!have_minchange) {
char *end = NULL;
args->min_change = strtod (argv[i], &end);
if (*end && *end) {
if (0 == strcmp (end, "%")) {
args->min_change /= 100;
} else {
usage (argv[0]);
}
}
}
else {
usage (argv[0]);
}
}
if ( !args->old_filename || !args->new_filename )
usage (argv[0]);
#undef is_yesno_opt
}
int
main (int argc, const char *argv[])
{
const char *old_filename, *new_filename;
cairo_perf_diff_files_args_t args = {
NULL, /* old filename */
NULL, /* new filename */
0.05, /* min change */
1, /* use UTF-8? */
1, /* display change bars? */
};
cairo_perf_report_t old, new;
double min_change;
char *end;
if (argc < 3) {
usage (argv[0]);
return 1;
}
parse_args (argc, argv, &args);
old_filename = argv[1];
new_filename = argv[2];
cairo_perf_report_load (&old, args.old_filename);
cairo_perf_report_load (&new, args.new_filename);
min_change = 0.05;
if (argc >= 4) {
min_change = strtod (argv[3], &end);
if (*end && *end == '%')
min_change = min_change / 100.0;
}
cairo_perf_report_load (&old, old_filename);
cairo_perf_report_load (&new, new_filename);
cairo_perf_report_diff (&old, &new, min_change);
cairo_perf_report_diff (&old, &new, &args);
return 0;
}

View file

@ -327,5 +327,7 @@ cairo_perf_case_t perf_cases[] = {
{ world_map, 800, 800},
{ box_outline, 100, 100},
{ mosaic, 800, 800 },
{ long_lines, 100, 100},
{ unaligned_clip, 100, 100},
{ NULL }
};

View file

@ -103,5 +103,7 @@ CAIRO_PERF_DECL (zrusin);
CAIRO_PERF_DECL (world_map);
CAIRO_PERF_DECL (box_outline);
CAIRO_PERF_DECL (mosaic);
CAIRO_PERF_DECL (long_lines);
CAIRO_PERF_DECL (unaligned_clip);
#endif

117
perf/long-lines.c Normal file
View file

@ -0,0 +1,117 @@
/*
* Copyright © 2006 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Author: Carl D. Worth <cworth@cworth.org>
*/
#include "cairo-perf.h"
/* This test case is designed to illustrate a performance bug in
* drawing very long lines, where most of the line is out of bounds of
* the destination surface, (but some portion of the line is
* visibile). These results are in the "long-lines-uncropped" report.
*
* For comparison, this test also renders the visible portions of the
* same lines, (this is the "long-lines-cropped" report).
*/
typedef enum { LONG_LINES_UNCROPPED, LONG_LINES_CROPPED } long_lines_crop_t;
#define NUM_LINES 20
#define LONG_FACTOR 50.0
static cairo_perf_ticks_t
do_long_lines (cairo_t *cr, int width, int height, long_lines_crop_t crop)
{
int i;
double x, y, dx, dy, min_x, min_y, max_x, max_y;
double outer_width, outer_height;
cairo_save (cr);
cairo_translate (cr, width / 2, height / 2);
if (crop == LONG_LINES_UNCROPPED) {
outer_width = LONG_FACTOR * width;
outer_height = LONG_FACTOR * height;
cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); /* red */
} else {
outer_width = width;
outer_height = height;
cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); /* green */
}
min_x = x = - outer_width / 2.0;
min_y = y = - outer_height / 2.0;
max_x = outer_width / 2.0;
max_y = outer_width / 2.0;
dx = outer_width / NUM_LINES;
dy = outer_height / NUM_LINES;
cairo_perf_timer_start ();
for (i = 0; i < NUM_LINES; i++) {
cairo_move_to (cr, 0, 0);
cairo_line_to (cr, x, min_y);
cairo_stroke (cr);
cairo_move_to (cr, 0, 0);
cairo_line_to (cr, x, max_y);
cairo_stroke (cr);
cairo_move_to (cr, 0, 0);
cairo_line_to (cr, min_x, y);
cairo_stroke (cr);
cairo_move_to (cr, 0, 0);
cairo_line_to (cr, max_x, y);
cairo_stroke (cr);
x += dx;
y += dy;
}
cairo_perf_timer_stop ();
cairo_restore (cr);
return cairo_perf_timer_elapsed ();
}
static cairo_perf_ticks_t
long_lines_uncropped (cairo_t *cr, int width, int height)
{
return do_long_lines (cr, width, height, LONG_LINES_UNCROPPED);
}
static cairo_perf_ticks_t
long_lines_cropped (cairo_t *cr, int width, int height)
{
return do_long_lines (cr, width, height, LONG_LINES_CROPPED);
}
void
long_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped);
cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped);
}

66
perf/unaligned-clip.c Normal file
View file

@ -0,0 +1,66 @@
/*
* Copyright © 2006 Jeff Muizelaar <jeff@infidigm.net>
* Copyright © 2006 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: Jeff Muizelaar <jeff@infidigm.net>
* Carl Worth <cworth@cworth.org>
*/
#include "cairo-perf.h"
static cairo_perf_ticks_t
do_unaligned_clip (cairo_t *cr, int width, int height)
{
cairo_save (cr);
cairo_perf_timer_start ();
/* First a triangular clip that obviously isn't along device-pixel
* boundaries. */
cairo_move_to (cr, 50, 50);
cairo_line_to (cr, 50, 90);
cairo_line_to (cr, 90, 90);
cairo_close_path (cr);
cairo_clip (cr);
/* Then a rectangular clip that would be but for the non-integer
* scaling. */
cairo_scale (cr, 1.1, 1.1);
cairo_move_to (cr, 55, 55);
cairo_line_to (cr, 90, 55);
cairo_line_to (cr, 90, 90);
cairo_line_to (cr, 90, 55);
cairo_close_path (cr);
cairo_clip (cr);
cairo_perf_timer_stop ();
cairo_restore (cr);
return cairo_perf_timer_elapsed ();
}
void
unaligned_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height)
{
cairo_perf_run (perf, "unaligned_clip", do_unaligned_clip);
}

View file

@ -157,6 +157,11 @@ static const MMXData c =
#define MC(x) c.mmx_##x
#endif
/* cast to void* in the middle to shut gcc up warning about
* "dereferencing type-punned pointers".
*/
#define M64(x) (*(__m64*)(void*)(&x))
static __inline__ __m64
shift (__m64 v, int s)
{
@ -1443,6 +1448,128 @@ fbCompositeSrc_8888x8888mmx (pixman_operator_t op,
_mm_empty();
}
void
fbCompositeSrc_8888x0565mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
CARD16 *dstLine, *dst;
CARD32 *srcLine, *src;
FbStride dstStride, srcStride;
CARD16 w;
CHECKPOINT();
fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
assert (pSrc->pDrawable == pMask->pDrawable);
while (height--)
{
dst = dstLine;
dstLine += dstStride;
src = srcLine;
srcLine += srcStride;
w = width;
CHECKPOINT();
while (w && (unsigned long)dst & 7)
{
__m64 vsrc = load8888 (*src);
ullong d = *dst;
__m64 vdest = expand565 ((__m64)d, 0);
vdest = pack565(over(vsrc, expand_alpha(vsrc), vdest), vdest, 0);
*dst = (ullong)vdest;
w--;
dst++;
src++;
}
CHECKPOINT();
while (w >= 4)
{
CARD32 s0, s1, s2, s3;
unsigned char a0, a1, a2, a3;
__m64 vsrc0, vsrc1, vsrc2, vsrc3;
s0 = *src;
s1 = *(src + 1);
s2 = *(src + 2);
s3 = *(src + 3);
a0 = (s0 >> 24);
a1 = (s1 >> 24);
a2 = (s2 >> 24);
a3 = (s3 >> 24);
vsrc0 = load8888(s0);
vsrc1 = load8888(s1);
vsrc2 = load8888(s2);
vsrc3 = load8888(s3);
if ((a0 & a1 & a2 & a3) == 0xFF)
{
__m64 vdest;
vdest = pack565(vsrc0, _mm_setzero_si64(), 0);
vdest = pack565(vsrc1, vdest, 1);
vdest = pack565(vsrc2, vdest, 2);
vdest = pack565(vsrc3, vdest, 3);
*(__m64 *)dst = vdest;
}
else if (a0 | a1 | a2 | a3)
{
__m64 vdest = *(__m64 *)dst;
vdest = pack565(over(vsrc0, expand_alpha(vsrc0), expand565(vdest, 0)), vdest, 0);
vdest = pack565(over(vsrc1, expand_alpha(vsrc1), expand565(vdest, 1)), vdest, 1);
vdest = pack565(over(vsrc2, expand_alpha(vsrc2), expand565(vdest, 2)), vdest, 2);
vdest = pack565(over(vsrc3, expand_alpha(vsrc3), expand565(vdest, 3)), vdest, 3);
*(__m64 *)dst = vdest;
}
w -= 4;
dst += 4;
src += 4;
}
CHECKPOINT();
while (w)
{
__m64 vsrc = load8888 (*src);
ullong d = *dst;
__m64 vdest = expand565 ((__m64)d, 0);
vdest = pack565(over(vsrc, expand_alpha(vsrc), vdest), vdest, 0);
*dst = (ullong)vdest;
w--;
dst++;
src++;
}
}
_mm_empty();
}
void
fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
PicturePtr pSrc,
@ -1497,7 +1624,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
if (m)
{
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), load8888(*dst));
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), load8888(*dst));
*dst = store8888(vdest);
}
@ -1525,8 +1652,8 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
vdest = *(__m64 *)dst;
dest0 = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m0)), expand8888(vdest, 0));
dest1 = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m1)), expand8888(vdest, 1));
dest0 = in_over(vsrc, vsrca, expand_alpha_rev (M64(m0)), expand8888(vdest, 0));
dest1 = in_over(vsrc, vsrca, expand_alpha_rev (M64(m1)), expand8888(vdest, 1));
*(__m64 *)dst = pack8888(dest0, dest1);
}
@ -1545,7 +1672,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op,
if (m)
{
__m64 vdest = load8888(*dst);
vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), vdest);
vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), vdest);
*dst = store8888(vdest);
}
@ -1615,7 +1742,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
if (m)
{
__m64 vdest = in(vsrc, expand_alpha_rev (*(__m64*)(&m)));
__m64 vdest = in(vsrc, expand_alpha_rev (M64(m)));
*dst = store8888(vdest);
}
else
@ -1647,8 +1774,8 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
vdest = *(__m64 *)dst;
dest0 = in(vsrc, expand_alpha_rev (*(__m64*)(&m0)));
dest1 = in(vsrc, expand_alpha_rev (*(__m64*)(&m1)));
dest0 = in(vsrc, expand_alpha_rev (M64(m0)));
dest1 = in(vsrc, expand_alpha_rev (M64(m1)));
*(__m64 *)dst = pack8888(dest0, dest1);
}
@ -1671,7 +1798,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
if (m)
{
__m64 vdest = load8888(*dst);
vdest = in(vsrc, expand_alpha_rev (*(__m64*)(&m)));
vdest = in(vsrc, expand_alpha_rev (M64(m)));
*dst = store8888(vdest);
}
else
@ -1726,7 +1853,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
vsrca = expand_alpha (vsrc);
vsrc16 = pack565(vsrc, _mm_setzero_si64(), 0);
src16 = *(ullong*)(&vsrc16);
src16 = *(ullong*)(void*)(&vsrc16);
srcsrcsrcsrc = (ullong)src16 << 48 | (ullong)src16 << 32 |
(ullong)src16 << 16 | (ullong)src16;
@ -1748,7 +1875,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
if (m)
{
__m64 vd = _mm_cvtsi32_si64 (*dst);
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), expand565(vd, 0));
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), expand565(vd, 0));
*dst = _mm_cvtsi64_si32 (pack565(vdest, _mm_setzero_si64(), 0));
}
@ -1778,13 +1905,13 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
vdest = *(__m64 *)dst;
vm0 = *(__m64*)(&m0);
vm0 = M64(m0);
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm0), expand565(vdest, 0)), vdest, 0);
vm1 = *(__m64*)(&m1);
vm1 = M64(m1);
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm1), expand565(vdest, 1)), vdest, 1);
vm2 = *(__m64*)(&m2);
vm2 = M64(m2);
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm2), expand565(vdest, 2)), vdest, 2);
vm3 = *(__m64*)(&m3);
vm3 = M64(m3);
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm3), expand565(vdest, 3)), vdest, 3);
*(__m64 *)dst = vdest;
@ -1804,7 +1931,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op,
if (m)
{
__m64 vd = _mm_cvtsi32_si64 (*dst);
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), expand565(vd, 0));
__m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (M64(m)), expand565(vd, 0));
*dst = _mm_cvtsi64_si32 (pack565(vdest, _mm_setzero_si64(), 0));
}
@ -2134,6 +2261,232 @@ fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op,
_mm_empty ();
}
void
fbCompositeIn_nx8x8mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
CARD8 *dstLine, *dst;
CARD8 *maskLine, *mask;
FbStride dstStride, maskStride;
CARD16 w;
CARD32 src;
CARD8 sa;
__m64 vsrc, vsrca;
fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 1);
fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
fbComposeGetSolid(pSrc, pDst, src);
sa = src >> 24;
if (sa == 0)
return;
vsrc = load8888(src);
vsrca = expand_alpha(vsrc);
while (height--)
{
dst = dstLine;
dstLine += dstStride;
mask = maskLine;
maskLine += maskStride;
w = width;
if ((((unsigned long)pDst & 3) == 0) &&
(((unsigned long)pSrc & 3) == 0))
{
while (w >= 4)
{
CARD32 m;
__m64 vmask;
__m64 vdest;
m = 0;
vmask = load8888 (*(CARD32 *)mask);
vdest = load8888 (*(CARD32 *)dst);
*(CARD32 *)dst = store8888 (in (in (vsrca, vmask), vdest));
dst += 4;
mask += 4;
w -= 4;
}
}
while (w--)
{
CARD16 tmp;
CARD8 a;
CARD32 m, d;
CARD32 r;
a = *mask++;
d = *dst;
m = FbInU (sa, 0, a, tmp);
r = FbInU (m, 0, d, tmp);
*dst++ = r;
}
}
_mm_empty();
}
void
fbCompositeIn_8x8mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
CARD8 *dstLine, *dst;
CARD8 *srcLine, *src;
FbStride srcStride, dstStride;
CARD16 w;
fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 1);
fbComposeGetStart (pSrc, xSrc, ySrc, CARD8, srcStride, srcLine, 1);
while (height--)
{
dst = dstLine;
dstLine += dstStride;
src = srcLine;
srcLine += srcStride;
w = width;
if ((((unsigned long)pDst & 3) == 0) &&
(((unsigned long)pSrc & 3) == 0))
{
while (w >= 4)
{
CARD32 *s = (CARD32 *)src;
CARD32 *d = (CARD32 *)dst;
*d = store8888 (in (load8888 (*s), load8888 (*d)));
w -= 4;
dst += 4;
src += 4;
}
}
while (w--)
{
CARD8 s, d;
CARD16 tmp;
s = *src;
d = *dst;
*dst = FbInU (s, 0, d, tmp);
src++;
dst++;
}
}
_mm_empty ();
}
void
fbCompositeSrcAdd_8888x8x8mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
CARD8 *dstLine, *dst;
CARD8 *maskLine, *mask;
FbStride dstStride, maskStride;
CARD16 w;
CARD32 src;
CARD8 sa;
__m64 vsrc, vsrca;
fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 1);
fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
fbComposeGetSolid(pSrc, pDst, src);
sa = src >> 24;
if (sa == 0)
return;
vsrc = load8888(src);
vsrca = expand_alpha(vsrc);
while (height--)
{
dst = dstLine;
dstLine += dstStride;
mask = maskLine;
maskLine += maskStride;
w = width;
if ((((unsigned long)pMask & 3) == 0) &&
(((unsigned long)pDst & 3) == 0))
{
while (w >= 4)
{
__m64 vmask = load8888 (*(CARD32 *)mask);
__m64 vdest = load8888 (*(CARD32 *)dst);
*(CARD32 *)dst = store8888 (_mm_adds_pu8 (in (vsrca, vmask), vdest));
w -= 4;
dst += 4;
mask += 4;
}
}
while (w--)
{
CARD16 tmp;
CARD16 a;
CARD32 m, d;
CARD32 r;
a = *mask++;
d = *dst;
m = FbInU (sa, 0, a, tmp);
r = FbAdd (m, d, 0, tmp);
*dst++ = r;
}
}
_mm_empty();
}
void
fbCompositeSrcAdd_8000x8000mmx (pixman_operator_t op,
PicturePtr pSrc,
@ -2309,7 +2662,7 @@ fbSolidFillmmx (FbPixels *pDraw,
}
fill = ((ullong)xor << 32) | xor;
vfill = *(__m64*)&fill;
vfill = M64(fill);
while (height--)
{

View file

@ -44,6 +44,20 @@ Bool fbHaveMMX(void);
pixman_private
void fbComposeSetupMMX(void);
pixman_private
void fbCompositeIn_nx8x8mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op,
PicturePtr pSrc,
@ -109,6 +123,35 @@ void fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrcAdd_8888x8x8mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeIn_8x8mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrcAdd_8000x8000mmx (pixman_operator_t op,
PicturePtr pSrc,
@ -136,6 +179,19 @@ void fbCompositeSrc_8888RevNPx8888mmx (pixman_operator_t op,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrc_8888x0565mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height);
pixman_private
void fbCompositeSrc_8888RevNPx0565mmx (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,

View file

@ -843,6 +843,58 @@ fbCompositeSrcAdd_8888x8888 (pixman_operator_t op,
}
}
static void
fbCompositeSrcAdd_8888x8x8 (pixman_operator_t op,
PicturePtr pSrc,
PicturePtr pMask,
PicturePtr pDst,
INT16 xSrc,
INT16 ySrc,
INT16 xMask,
INT16 yMask,
INT16 xDst,
INT16 yDst,
CARD16 width,
CARD16 height)
{
CARD8 *dstLine, *dst;
CARD8 *maskLine, *mask;
FbStride dstStride, maskStride;
CARD16 w;
CARD32 src;
CARD8 sa;
fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 1);
fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
fbComposeGetSolid (pSrc, pDst, src);
sa = (src >> 24);
while (height--)
{
dst = dstLine;
dstLine += dstStride;
mask = maskLine;
maskLine += maskStride;
w = width;
while (w--)
{
CARD16 tmp;
CARD16 a;
CARD32 m, d;
CARD32 r;
a = *mask++;
d = *dst;
m = FbInU (sa, 0, a, tmp);
r = FbAdd (m, d, 0, tmp);
*dst++ = r;
}
}
}
static void
fbCompositeSrcAdd_1000x1000 (pixman_operator_t op,
PicturePtr pSrc,
@ -1683,7 +1735,12 @@ pixman_composite (pixman_operator_t op,
func = fbCompositeSrc_8888x0888;
break;
case PICT_r5g6b5:
func = fbCompositeSrc_8888x0565;
#ifdef USE_MMX
if (fbHaveMMX())
func = fbCompositeSrc_8888x0565mmx;
else
#endif
func = fbCompositeSrc_8888x0565;
break;
}
break;
@ -1702,7 +1759,12 @@ pixman_composite (pixman_operator_t op,
func = fbCompositeSrc_8888x0888;
break;
case PICT_b5g6r5:
func = fbCompositeSrc_8888x0565;
#ifdef USE_MMX
if (fbHaveMMX())
func = fbCompositeSrc_8888x0565mmx;
else
#endif
func = fbCompositeSrc_8888x0565;
break;
}
break;
@ -1759,6 +1821,26 @@ pixman_composite (pixman_operator_t op,
break;
}
}
else
{
if ((pSrc->format_code == PICT_a8r8g8b8 ||
pSrc->format_code == PICT_a8b8g8r8) &&
srcRepeat &&
pMask->format_code == PICT_a8 &&
pDst->format_code == PICT_a8)
{
#ifdef USE_MMX
if (fbHaveMMX())
{
srcRepeat = FALSE;
func = fbCompositeSrcAdd_8888x8x8mmx;
}
else
#endif
func = fbCompositeSrcAdd_8888x8x8;
}
}
break;
case PIXMAN_OPERATOR_SRC:
if (pMask)
@ -1798,10 +1880,34 @@ pixman_composite (pixman_operator_t op,
}
}
break;
case PIXMAN_OPERATOR_IN:
#ifdef USE_MMX
if (pSrc->format_code == PICT_a8 &&
pDst->format_code == PICT_a8 &&
!pMask)
{
if (fbHaveMMX())
func = fbCompositeIn_8x8mmx;
}
else if (srcRepeat && pMask && !pMask->componentAlpha &&
(pSrc->format_code == PICT_a8r8g8b8 ||
pSrc->format_code == PICT_a8b8g8r8) &&
(pMask->format_code == PICT_a8) &&
pDst->format_code == PICT_a8)
{
if (fbHaveMMX())
{
srcRepeat = FALSE;
func = fbCompositeIn_nx8x8mmx;
}
}
#else
func = NULL;
#endif
break;
case PIXMAN_OPERATOR_CLEAR:
case PIXMAN_OPERATOR_DST:
case PIXMAN_OPERATOR_OVER_REVERSE:
case PIXMAN_OPERATOR_IN:
case PIXMAN_OPERATOR_IN_REVERSE:
case PIXMAN_OPERATOR_OUT:
case PIXMAN_OPERATOR_OUT_REVERSE:

View file

@ -26,9 +26,9 @@
#ifdef ICINT_NEED_IC_ONES
/* Fall back on HACKMEM 169. */
int
_FbOnes (unsigned long mask)
_FbOnes (unsigned int mask)
{
register unsigned long y;
register int y;
y = (mask >> 1) &033333333333;
y = mask - y - ((y >>1) & 033333333333);

View file

@ -804,15 +804,15 @@ fbRasterizeTrapezoid (pixman_image_t *pMask,
in libgcc in case a target does not have one, which should be just as
good as the static function below. */
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
# if __INT_MIN__ == 0x7fffffff
# define _FbOnes(mask) __builtin_popcount(mask)
# else
# define _FbOnes(mask) __builtin_popcountl((mask) & 0xffffffff)
# endif
static INLINE int
_FbOnes(unsigned int mask)
{
return __builtin_popcount(mask);
}
#else
# define ICINT_NEED_IC_ONES
pixman_private int
_FbOnes(unsigned long mask);
_FbOnes(unsigned int mask);
#endif
/* icformat.c */

View file

@ -13,6 +13,7 @@
#define fbCompositeSolid_nx8888mmx _cairo_pixman_composite_solid_nx8888mmx
#define fbCompositeSrc_8888RevNPx0565mmx _cairo_pixman_composite_src_8888RevNPx0565mmx
#define fbCompositeSrc_8888RevNPx8888mmx _cairo_pixman_composite_src_8888RevNPx8888_mmx
#define fbCompositeSrc_8888x0565mmx _cairo_pixman_composite_src_8888x0565mmx
#define fbCompositeSrc_8888x8888mmx _cairo_pixman_composite_src_8888x8888mmx
#define fbCompositeSrc_8888x8x8888mmx _cairo_pixman_composite_src_8888x8x8888mmx
#define fbCompositeSrcAdd_8000x8000mmx _cairo_pixman_composite_src_add_8000x8000mmx

View file

@ -1421,7 +1421,7 @@ QuickSortRects(
* Step 2. Split the rectangles into the minimum number of proper y-x
* banded regions. This may require horizontally merging
* rectangles, and vertically coalescing bands. With any luck,
* this step in an identity tranformation (ala the Box widget),
* this step in an identity transformation (ala the Box widget),
* or a coalescing into 1 box (ala Menus).
*
* Step 3. Merge the separate regions down to a single region by calling

View file

@ -177,6 +177,7 @@ libcairo_la_SOURCES = \
cairo-clip-private.h \
cairo-color.c \
cairo-debug.c \
cairo-deflate-stream.c \
cairo-fixed.c \
cairo-font.c \
cairo-font-options.c \
@ -261,9 +262,11 @@ $(backend_pkgconfigs): $(top_srcdir)/configure
$(top_builddir)/config.h: $(top_srcdir)/config.h.in
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) config.h
DISTCLEANFILES += cairo-features.h
cairo-features.h:
cd $(top_builddir) && ./config.status src/cairo-features.h
CLEANFILES = cairo.def
cairo.def: $(cairoinclude_HEADERS)
@echo Generating $@
@(echo EXPORTS; \
@ -290,5 +293,3 @@ install-data-local:
TESTS_ENVIRONMENT = srcdir="$(srcdir)"
TESTS = check-def.sh check-plt.sh check-headers.sh
EXTRA_DIST += $(TESTS)
CLEANFILES = cairo.def cairo-features.h

View file

@ -44,7 +44,7 @@
* @element_size.
*
* The #cairo_array_t object provides grow-by-doubling storage. It
* never intereprets the data passed to it, nor does it provide any
* never interprets the data passed to it, nor does it provide any
* sort of callback mechanism for freeing resources held onto by
* stored objects.
*

View file

@ -63,6 +63,7 @@
typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
typedef struct _cairo_atsui_font cairo_atsui_font_t;
typedef struct _cairo_atsui_scaled_path cairo_atsui_scaled_path_t;
static cairo_status_t _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
ATSUFontID font_id,
@ -85,6 +86,11 @@ struct _cairo_atsui_font_face {
ATSUFontID font_id;
};
struct _cairo_atsui_scaled_path {
cairo_path_fixed_t *path;
cairo_matrix_t *scale;
};
static void
_cairo_atsui_font_face_destroy (void *abstract_face)
{
@ -137,6 +143,47 @@ cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
return &font_face->base;
}
static CGContextRef
CGBitmapContextCreateWithCairoImageSurface (const cairo_image_surface_t * surface)
{
CGContextRef contextRef;
CGColorSpaceRef colorSpace;
int bits_per_comp, alpha;
/* Create a CGBitmapContext for the dest surface for drawing into */
if (surface->depth == 1) {
colorSpace = CGColorSpaceCreateDeviceGray ();
bits_per_comp = 1;
alpha = kCGImageAlphaNone;
} else if (surface->depth == 8) {
colorSpace = CGColorSpaceCreateDeviceGray ();
bits_per_comp = 8;
alpha = kCGImageAlphaNone;
} else if (surface->depth == 24) {
colorSpace = CGColorSpaceCreateDeviceRGB ();
bits_per_comp = 8;
alpha = kCGImageAlphaNoneSkipFirst | CG_BITMAP_BYTE_ORDER_FLAG;
} else if (surface->depth == 32) {
colorSpace = CGColorSpaceCreateDeviceRGB ();
bits_per_comp = 8;
alpha = kCGImageAlphaPremultipliedFirst | CG_BITMAP_BYTE_ORDER_FLAG;
} else {
/* not reached */
return NULL;
}
contextRef = CGBitmapContextCreate (surface->data,
surface->width,
surface->height,
bits_per_comp,
surface->stride,
colorSpace,
alpha);
CGColorSpaceRelease (colorSpace);
return contextRef;
}
static CGAffineTransform
CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale)
{
@ -145,6 +192,17 @@ CGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale)
0, 0);
}
static CGAffineTransform
CGAffineTransformMakeWithCairoScaleFactors(const cairo_matrix_t *scale)
{
double xscale = 1.0;
double yscale = 1.0;
_cairo_matrix_compute_scale_factors(scale, &xscale, &yscale, 1);
return CGAffineTransformMake(xscale, 0,
0, yscale,
0, 0);
}
static ATSUStyle
CreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale)
{
@ -152,14 +210,11 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale)
OSStatus err;
/* Set the style's size */
CGAffineTransform theTransform =
CGAffineTransformMakeWithCairoFontScale(scale);
Fixed theSize =
FloatToFixed(CGSizeApplyAffineTransform
(CGSizeMake(1.0, 1.0), theTransform).height);
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
Fixed theSize = FloatToFixed(1.0);
CGAffineTransform theTransform = CGAffineTransformMakeWithCairoScaleFactors(scale);
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag, kATSUFontMatrixTag };
const ByteCount theFontStyleSizes[] = { sizeof(Fixed), sizeof(CGAffineTransform) };
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize, &theTransform };
err = ATSUCreateAndCopyStyle(inStyle, &style);
@ -269,6 +324,7 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
OSStatus err;
Boolean isItalic, isBold;
const char *family = toy_face->family;
const char *full_name;
err = ATSUCreateStyle(&style);
@ -295,33 +351,56 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
break;
}
/* The APIs for resolving a font family to a regular
* font face are all broken or deprecated in 10.4, so
* just try our best to find a sensible font.
*
* First we try to map the CSS generic font families
* to fonts that should always be available.
* If the family isn't a CSS family, guess that the
* font family name is the same as the full name of the
* regular font instance, which works in many cases.
* 'Times' is one common exception to this rule, so it's
* handled specially.
*/
if (!strcmp(family, "serif") || !strcmp(family, "Times"))
full_name = "Times Roman";
else if (!strcmp(family, "sans-serif") || !strcmp(family, "sans"))
full_name = "Helvetica";
else if (!strcmp(family, "cursive"))
full_name = "Apple Chancery";
else if (!strcmp(family, "fantasy"))
full_name = "American Typewriter";
else if (!strcmp(family, "monospace") || !strcmp(family, "mono"))
full_name = "Courier";
else
full_name = family;
err = ATSUFindFontFromName(family, strlen(family),
kFontFamilyName,
kFontFullName,
kFontNoPlatformCode,
kFontRomanScript,
kFontNoLanguageCode, &fontID);
if (err != noErr) {
/* couldn't get the font - remap css names and try again */
if (!strcmp(family, "serif"))
family = "Times";
else if (!strcmp(family, "sans-serif"))
family = "Helvetica";
else if (!strcmp(family, "cursive"))
family = "Apple Chancery";
else if (!strcmp(family, "fantasy"))
family = "Gadget";
else if (!strcmp(family, "monospace"))
family = "Courier";
else /* anything else - return error instead? */
family = "Courier";
/* Look for any font instance in the family. This may
* succeed, but select the bold or italic face. It only
* selects the first loaded font instance in the family.
*/
err = ATSUFindFontFromName(family, strlen(family),
kFontFamilyName,
kFontNoPlatformCode,
kFontRomanScript,
kFontNoLanguageCode, &fontID);
if (err != noErr) {
/* Last chance - try Courier. */
full_name = "Courier";
err = ATSUFindFontFromName(full_name, strlen(full_name),
kFontFullName,
kFontNoPlatformCode,
kFontRomanScript,
kFontNoLanguageCode, &fontID);
}
}
{
@ -398,11 +477,19 @@ OSStatus _close_path_for_metrics(void *callback_data)
return noErr;
}
static GlyphID
_cairo_atsui_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
if (index > 0xffff)
return kATSDeletedGlyphcode;
return index;
}
static cairo_status_t
_cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_text_extents_t extents;
cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
OSStatus err, callback_err;
ATSGlyphScreenMetrics metricsH;
static ATSCubicMoveToUPP moveProc = NULL;
@ -410,10 +497,17 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
static ATSCubicCurveToUPP curveProc = NULL;
static ATSCubicClosePathUPP closePathProc = NULL;
CGMutablePathRef path;
GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
double xscale, yscale;
CGRect rect;
if (theGlyph == kATSDeletedGlyphcode) {
_cairo_scaled_glyph_set_metrics (scaled_glyph,
&scaled_font->base,
&extents);
return CAIRO_STATUS_SUCCESS;
}
/* We calculate the advance from the screen metrics. We
* could probably take this from the glyph path.
*/
@ -421,7 +515,7 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
1, &theGlyph, 0, false,
false, &metricsH);
if (err != noErr)
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_NO_MEMORY;
/* Scale down to font units.*/
_cairo_matrix_compute_scale_factors (&scaled_font->base.scale,
@ -450,11 +544,8 @@ _cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
(void *)path, &callback_err);
if (err != noErr) {
/* This could potentially happen for bitmap fonts, where
* no paths are available.
*/
CGPathRelease (path);
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_NO_MEMORY;
}
rect = CGPathGetBoundingBox (path);
@ -476,12 +567,15 @@ static OSStatus
_move_to (const Float32Point *point,
void *callback_data)
{
cairo_path_fixed_t *path = callback_data;
_cairo_path_fixed_close_path (path);
_cairo_path_fixed_move_to (path,
_cairo_fixed_from_double(point->x),
_cairo_fixed_from_double(point->y));
cairo_atsui_scaled_path_t *scaled_path = callback_data;
double x = point->x;
double y = point->y;
cairo_matrix_transform_point (scaled_path->scale, &x, &y);
_cairo_path_fixed_close_path (scaled_path->path);
_cairo_path_fixed_move_to (scaled_path->path,
_cairo_fixed_from_double (x),
_cairo_fixed_from_double (y));
return noErr;
}
@ -490,11 +584,15 @@ static OSStatus
_line_to (const Float32Point *point,
void *callback_data)
{
cairo_path_fixed_t *path = callback_data;
cairo_atsui_scaled_path_t *scaled_path = callback_data;
double x = point->x;
double y = point->y;
cairo_matrix_transform_point (scaled_path->scale, &x, &y);
_cairo_path_fixed_line_to (path,
_cairo_fixed_from_double(point->x),
_cairo_fixed_from_double(point->y));
_cairo_path_fixed_line_to (scaled_path->path,
_cairo_fixed_from_double (x),
_cairo_fixed_from_double (y));
return noErr;
}
@ -505,15 +603,25 @@ _curve_to (const Float32Point *point1,
const Float32Point *point3,
void *callback_data)
{
cairo_path_fixed_t *path = callback_data;
cairo_atsui_scaled_path_t *scaled_path = callback_data;
double x1 = point1->x;
double y1 = point1->y;
double x2 = point2->x;
double y2 = point2->y;
double x3 = point3->x;
double y3 = point3->y;
cairo_matrix_transform_point (scaled_path->scale, &x1, &y1);
cairo_matrix_transform_point (scaled_path->scale, &x2, &y2);
cairo_matrix_transform_point (scaled_path->scale, &x3, &y3);
_cairo_path_fixed_curve_to (path,
_cairo_fixed_from_double(point1->x),
_cairo_fixed_from_double(point1->y),
_cairo_fixed_from_double(point2->x),
_cairo_fixed_from_double(point2->y),
_cairo_fixed_from_double(point3->x),
_cairo_fixed_from_double(point3->y));
_cairo_path_fixed_curve_to (scaled_path->path,
_cairo_fixed_from_double (x1),
_cairo_fixed_from_double (y1),
_cairo_fixed_from_double (x2),
_cairo_fixed_from_double (y2),
_cairo_fixed_from_double (x3),
_cairo_fixed_from_double (y3));
return noErr;
}
@ -522,9 +630,9 @@ static OSStatus
_close_path (void *callback_data)
{
cairo_path_fixed_t *path = callback_data;
cairo_atsui_scaled_path_t *scaled_path = callback_data;
_cairo_path_fixed_close_path (path);
_cairo_path_fixed_close_path (scaled_path->path);
return noErr;
}
@ -537,13 +645,36 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
static ATSCubicLineToUPP lineProc = NULL;
static ATSCubicCurveToUPP curveProc = NULL;
static ATSCubicClosePathUPP closePathProc = NULL;
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
OSStatus err;
cairo_path_fixed_t *path;
path = _cairo_path_fixed_create ();
if (!path)
cairo_atsui_scaled_path_t scaled_path;
cairo_matrix_t *font_to_device = &scaled_font->base.scale;
cairo_matrix_t unscaled_font_to_device;
double xscale;
double yscale;
scaled_path.path = _cairo_path_fixed_create ();
if (!scaled_path.path)
return CAIRO_STATUS_NO_MEMORY;
if (theGlyph == kATSDeletedGlyphcode) {
_cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base,
scaled_path.path);
return CAIRO_STATUS_SUCCESS;
}
/* extract the rotation/shear component of the scale matrix. */
_cairo_matrix_compute_scale_factors (font_to_device, &xscale, &yscale, 1);
cairo_matrix_init (&unscaled_font_to_device,
font_to_device->xx,
font_to_device->yx,
font_to_device->xy,
font_to_device->yy, 0., 0.);
cairo_matrix_scale (&unscaled_font_to_device, 1.0/xscale, 1.0/yscale);
scaled_path.scale = &unscaled_font_to_device;
if (moveProc == NULL) {
moveProc = NewATSCubicMoveToUPP(_move_to);
lineProc = NewATSCubicLineToUPP(_line_to);
@ -552,13 +683,140 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
}
err = ATSUGlyphGetCubicPaths(scaled_font->style,
_cairo_scaled_glyph_index (scaled_glyph),
theGlyph,
moveProc,
lineProc,
curveProc,
closePathProc, (void *)path, &err);
closePathProc, (void *)&scaled_path, &err);
_cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, path);
_cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base,
scaled_path.path);
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
OSStatus err;
CGContextRef drawingContext;
cairo_image_surface_t *surface;
cairo_format_t format;
ATSFontRef atsFont;
CGFontRef cgFont;
cairo_scaled_font_t base = scaled_font->base;
cairo_font_extents_t extents = base.extents;
GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
ATSGlyphScreenMetrics metricsH;
double left, bottom, width, height;
double xscale, yscale;
CGRect bbox;
CGAffineTransform transform;
if (theGlyph == kATSDeletedGlyphcode) {
surface = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
if (!surface)
return CAIRO_STATUS_NO_MEMORY;
_cairo_scaled_glyph_set_surface (scaled_glyph,
&base,
surface);
return CAIRO_STATUS_SUCCESS;
}
/* Compute a box to contain the glyph mask. The vertical
* sizes come from the font extents; extra pixels are
* added to account for fractional sizes.
*/
height = extents.ascent + extents.descent + 2.0;
bottom = -extents.descent - 1.0;
/* Horizontal sizes come from the glyph typographic metrics.
* It is possible that this might result in clipped text
* in fonts where the typographic bounds don't cover the ink.
* The width is recalculated, since metricsH.width is rounded.
*/
err = ATSUGlyphGetScreenMetrics (scaled_font->style,
1, &theGlyph, 0, false,
false, &metricsH);
left = metricsH.sideBearing.x - 1.0;
width = metricsH.deviceAdvance.x
- metricsH.sideBearing.x
+ metricsH.otherSideBearing.x + 2.0;
/* The xy and yx components are negated because the y-axis
* is flipped into the cairo system then flipped back, ie:
* [1 0][xx yx][1 0]
* [0 -1][xy yy][0 -1]
*/
transform = CGAffineTransformMake (base.scale.xx,
-base.scale.yx,
-base.scale.xy,
base.scale.yy,
0., 0.);
_cairo_matrix_compute_scale_factors (&base.scale,
&xscale, &yscale, 1);
transform = CGAffineTransformScale (transform, 1.0/xscale, 1.0/yscale);
/* Rotate the bounding box. This computes the smallest CGRect
* that would contain the bounding box after rotation.
*/
bbox = CGRectApplyAffineTransform (CGRectMake (left, bottom,
width, height), transform);
/* Compute the smallest CGRect with integer coordinates
* that contains the bounding box.
*/
bbox = CGRectIntegral (bbox);
left = CGRectGetMinX (bbox);
bottom = CGRectGetMinY (bbox);
/* XXX should we select format based on antialiasing flags, as ft does? */
format = CAIRO_FORMAT_A8;
/* create the glyph mask surface */
surface = (cairo_image_surface_t *)cairo_image_surface_create (format, bbox.size.width, bbox.size.height);
if (!surface)
return CAIRO_STATUS_NO_MEMORY;
drawingContext = CGBitmapContextCreateWithCairoImageSurface (surface);
if (!drawingContext) {
cairo_surface_destroy ((cairo_surface_t *)surface);
return CAIRO_STATUS_NO_MEMORY;
}
atsFont = FMGetATSFontRefFromFont (scaled_font->fontID);
cgFont = CGFontCreateWithPlatformFont (&atsFont);
CGContextSetFont (drawingContext, cgFont);
if (base.options.antialias == CAIRO_ANTIALIAS_NONE) {
CGContextSetShouldAntialias (drawingContext, false);
}
/* solid white */
CGContextSetRGBFillColor (drawingContext, 1.0, 1.0, 1.0, 1.0);
CGContextSetFontSize (drawingContext, 1.0);
CGContextTranslateCTM (drawingContext, -left, -bottom);
CGContextScaleCTM (drawingContext, xscale, yscale);
CGContextSetTextMatrix (drawingContext, transform);
CGContextShowGlyphsAtPoint (drawingContext, 0, 0,
&theGlyph, 1);
CGContextRelease (drawingContext);
/* correct for difference between cairo and quartz
* coordinate systems.
*/
cairo_surface_set_device_offset ((cairo_surface_t *)surface, left,
-bbox.size.height - bottom);
_cairo_scaled_glyph_set_surface (scaled_glyph,
&base,
surface);
return CAIRO_STATUS_SUCCESS;
}
@ -583,6 +841,12 @@ _cairo_atsui_font_scaled_glyph_init (void *abstract_font,
return status;
}
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
status = _cairo_atsui_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
if (status)
return status;
}
return CAIRO_STATUS_SUCCESS;
}
@ -660,21 +924,23 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
int num_glyphs)
{
cairo_atsui_font_t *font = abstract_font;
CGContextRef myBitmapContext = 0, drawingContext;
CGColorSpaceRef colorSpace = 0;
CGContextRef drawingContext;
cairo_image_surface_t *destImageSurface;
int i, bits_per_comp, alpha;
int i;
void *extra = NULL;
cairo_bool_t can_draw_directly;
cairo_rectangle_int16_t rect;
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
ATSFontRef atsFont;
CGFontRef cgFont;
CGAffineTransform textTransform;
if (!_cairo_surface_is_quartz (generic_surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Check if we can draw directly to the destination surface */
can_draw_directly = _cairo_surface_is_quartz (generic_surface) &&
_cairo_pattern_is_opaque_solid (pattern) &&
can_draw_directly = _cairo_pattern_is_opaque_solid (pattern) &&
op == CAIRO_OPERATOR_OVER;
if (!can_draw_directly) {
@ -689,41 +955,12 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
&rect,
&extra);
/* Create a CGBitmapContext for the dest surface for drawing into */
if (destImageSurface->depth == 1) {
colorSpace = CGColorSpaceCreateDeviceGray();
bits_per_comp = 1;
alpha = kCGImageAlphaNone;
} else if (destImageSurface->depth == 8) {
colorSpace = CGColorSpaceCreateDeviceGray();
bits_per_comp = 8;
alpha = kCGImageAlphaNone;
} else if (destImageSurface->depth == 24) {
colorSpace = CGColorSpaceCreateDeviceRGB();
bits_per_comp = 8;
alpha = kCGImageAlphaNoneSkipFirst | CG_BITMAP_BYTE_ORDER_FLAG;
} else if (destImageSurface->depth == 32) {
colorSpace = CGColorSpaceCreateDeviceRGB();
bits_per_comp = 8;
alpha = kCGImageAlphaPremultipliedFirst | CG_BITMAP_BYTE_ORDER_FLAG;
} else {
// not reached
drawingContext = CGBitmapContextCreateWithCairoImageSurface (destImageSurface);
if (!drawingContext)
return CAIRO_INT_STATUS_UNSUPPORTED;
}
myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
destImageSurface->width,
destImageSurface->height,
bits_per_comp,
destImageSurface->stride,
colorSpace,
alpha);
CGColorSpaceRelease(colorSpace);
CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height);
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
drawingContext = myBitmapContext;
CGContextTranslateCTM(drawingContext, 0, destImageSurface->height);
CGContextScaleCTM(drawingContext, 1.0f, -1.0f);
} else {
drawingContext = ((cairo_quartz_surface_t *)generic_surface)->context;
CGContextSaveGState (drawingContext);
@ -756,38 +993,33 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f);
}
if (_cairo_surface_is_quartz (generic_surface)) {
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
if (surface->clip_region) {
pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
int num_boxes = pixman_region_num_rects (surface->clip_region);
CGRect stack_rects[10];
CGRect *rects;
int i;
/* XXX: Return-value of malloc needs to be checked for
* NULL. Can someone fix this who is more familiar with
* the cleanup needed in this function?
*/
if (num_boxes > 10)
rects = malloc (sizeof (CGRect) * num_boxes);
else
rects = stack_rects;
for (i = 0; i < num_boxes; i++) {
rects[i].origin.x = boxes[i].x1;
rects[i].origin.y = boxes[i].y1;
rects[i].size.width = boxes[i].x2 - boxes[i].x1;
rects[i].size.height = boxes[i].y2 - boxes[i].y1;
}
CGContextClipToRects (drawingContext, rects, num_boxes);
if (rects != stack_rects)
free(rects);
if (surface->clip_region) {
pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
int num_boxes = pixman_region_num_rects (surface->clip_region);
CGRect stack_rects[10];
CGRect *rects;
int i;
/* XXX: Return-value of malloc needs to be checked for
* NULL. Can someone fix this who is more familiar with
* the cleanup needed in this function?
*/
if (num_boxes > 10)
rects = malloc (sizeof (CGRect) * num_boxes);
else
rects = stack_rects;
for (i = 0; i < num_boxes; i++) {
rects[i].origin.x = boxes[i].x1;
rects[i].origin.y = boxes[i].y1;
rects[i].size.width = boxes[i].x2 - boxes[i].x1;
rects[i].size.height = boxes[i].y2 - boxes[i].y1;
}
} else {
/* XXX: Need to get the text clipped */
CGContextClipToRects (drawingContext, rects, num_boxes);
if (rects != stack_rects)
free(rects);
}
/* TODO - bold and italic text
@ -809,7 +1041,7 @@ _cairo_atsui_font_old_show_glyphs (void *abstract_font,
}
if (!can_draw_directly) {
CGContextRelease(myBitmapContext);
CGContextRelease(drawingContext);
_cairo_surface_release_dest_image(generic_surface,
&rect,

View file

@ -54,7 +54,7 @@ _cairo_cache_remove (cairo_cache_t *cache,
cairo_cache_entry_t *entry);
static void
_cairo_cache_shrink_to_accomodate (cairo_cache_t *cache,
_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
unsigned long additional);
static cairo_status_t
@ -215,7 +215,7 @@ _cairo_cache_thaw (cairo_cache_t *cache)
cache->freeze_count--;
if (cache->freeze_count == 0)
_cairo_cache_shrink_to_accomodate (cache, 0);
_cairo_cache_shrink_to_accommodate (cache, 0);
}
/**
@ -267,17 +267,17 @@ _cairo_cache_remove_random (cairo_cache_t *cache)
}
/**
* _cairo_cache_shrink_to_accomodate:
* _cairo_cache_shrink_to_accommodate:
* @cache: a cache
* @additional: additional size requested in bytes
*
* If cache is not frozen, eject entries randomly until the size of
* the cache is at least @additional bytes less than
* cache->max_size. That is, make enough room to accomodate a new
* cache->max_size. That is, make enough room to accommodate a new
* entry of size @additional.
**/
static void
_cairo_cache_shrink_to_accomodate (cairo_cache_t *cache,
_cairo_cache_shrink_to_accommodate (cairo_cache_t *cache,
unsigned long additional)
{
cairo_int_status_t status;
@ -313,7 +313,7 @@ _cairo_cache_insert (cairo_cache_t *cache,
{
cairo_status_t status;
_cairo_cache_shrink_to_accomodate (cache, entry->size);
_cairo_cache_shrink_to_accommodate (cache, entry->size);
status = _cairo_hash_table_insert (cache->hash_table,
(cairo_hash_entry_t *) entry);

View file

@ -127,6 +127,6 @@ _cairo_clip_translate (cairo_clip_t *clip,
cairo_fixed_t ty);
cairo_private cairo_rectangle_list_t*
_cairo_clip_copy_rectangles (cairo_clip_t *clip, cairo_gstate_t *gstate);
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate);
#endif /* CAIRO_CLIP_PRIVATE_H */

View file

@ -601,7 +601,7 @@ _cairo_clip_rect_to_user (cairo_gstate_t *gstate,
}
cairo_private cairo_rectangle_list_t*
_cairo_clip_copy_rectangles (cairo_clip_t *clip, cairo_gstate_t *gstate)
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
{
cairo_rectangle_list_t *list;
cairo_rectangle_t *rectangles;

142
src/cairo-deflate-stream.c Normal file
View file

@ -0,0 +1,142 @@
/* cairo_deflate_stream.c: Output stream abstraction
*
* Copyright © 2006 Adrian Johnson
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
* The Original Code is cairo_output_stream.c as distributed with the
* cairo graphics library.
*
* The Initial Developer of the Original Code is Adrian Johnson.
*
* Author(s):
* Adrian Johnson <ajohnson@redneon.com>
*/
#include "cairoint.h"
#include "cairo-output-stream-private.h"
#include <zlib.h>
#define BUFFER_SIZE 16384
typedef struct _cairo_deflate_stream {
cairo_output_stream_t base;
cairo_output_stream_t *output;
z_stream zlib_stream;
unsigned char input_buf[BUFFER_SIZE];
unsigned char output_buf[BUFFER_SIZE];
} cairo_deflate_stream_t;
static void
cairo_deflate_stream_deflate (cairo_deflate_stream_t *stream, cairo_bool_t flush)
{
int ret;
cairo_bool_t finished;
do {
ret = deflate (&stream->zlib_stream, flush ? Z_FINISH : Z_NO_FLUSH);
if (flush || stream->zlib_stream.avail_out == 0)
{
_cairo_output_stream_write (stream->output,
stream->output_buf,
BUFFER_SIZE - stream->zlib_stream.avail_out);
stream->zlib_stream.next_out = stream->output_buf;
stream->zlib_stream.avail_out = BUFFER_SIZE;
}
finished = TRUE;
if (stream->zlib_stream.avail_in != 0)
finished = FALSE;
if (flush && ret != Z_STREAM_END)
finished = FALSE;
} while (!finished);
stream->zlib_stream.next_in = stream->input_buf;
}
static cairo_status_t
_cairo_deflate_stream_write (cairo_output_stream_t *base,
const unsigned char *data,
unsigned int length)
{
cairo_deflate_stream_t *stream = (cairo_deflate_stream_t *) base;
unsigned int count;
const unsigned char *p = data;
while (length) {
count = length;
if (count > BUFFER_SIZE - stream->zlib_stream.avail_in)
count = BUFFER_SIZE - stream->zlib_stream.avail_in;
memcpy (stream->input_buf + stream->zlib_stream.avail_in, p, count);
p += count;
stream->zlib_stream.avail_in += count;
length -= count;
if (stream->zlib_stream.avail_in == BUFFER_SIZE)
cairo_deflate_stream_deflate (stream, FALSE);
}
return _cairo_output_stream_get_status (stream->output);
}
static cairo_status_t
_cairo_deflate_stream_close (cairo_output_stream_t *base)
{
cairo_deflate_stream_t *stream = (cairo_deflate_stream_t *) base;
cairo_deflate_stream_deflate (stream, TRUE);
deflateEnd (&stream->zlib_stream);
return _cairo_output_stream_get_status (stream->output);
}
cairo_output_stream_t *
_cairo_deflate_stream_create (cairo_output_stream_t *output)
{
cairo_deflate_stream_t *stream;
stream = malloc (sizeof (cairo_deflate_stream_t));
if (stream == NULL)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
_cairo_output_stream_init (&stream->base,
_cairo_deflate_stream_write,
_cairo_deflate_stream_close);
stream->output = output;
stream->zlib_stream.zalloc = Z_NULL;
stream->zlib_stream.zfree = Z_NULL;
stream->zlib_stream.opaque = Z_NULL;
if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
return (cairo_output_stream_t *) &cairo_output_stream_nil;
stream->zlib_stream.next_in = stream->input_buf;
stream->zlib_stream.avail_in = 0;
stream->zlib_stream.next_out = stream->output_buf;
stream->zlib_stream.avail_out = BUFFER_SIZE;
return &stream->base;
}

View file

@ -47,7 +47,7 @@ static const cairo_font_options_t cairo_font_options_nil = {
* _cairo_font_options_init_default:
* @options: a #cairo_font_options_t
*
* Initializes all fileds of the font options object to default values.
* Initializes all fields of the font options object to default values.
**/
void
_cairo_font_options_init_default (cairo_font_options_t *options)
@ -233,7 +233,7 @@ slim_hidden_def (cairo_font_options_hash);
* @options: a #cairo_font_options_t
* @antialias: the new antialiasing mode
*
* Sets the antiliasing mode for the font options object. This
* Sets the antialiasing mode for the font options object. This
* specifies the type of antialiasing to do when rendering text.
**/
void
@ -251,7 +251,7 @@ slim_hidden_def (cairo_font_options_set_antialias);
* cairo_font_options_get_antialias:
* @options: a #cairo_font_options_t
*
* Gets the antialising mode for the font options object.
* Gets the antialiasing mode for the font options object.
*
* Return value: the antialiasing mode
**/

View file

@ -135,7 +135,7 @@ static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
/*
* We maintain a hash table to map file/id => cairo_ft_unscaled_font_t.
* The hash table itself isn't limited in size. However, we limit the
* number of FT_Face objects we keep around; when we've exceeeded that
* number of FT_Face objects we keep around; when we've exceeded that
* limit and need to create a new FT_Face, we dump the FT_Face from a
* random cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
* there are any).
@ -2165,7 +2165,7 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
* @pattern: an existing #FcPattern
*
* Add options to a #FcPattern based on a #cairo_font_options_t font
* options object. Options that are already in the pattern, are not overriden,
* options object. Options that are already in the pattern, are not overridden,
* so you should call this function after calling FcConfigSubstitute() (the
* user's settings should override options based on the surface type), but
* before calling FcDefaultSubstitute().
@ -2272,7 +2272,7 @@ slim_hidden_def (cairo_ft_font_options_substitute);
* also for the FreeType backend and can be used with functions such
* as cairo_ft_font_lock_face().
*
* Font rendering options are representated both here and when you
* Font rendering options are represented both here and when you
* call cairo_scaled_font_create(). Font options that have a representation
* in a #FcPattern must be passed in here; to modify #FcPattern
* appropriately to reflect the options in a #cairo_font_options_t, call

View file

@ -1684,8 +1684,8 @@ static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = {
#define GLYPH_CACHE_TEXTURE_SIZE 512
#define GLYPH_CACHE_MAX_LEVEL 64
#define GLYPH_CACHE_MAX_HEIGHT 72
#define GLYPH_CACHE_MAX_WIDTH 72
#define GLYPH_CACHE_MAX_HEIGHT 96
#define GLYPH_CACHE_MAX_WIDTH 96
#define WRITE_VEC2(ptr, _x, _y) \
*(ptr)++ = (_x); \
@ -2072,6 +2072,11 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
if (status)
goto UNLOCK;
x_offset = scaled_glyphs[i]->surface->base.device_transform.x0;
y_offset = scaled_glyphs[i]->surface->base.device_transform.y0;
x1 = _cairo_lround (glyphs[i].x) + x_offset;
y1 = _cairo_lround (glyphs[i].y) + y_offset;
glitz_composite (_glitz_operator (op),
src->surface,
clone->surface,

View file

@ -323,7 +323,7 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
* _cairo_gstate_is_redirected
* @gstate: a #cairo_gstate_t
*
* Return value: TRUE if the gstate is redirected to a traget
* Return value: TRUE if the gstate is redirected to a target
* different than the original, FALSE otherwise.
**/
cairo_bool_t
@ -1177,9 +1177,9 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
}
cairo_rectangle_list_t*
_cairo_gstate_copy_clip_rectangles (cairo_gstate_t *gstate)
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
{
return _cairo_clip_copy_rectangles (&gstate->clip, gstate);
return _cairo_clip_copy_rectangle_list (&gstate->clip, gstate);
}
static void
@ -1327,7 +1327,7 @@ _cairo_gstate_get_font_face (cairo_gstate_t *gstate,
*
* We pass this to the font when making requests of it, which causes it to
* reply for a particular [user request, device] combination, under the CTM
* (to accomodate the "zoom in" == "bigger fonts" issue above).
* (to accommodate the "zoom in" == "bigger fonts" issue above).
*
* The other terms in our communication with the font are therefore in
* device space. When we ask it to perform text->glyph conversion, it will

View file

@ -347,8 +347,8 @@ _cairo_image_surface_create_with_content (cairo_content_t content,
* Creates an image surface for the provided pixel data. The output
* buffer must be kept around until the #cairo_surface_t is destroyed
* or cairo_surface_finish() is called on the surface. The initial
* contents of @buffer will be used as the inital image contents; you
* must explicitely clear the buffer, using, for example,
* contents of @buffer will be used as the initial image contents; you
* must explicitly clear the buffer, using, for example,
* cairo_rectangle() and cairo_fill() if you want it cleared.
*
* Return value: a pointer to the newly created surface. The caller

View file

@ -230,7 +230,7 @@ _lzw_symbol_table_init (lzw_symbol_table_t *table)
/* Lookup a symbol in the symbol table. The PREV and NEXT fields of
* symbol form the key for the lookup.
*
* If succesful, then this function returns TRUE and slot_ret will be
* If successful, then this function returns TRUE and slot_ret will be
* left pointing at the result that will have the CODE field of
* interest.
*

View file

@ -102,7 +102,7 @@ slim_hidden_def(cairo_matrix_init);
* @x0: location to store x0 (X-translation component) of matrix, or %NULL
* @y0: location to store y0 (Y-translation component) of matrix, or %NULL
*
* Gets the matrix values for the affine tranformation that @matrix represents.
* Gets the matrix values for the affine transformation that @matrix represents.
* See cairo_matrix_init().
*
*

View file

@ -46,7 +46,7 @@
* the meta surface had instead been applied to the target surface.
*
* The recording phase of the meta surface is careful to snapshot all
* necessary objects (paths, patterns, etc.), in order to acheive
* necessary objects (paths, patterns, etc.), in order to achieve
* accurate replay. The efficiency of the meta surface could be
* improved by improving the implementation of snapshot for the
* various objects. For example, it would be nice to have a

View file

@ -548,6 +548,29 @@ SurfacePatternDrawFunc (void *info, CGContextRef context)
cairo_surface_destroy ((cairo_surface_t*) quartz_surf);
}
/* Borrowed from cairo-meta-surface */
static cairo_status_t
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
_cairo_pattern_init_copy (pattern, other);
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern =
(cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;
surface_pattern->surface = _cairo_surface_snapshot (surface);
cairo_surface_destroy (surface);
if (surface_pattern->surface->status)
return surface_pattern->surface->status;
}
return CAIRO_STATUS_SUCCESS;
}
static CGPatternRef
_cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (cairo_nquartz_surface_t *dest,
cairo_pattern_t *abspat)
@ -564,6 +587,9 @@ _cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (cairo_nquartz_surface_
CGPatternRef cgpat;
float rw, rh;
cairo_pattern_union_t *snap_pattern = NULL;
cairo_pattern_t *target_pattern = abspat;
/* SURFACE is the only type we'll handle here */
if (abspat->type != CAIRO_PATTERN_TYPE_SURFACE)
return NULL;
@ -628,8 +654,18 @@ _cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (cairo_nquartz_surface_
rh = extents.height;
#endif
cairo_pattern_reference (abspat);
cgpat = CGPatternCreate (abspat,
/* XXX fixme: only do snapshots if the context is for printing, or get rid of the
other block if it doesn't fafect performance */
if (1 /* context is for printing */) {
snap_pattern = (cairo_pattern_union_t*) malloc(sizeof(cairo_pattern_union_t));
target_pattern = (cairo_pattern_t*) snap_pattern;
_init_pattern_with_snapshot (snap_pattern, abspat);
} else {
cairo_pattern_reference (abspat);
target_pattern = abspat;
}
cgpat = CGPatternCreate (target_pattern,
pbounds,
ptransform,
rw, rh,
@ -672,7 +708,7 @@ _cairo_nquartz_setup_source (cairo_nquartz_surface_t *surface,
{
CGShadingRef shading = _cairo_nquartz_cairo_gradient_pattern_to_quartz (source);
if (!shading)
return CAIRO_INT_STATUS_UNSUPPORTED;
return DO_UNSUPPORTED;
surface->sourceShading = shading;
@ -680,7 +716,7 @@ _cairo_nquartz_setup_source (cairo_nquartz_surface_t *surface,
} else if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
CGPatternRef pattern = _cairo_nquartz_cairo_repeating_surface_pattern_to_quartz (surface, source);
if (!pattern)
return CAIRO_INT_STATUS_UNSUPPORTED;
return DO_UNSUPPORTED;
float patternAlpha = 1.0f;
@ -692,6 +728,8 @@ _cairo_nquartz_setup_source (cairo_nquartz_surface_t *surface,
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetFillColorSpace (surface->cgContext, patternSpace);
CGContextSetFillPattern (surface->cgContext, pattern, &patternAlpha);
CGContextSetStrokeColorSpace (surface->cgContext, patternSpace);
CGContextSetStrokePattern (surface->cgContext, pattern, &patternAlpha);
CGColorSpaceRelease (patternSpace);
/* Quartz likes to munge the pattern phase (as yet unexplained
@ -1247,7 +1285,9 @@ _cairo_nquartz_surface_stroke (void *abstract_surface,
CGContextSaveGState (surface->cgContext);
CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
// Turning antialiasing off causes misrendering with
// single-pixel lines (e.g. 20,10.5 -> 21,10.5 end up being rendered as 2 pixels)
//CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
CGContextSetLineWidth (surface->cgContext, style->line_width);
CGContextSetLineCap (surface->cgContext, _cairo_nquartz_cairo_line_cap_to_quartz (style->line_cap));
CGContextSetLineJoin (surface->cgContext, _cairo_nquartz_cairo_line_join_to_quartz (style->line_join));
@ -1294,6 +1334,8 @@ _cairo_nquartz_surface_stroke (void *abstract_surface,
rv = CAIRO_INT_STATUS_UNSUPPORTED;
}
_cairo_nquartz_teardown_source (surface, source);
CGContextRestoreGState (surface->cgContext);
ND((stderr, "-- stroke\n"));
@ -1363,8 +1405,16 @@ _cairo_nquartz_surface_show_glyphs (void *abstract_surface,
CGContextSetFontSize (surface->cgContext, 1.0);
// XXXtodo/perf: stack storage for glyphs/sizes
CGGlyph *cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs);
CGSize *cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs);
#define STATIC_BUF_SIZE 64
CGGlyph glyphs_static[STATIC_BUF_SIZE];
CGSize cg_advances_static[STATIC_BUF_SIZE];
CGGlyph *cg_glyphs = &glyphs_static[0];
CGSize *cg_advances = &cg_advances_static[0];
if (num_glyphs > STATIC_BUF_SIZE) {
cg_glyphs = (CGGlyph*) malloc(sizeof(CGGlyph) * num_glyphs);
cg_advances = (CGSize*) malloc(sizeof(CGSize) * num_glyphs);
}
double xprev = glyphs[0].x;
double yprev = glyphs[0].y;
@ -1392,8 +1442,10 @@ _cairo_nquartz_surface_show_glyphs (void *abstract_surface,
cg_advances,
num_glyphs);
free (cg_glyphs);
free (cg_advances);
if (cg_glyphs != &glyphs_static[0]) {
free (cg_glyphs);
free (cg_advances);
}
if (action == DO_SHADING)
CGContextDrawShading (surface->cgContext, surface->sourceShading);
@ -1422,10 +1474,13 @@ _cairo_nquartz_surface_mask (void *abstract_surface,
CGContextSetAlpha (surface->cgContext, solid_mask->color.alpha);
} else {
/* So, CGContextClipToMask is not present in 10.3.9, so we're doomed; we could
* do fallback, if we implemented _composite, but for now let's just not support
* this. (But pretend we did.)
/* So, CGContextClipToMask is not present in 10.3.9, so we're
* doomed; if we have imageData, we can do fallback, otherwise
* just pretend success.
*/
if (surface->imageData)
return CAIRO_INT_STATUS_UNSUPPORTED;
return CAIRO_STATUS_SUCCESS;
}
@ -1646,7 +1701,7 @@ cairo_nquartz_surface_create (cairo_format_t format,
if (width % 4 == 0)
stride = width;
else
stride = (width & 3) + 1;
stride = (width & ~3) + 4;
bitinfo = kCGImageAlphaNone;
bitsPerComponent = 8;
} else if (format == CAIRO_FORMAT_A1) {

View file

@ -251,7 +251,7 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
PRECTL prcl_begin_paint_rect)
{
POINTL aptlPoints[4];
LONG lOldYInversion;
LONG lOldYInversion, rc = GPI_OK;
/* Enable Y Inversion for the HPS, so the
* GpiDrawBits will work with upside-top image, not with upside-down image!
@ -312,13 +312,63 @@ _cairo_os2_surface_blit_pixels (cairo_os2_surface_t *surface,
}
}
#endif
GpiDrawBits (hps_begin_paint,
surface->pixels,
&(surface->bitmap_info),
4,
aptlPoints,
ROP_SRCCOPY,
BBO_IGNORE);
rc = GpiDrawBits (hps_begin_paint,
surface->pixels,
&(surface->bitmap_info),
4,
aptlPoints,
ROP_SRCCOPY,
BBO_IGNORE);
if (rc != GPI_OK) {
/* if GpiDrawBits () failed then this is most likely because the
* display driver could not handle a 32bit bitmap. So we need to
* - create a buffer that only contains 3 bytes per pixel
* - change the bitmap info header to contain 24bit
* - pass the new buffer to GpiDrawBits () again
* - clean up the new buffer
*/
BITMAPINFOHEADER2 bmpheader;
unsigned char *pchPixBuf, *pchPixSource;
void *pBufStart;
ULONG ulPixels;
/* allocate temporary pixel buffer */
pchPixBuf = (unsigned char *) malloc (3 * surface->bitmap_info.cx *
surface->bitmap_info.cy);
pchPixSource = surface->pixels; /* start at beginning of pixel buffer */
pBufStart = pchPixBuf; /* remember beginning of the new pixel buffer */
/* copy the first three bytes for each pixel but skip over the fourth */
for (ulPixels = 0; ulPixels < surface->bitmap_info.cx * surface->bitmap_info.cy; ulPixels++)
{
/* copy BGR from source buffer */
*pchPixBuf++ = *pchPixSource++;
*pchPixBuf++ = *pchPixSource++;
*pchPixBuf++ = *pchPixSource++;
pchPixSource++; /* jump over alpha channel in source buffer */
}
/* jump back to start of the buffer for display and cleanup */
pchPixBuf = pBufStart;
/* set up the bitmap header, but this time with 24bit depth only */
memset (&bmpheader, 0, sizeof (bmpheader));
bmpheader.cbFix = sizeof (BITMAPINFOHEADER2);
bmpheader.cx = surface->bitmap_info.cx;
bmpheader.cy = surface->bitmap_info.cy;
bmpheader.cPlanes = surface->bitmap_info.cPlanes;
bmpheader.cBitCount = 24;
rc = GpiDrawBits (hps_begin_paint,
pchPixBuf,
(PBITMAPINFO2)&bmpheader,
4,
aptlPoints,
ROP_SRCCOPY,
BBO_IGNORE);
free (pchPixBuf);
}
/* Restore Y inversion */
GpiEnableYInversion (hps_begin_paint, lOldYInversion);
@ -372,7 +422,7 @@ _cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface,
hps = GpiCreatePS (hab,
hdc,
&sizlTemp,
PU_PELS | GPIT_NORMAL | GPIA_ASSOC );
PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
if (!hps) {
DevCloseDC (hdc);
return;
@ -405,7 +455,7 @@ _cairo_os2_surface_get_pixels_from_screen (cairo_os2_surface_t *surface,
/* Target coordinates (Noninclusive) */
aptlPoints[0].x = 0;
aptlPoints[0].y = 0;
aptlPoints[1].x = sizlTemp.cx;
aptlPoints[1].y = sizlTemp.cy;

View file

@ -159,4 +159,8 @@ _cairo_memory_stream_length (cairo_output_stream_t *stream);
cairo_private cairo_output_stream_t *
_cairo_base85_stream_create (cairo_output_stream_t *output);
/* cairo_deflate_stream.c */
cairo_private cairo_output_stream_t *
_cairo_deflate_stream_create (cairo_output_stream_t *output);
#endif /* CAIRO_OUTPUT_STREAM_PRIVATE_H */

View file

@ -187,9 +187,19 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
point.x = x;
point.y = y;
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
if (status)
return status;
/* If the previous op was also a MOVE_TO, then just change its
* point rather than adding a new op. */
if (path->op_buf_tail && path->op_buf_tail->num_ops &&
path->op_buf_tail->op[path->op_buf_tail->num_ops - 1] == CAIRO_PATH_OP_MOVE_TO)
{
cairo_point_t *last_move_to_point;
last_move_to_point = &path->arg_buf_tail->points[path->arg_buf_tail->num_points - 1];
*last_move_to_point = point;
} else {
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
if (status)
return status;
}
path->current_point = point;
path->has_current_point = TRUE;

View file

@ -848,7 +848,7 @@ _cairo_stroker_curve_to (void *closure,
}
/* We're using two different algorithms here for dashed and un-dashed
* splines. The dashed alogorithm uses the existing line dashing
* splines. The dashed algorithm uses the existing line dashing
* code. It's linear in path length, but gets subtly wrong results for
* self-intersecting paths (an outstanding but for self-intersecting
* non-curved paths as well). The non-dashed algorithm tessellates a
@ -856,7 +856,7 @@ _cairo_stroker_curve_to (void *closure,
* self-intersecting problem, but it's (unsurprisingly) not O(n) and
* more significantly, it doesn't yet handle dashes.
*
* The only reason we're doing split algortihms here is to
* The only reason we're doing split algorithms here is to
* minimize the impact of fixing the splines-aren't-dashed bug for
* 1.0.2. Long-term the right answer is to rewrite the whole pile
* of stroking code so that the entire result is computed as a

View file

@ -285,7 +285,7 @@ _cairo_pattern_create_in_error (cairo_status_t status)
* If the values passed in are outside that range, they will be
* clamped.
*
* Return value: the newly created #cairo_pattern_t if succesful, or
* Return value: the newly created #cairo_pattern_t if successful, or
* an error pattern in case of no memory. The caller owns the
* returned object and should call cairo_pattern_destroy() when
* finished with it.
@ -326,7 +326,7 @@ slim_hidden_def (cairo_pattern_create_rgb);
* 1. If the values passed in are outside that range, they will be
* clamped.
*
* Return value: the newly created #cairo_pattern_t if succesful, or
* Return value: the newly created #cairo_pattern_t if successful, or
* an error pattern in case of no memory. The caller owns the
* returned object and should call cairo_pattern_destroy() when
* finished with it.
@ -363,7 +363,7 @@ slim_hidden_def (cairo_pattern_create_rgba);
*
* Create a new cairo_pattern_t for the given surface.
*
* Return value: the newly created #cairo_pattern_t if succesful, or
* Return value: the newly created #cairo_pattern_t if successful, or
* an error pattern in case of no memory. The caller owns the
* returned object and should call cairo_pattern_destroy() when
* finished with it.
@ -412,7 +412,7 @@ slim_hidden_def (cairo_pattern_create_for_surface);
* pattern space is identical to user space, but the relationship
* between the spaces can be changed with cairo_pattern_set_matrix().
*
* Return value: the newly created #cairo_pattern_t if succesful, or
* Return value: the newly created #cairo_pattern_t if successful, or
* an error pattern in case of no memory. The caller owns the
* returned object and should call cairo_pattern_destroy() when
* finished with it.
@ -456,7 +456,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
* pattern space is identical to user space, but the relationship
* between the spaces can be changed with cairo_pattern_set_matrix().
*
* Return value: the newly created #cairo_pattern_t if succesful, or
* Return value: the newly created #cairo_pattern_t if successful, or
* an error pattern in case of no memory. The caller owns the
* returned object and should call cairo_pattern_destroy() when
* finished with it.

View file

@ -71,7 +71,7 @@
* using a tiling pattern (4.6.2). How do you create such a scratch
* surface? cairo_surface_create_similar() ?
*
* - What if you create a similiar surface and does show_page and then
* - What if you create a similar surface and does show_page and then
* does show_surface on another surface?
*
* - Output TM so page scales to the right size - PDF default user
@ -129,6 +129,8 @@ typedef struct _cairo_pdf_surface {
cairo_pdf_resource_t self;
cairo_pdf_resource_t length;
long start_offset;
cairo_bool_t compressed;
cairo_output_stream_t *old_output;
} current_stream;
cairo_bool_t has_clip;
@ -146,8 +148,9 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
static cairo_pdf_resource_t
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
cairo_bool_t compressed,
const char *fmt,
...) CAIRO_PRINTF_FORMAT(2, 3);
...) CAIRO_PRINTF_FORMAT(3, 4);
static void
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
@ -456,6 +459,7 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface)
static cairo_pdf_resource_t
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
cairo_bool_t compressed,
const char *fmt,
...)
{
@ -464,12 +468,16 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
surface->current_stream.active = TRUE;
surface->current_stream.self = _cairo_pdf_surface_new_object (surface);
surface->current_stream.length = _cairo_pdf_surface_new_object (surface);
surface->current_stream.compressed = compressed;
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
"<< /Length %d 0 R\r\n",
surface->current_stream.self.id,
surface->current_stream.length.id);
if (compressed)
_cairo_output_stream_printf (surface->output,
" /Filter /FlateDecode\r\n");
if (fmt != NULL) {
va_start (ap, fmt);
@ -483,6 +491,11 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
surface->current_stream.start_offset = _cairo_output_stream_get_position (surface->output);
if (compressed) {
surface->current_stream.old_output = surface->output;
surface->output = _cairo_deflate_stream_create (surface->output);
}
return surface->current_stream.self;
}
@ -494,6 +507,13 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
if (! surface->current_stream.active)
return;
if (surface->current_stream.compressed) {
_cairo_output_stream_destroy (surface->output);
surface->output = surface->current_stream.old_output;
_cairo_output_stream_printf (surface->output,
"\r\n");
}
length = _cairo_output_stream_get_position (surface->output) -
surface->current_stream.start_offset;
_cairo_output_stream_printf (surface->output,
@ -577,6 +597,7 @@ _cairo_pdf_surface_resume_content_stream (cairo_pdf_surface_t *surface)
cairo_pdf_resource_t stream;
stream = _cairo_pdf_surface_open_stream (surface,
TRUE,
" /Type /XObject\r\n"
" /Subtype /Form\r\n"
" /BBox [ 0 0 %f %f ]\r\n",
@ -593,6 +614,7 @@ _cairo_pdf_surface_start_page (void *abstract_surface)
cairo_pdf_resource_t stream;
stream = _cairo_pdf_surface_open_stream (surface,
TRUE,
" /Type /XObject\r\n"
" /Subtype /Form\r\n"
" /BBox [ 0 0 %f %f ]\r\n",
@ -626,7 +648,7 @@ compress_dup (const void *data, unsigned long data_size,
}
/* Emit alpha channel from the image into the given data, providing
* and id that can be used to reference the resulting SMask object.
* an id that can be used to reference the resulting SMask object.
*
* In the case that the alpha channel happens to be all opaque, then
* no SMask object will be emitted and *id_ret will be set to 0.
@ -680,6 +702,7 @@ emit_smask (cairo_pdf_surface_t *surface,
}
*stream_ret = _cairo_pdf_surface_open_stream (surface,
FALSE,
" /Type /XObject\r\n"
" /Subtype /Image\r\n"
" /Width %d\r\n"
@ -789,12 +812,14 @@ emit_image (cairo_pdf_surface_t *surface,
if (need_smask)
*image_ret = _cairo_pdf_surface_open_stream (surface,
FALSE,
IMAGE_DICTIONARY
" /SMask %d 0 R\r\n",
image->width, image->height,
smask.id);
else
*image_ret = _cairo_pdf_surface_open_stream (surface,
FALSE,
IMAGE_DICTIONARY,
image->width, image->height);
@ -865,16 +890,40 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
_cairo_surface_get_extents (&surface->base, &surface_extents);
/* In PDF, (as far as I can tell), all patterns are repeating. So
* we support cairo's EXTEND_NONE semantics by setting the repeat
* step size to the larger of the image size and the extents of
* the destination surface. That way we guarantee the pattern will
* not repeat.
*/
switch (extend) {
case CAIRO_EXTEND_NONE:
xstep = MAX(image->width, surface_extents.width);
ystep = MAX(image->height, surface_extents.height);
{
/* In PDF, (as far as I can tell), all patterns are
* repeating. So we support cairo's EXTEND_NONE semantics
* by setting the repeat step size to a size large enough
* to guarantee that no more than a single occurrence will
* be visible.
*
* First, map the pattern's extents through the inverse
* pattern matrix to compute the device-space bounds of
* the desired single occurrence. Then consider the bounds
* of (the union of this rectangle with the target surface
* extents). If the repeat size is larger than the
* diagonal of the bounds of the union, then it is
* guaranteed to never repeat visibly.
*/
double x1 = 0.0, y1 = 0.0;
double x2 = image->width, y2 = image->height;
cairo_matrix_t surface_to_device = pattern->base.matrix;
cairo_matrix_invert (&surface_to_device);
_cairo_matrix_transform_bounding_box (&surface_to_device,
&x1, &y1, &x2, &y2,
NULL);
/* Rather than computing precise bounds of the union, just
* add the surface extents unconditionally. We only
* required an answer that's large enough, we don't really
* care if it's not as tight as possible. */
x1 = MAX (fabs(x1), fabs(x2)) + surface_extents.width;
y1 = MAX (fabs(y1), fabs(y2)) + surface_extents.height;
/* Similarly, don't bother computing the square root to
* determine the length of the final diagonal. */
xstep = ystep = _cairo_lround (ceil (x1 + y1));
}
break;
case CAIRO_EXTEND_REPEAT:
xstep = image->width;
@ -928,6 +977,7 @@ emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_matrix_scale (&pdf_p2d, 1.0, -1.0);
stream = _cairo_pdf_surface_open_stream (surface,
FALSE,
" /BBox [0 0 %d %d]\r\n"
" /XStep %d\r\n"
" /YStep %d\r\n"
@ -1006,7 +1056,7 @@ emit_linear_colorgradient (cairo_pdf_surface_t *surface,
}
static cairo_pdf_resource_t
emit_stiched_colorgradient (cairo_pdf_surface_t *surface,
emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
unsigned int n_stops,
cairo_pdf_color_stop_t stops[])
{
@ -1020,7 +1070,7 @@ emit_stiched_colorgradient (cairo_pdf_surface_t *surface,
&stops[i+1]);
}
/* ... and stich them together */
/* ... and stitch them together */
function = _cairo_pdf_surface_new_object (surface);
_cairo_output_stream_printf (surface->output,
"%d 0 obj\r\n"
@ -1065,7 +1115,7 @@ emit_stiched_colorgradient (cairo_pdf_surface_t *surface,
return function;
}
#define COLOR_STOP_EPSILLON 1e-6
#define COLOR_STOP_EPSILON 1e-6
static cairo_pdf_resource_t
emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *pattern)
@ -1095,13 +1145,13 @@ emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *patt
/* make sure first offset is 0.0 and last offset is 1.0. (Otherwise Acrobat
* Reader chokes.) */
if (stops[0].offset > COLOR_STOP_EPSILLON) {
if (stops[0].offset > COLOR_STOP_EPSILON) {
memcpy (allstops, stops, sizeof (cairo_pdf_color_stop_t));
stops = allstops;
stops[0].offset = 0.0;
n_stops++;
}
if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILLON) {
if (stops[n_stops-1].offset < 1.0 - COLOR_STOP_EPSILON) {
memcpy (&stops[n_stops],
&stops[n_stops - 1],
sizeof (cairo_pdf_color_stop_t));
@ -1110,12 +1160,12 @@ emit_pattern_stops (cairo_pdf_surface_t *surface, cairo_gradient_pattern_t *patt
}
if (n_stops == 2) {
/* no need for stiched function */
/* no need for stitched function */
function = emit_linear_colorgradient (surface, &stops[0], &stops[1]);
} else {
/* multiple stops: stich. XXX possible optimization: regulary spaced
* stops do not require stiching. XXX */
function = emit_stiched_colorgradient (surface,
/* multiple stops: stitch. XXX possible optimization: regulary spaced
* stops do not require stitching. XXX */
function = emit_stitched_colorgradient (surface,
n_stops,
stops);
}
@ -1942,7 +1992,7 @@ _cairo_pdf_surface_emit_outline_glyph (cairo_pdf_surface_t *surface,
if (status)
return status;
*glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL);
*glyph_ret = _cairo_pdf_surface_open_stream (surface, FALSE, NULL);
_cairo_output_stream_printf (surface->output,
"0 0 %f %f %f %f d1\r\n",
@ -1980,7 +2030,7 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
cairo_status_t status;
cairo_image_surface_t *image;
unsigned char *row, *byte;
int rows, cols, bytes_per_row;
int rows, cols;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph_index,
@ -1997,7 +2047,7 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
return cairo_surface_status (&image->base);
}
*glyph_ret = _cairo_pdf_surface_open_stream (surface, NULL);
*glyph_ret = _cairo_pdf_surface_open_stream (surface, FALSE, NULL);
_cairo_output_stream_printf (surface->output,
"0 0 %f %f %f %f d1\r\n",
@ -2025,7 +2075,6 @@ _cairo_pdf_surface_emit_bitmap_glyph (cairo_pdf_surface_t *surface,
_cairo_output_stream_printf (surface->output,
"ID ");
bytes_per_row = (image->width + 7) / 8;
for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
@ -2727,6 +2776,7 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
cairo_pdf_surface_t *surface = abstract_surface;
unsigned int current_subset_id = (unsigned int)-1;
unsigned int font_id, subset_id, subset_glyph_index;
cairo_bool_t diagonal;
cairo_status_t status;
int i;
@ -2742,6 +2792,12 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
_cairo_output_stream_printf (surface->output,
"BT\r\n");
if (scaled_font->scale.xy == 0.0 &&
scaled_font->scale.yx == 0.0)
diagonal = TRUE;
else
diagonal = FALSE;
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets,
scaled_font, glyphs[i].index,
@ -2749,22 +2805,29 @@ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
if (status)
return status;
if (subset_id != current_subset_id) {
if (subset_id != current_subset_id)
_cairo_output_stream_printf (surface->output,
"/CairoFont-%d-%d 1 Tf\r\n",
font_id, subset_id);
current_subset_id = subset_id;
}
_cairo_output_stream_printf (surface->output,
"%f %f %f %f %f %f Tm <%02x> Tj\r\n",
scaled_font->scale.xx,
scaled_font->scale.yx,
-scaled_font->scale.xy,
-scaled_font->scale.yy,
glyphs[i].x,
glyphs[i].y,
subset_glyph_index);
if (subset_id != current_subset_id || !diagonal) {
_cairo_output_stream_printf (surface->output,
"%f %f %f %f %f %f Tm <%02x> Tj\r\n",
scaled_font->scale.xx,
scaled_font->scale.yx,
-scaled_font->scale.xy,
-scaled_font->scale.yy,
glyphs[i].x,
glyphs[i].y,
subset_glyph_index);
current_subset_id = subset_id;
} else {
_cairo_output_stream_printf (surface->output,
"%f %f Td <%02x> Tj\r\n",
(glyphs[i].x - glyphs[i-1].x)/scaled_font->scale.xx,
(glyphs[i].y - glyphs[i-1].y)/scaled_font->scale.yy,
subset_glyph_index);
}
}
_cairo_output_stream_printf (surface->output,

View file

@ -89,7 +89,7 @@ typedef struct cairo_ps_surface {
/* A word wrap stream can be used as a filter to do word wrapping on
* top of an existing output stream. The word wrapping is quite
* simple, using isspace to determine characters that separate
* words. Any word that will cause the column count exceeed the given
* words. Any word that will cause the column count exceed the given
* max_column will have a '\n' character emitted before it.
*
* The stream is careful to maintain integrity for words that cross
@ -282,7 +282,7 @@ _cairo_ps_surface_path_close_path (void *closure)
}
/* The line cap value is needed to workaround the fact that PostScript
* semnatics for stroking degenerate sub-paths do not match cairo
* semantics for stroking degenerate sub-paths do not match cairo
* semantics. (PostScript draws something for any line cap value,
* while cairo draws something only for round caps).
*
@ -572,7 +572,7 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
cairo_status_t status;
cairo_image_surface_t *image;
unsigned char *row, *byte;
int rows, cols, bytes_per_row;
int rows, cols;
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph_index,
@ -613,7 +613,6 @@ _cairo_ps_surface_emit_bitmap_glyph_data (cairo_ps_surface_t *surface,
_cairo_output_stream_printf (surface->final_stream,
" /DataSource {<");
bytes_per_row = (image->width + 7) / 8;
for (row = image->data, rows = image->height; rows; row += image->stride, rows--) {
for (byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);

View file

@ -326,7 +326,7 @@ _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_
/* XXX: This 256 number is arbitary---we've never done any measurement
* of this. In fact, having a per-font glyph caches each managed
* separately is probably not waht we want anyway. Would probably be
* separately is probably not what we want anyway. Would probably be
* much better to have a single cache for glyphs with random
* replacement across all glyphs of all fonts. */
static int max_glyphs_cached_per_font = 256;
@ -790,6 +790,12 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_scaled_glyph_t *scaled_glyph;
if (utf8[0] == '\0') {
*num_glyphs = 0;
*glyphs = NULL;
return CAIRO_STATUS_SUCCESS;
}
if (scaled_font->backend->text_to_glyphs) {
status = scaled_font->backend->text_to_glyphs (scaled_font,
x, y, utf8,
@ -1091,7 +1097,7 @@ _scaled_glyph_path_close_path (void *abstract_closure)
* operates only on an A1 surface, (converting an A8 surface to A1 if
* necessary), and performs the tracing by drawing a little square
* around each pixel that is on in the mask. We do not pretend that
* this is a high-quality result. But we are leaving it up to somone
* this is a high-quality result. But we are leaving it up to someone
* who cares enough about getting a better result to implement
* something more sophisticated.
**/

View file

@ -511,7 +511,7 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
cairo_antialias_t antialias)
{
cairo_status_t status;
pixman_region16_t *trap_region;
pixman_region16_t *trap_region = NULL;
pixman_region16_t *clear_region = NULL;
cairo_rectangle_int16_t extents;
cairo_composite_traps_info_t traps_info;
@ -519,30 +519,38 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
if (traps->num_traps == 0)
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_get_extents (dst, &extents);
if (status)
return status;
status = _cairo_traps_extract_region (traps, &trap_region);
if (status)
return status;
if (_cairo_operator_bounded_by_mask (op))
{
cairo_rectangle_int16_t trap_extents;
if (trap_region) {
status = _cairo_clip_intersect_to_region (clip, trap_region);
_cairo_region_extents_rectangle (trap_region, &extents);
if (status)
goto out;
_cairo_region_extents_rectangle (trap_region, &trap_extents);
} else {
cairo_box_t trap_extents;
_cairo_traps_extents (traps, &trap_extents);
_cairo_box_round_to_rectangle (&trap_extents, &extents);
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
cairo_box_t trap_box;
_cairo_traps_extents (traps, &trap_box);
_cairo_box_round_to_rectangle (&trap_box, &trap_extents);
}
_cairo_rectangle_intersect (&extents, &trap_extents);
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
if (status)
goto out;
}
else
{
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
status = _cairo_surface_get_extents (dst, &extents);
if (status)
return status;
if (trap_region && !clip_surface) {
/* If we optimize drawing with an unbounded operator to
* _cairo_surface_fill_rectangles() or to drawing with a

View file

@ -1760,7 +1760,7 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
*
* This function returns a bounding box for the surface. The surface
* bounds are defined as a region beyond which no rendering will
* possibly be recorded, in otherwords, it is the maximum extent of
* possibly be recorded, in other words, it is the maximum extent of
* potentially usable coordinates.
*
* For vector surfaces, (PDF, PS, SVG and meta-surfaces), the surface

View file

@ -623,7 +623,7 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status;
unsigned char *row, *byte;
int rows, cols, bytes_per_row;
int rows, cols;
int x, y, bit;
status = _cairo_scaled_glyph_lookup (scaled_font,
@ -644,7 +644,6 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
_cairo_output_stream_printf (document->xml_node_glyphs, "<g");
emit_transform (document->xml_node_glyphs, " transform", ">/n", &image->base.device_transform);
bytes_per_row = (image->width + 7) / 8;
for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) {
for (x = 0, byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);

View file

@ -131,7 +131,7 @@ static const unsigned short charstring_key = 4330;
#define CHARSTRING_endchar 0x000e
/* Before calling this function, the caller must allocate sufficient
* space in data (see _cairo_array_grow_by). The maxium number of
* space in data (see _cairo_array_grow_by). The maximum number of
* bytes that will be used is 2.
*/
static void
@ -156,7 +156,7 @@ charstring_encode_command (cairo_array_t *data, int command)
}
/* Before calling this function, the caller must allocate sufficient
* space in data (see _cairo_array_grow_by). The maxium number of
* space in data (see _cairo_array_grow_by). The maximum number of
* bytes that will be used is 5.
*/
static void

View file

@ -482,7 +482,12 @@ cairo_type1_font_subset_decode_integer (const unsigned char *p, int *integer)
return p;
}
static const char *ps_standard_encoding[256] = {
#if 0
/*
* The two tables that follow are generated using this perl code:
*/
@encoding = (
/* 0 */
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
@ -563,8 +568,106 @@ static const char *ps_standard_encoding[256] = {
NULL, "dotlessi", NULL, NULL,
"lslash", "oslash", "oe", "germandbls",
NULL, NULL, NULL, NULL
);
print "static const char ps_standard_encoding_symbol[] = {\n";
$s = qq( "\\0");
for $sym (@encoding) {
if (! ($sym eq NULL)) {
$ss = qq( "$sym\\0");
if (length($s) + length($ss) > 78) {
print qq( $s\n);
$s = "";
}
$s .= $ss;
}
}
print qq( $s\n);
print "};\n\n";
print "static const int16_t ps_standard_encoding_offset[256] = {\n";
$offset = 1;
$s = qq();
for $sym (@encoding) {
if (! ($sym eq NULL)) {
$ss = qq( $offset/*$sym*/,);
$offset += length($sym) + 1;
} else {
$ss = qq( 0,);
}
if (length($s) + length($ss) > 78) {
print qq( $s\n);
$s = "";
}
$s .= $ss;
}
print qq( $s\n);
print "};\n";
exit;
#endif
static const char ps_standard_encoding_symbol[] = {
"\0" "space\0" "exclam\0" "quotedbl\0" "numbersign\0" "dollar\0" "percent\0"
"ampersand\0" "quoteright\0" "parenleft\0" "parenright\0" "asterisk\0"
"plus\0" "comma\0" "hyphen\0" "period\0" "slash\0" "zero\0" "one\0" "two\0"
"three\0" "four\0" "five\0" "six\0" "seven\0" "eight\0" "nine\0" "colon\0"
"semicolon\0" "less\0" "equal\0" "greater\0" "question\0" "at\0" "A\0" "B\0"
"C\0" "D\0" "E\0" "F\0" "G\0" "H\0" "I\0" "J\0" "K\0" "L\0" "M\0" "N\0" "O\0"
"P\0" "Q\0" "R\0" "S\0" "T\0" "U\0" "V\0" "W\0" "X\0" "Y\0" "Z\0"
"bracketleft\0" "backslash\0" "bracketright\0" "asciicircum\0" "underscore\0"
"quoteleft\0" "a\0" "b\0" "c\0" "d\0" "e\0" "f\0" "g\0" "h\0" "i\0" "j\0"
"k\0" "l\0" "m\0" "n\0" "o\0" "p\0" "q\0" "r\0" "s\0" "t\0" "u\0" "v\0" "w\0"
"x\0" "y\0" "z\0" "braceleft\0" "bar\0" "braceright\0" "asciitilde\0"
"exclamdown\0" "cent\0" "sterling\0" "fraction\0" "yen\0" "florin\0"
"section\0" "currency\0" "quotesingle\0" "quotedblleft\0" "guillemotleft\0"
"guilsinglleft\0" "guilsinglright\0" "fi\0" "fl\0" "endash\0" "dagger\0"
"daggerdbl\0" "periodcentered\0" "paragraph\0" "bullet\0" "quotesinglbase\0"
"quotedblbase\0" "quotedblright\0" "guillemotright\0" "ellipsis\0"
"perthousand\0" "questiondown\0" "grave\0" "acute\0" "circumflex\0" "tilde\0"
"macron\0" "breve\0" "dotaccent\0" "dieresis\0" "ring\0" "cedilla\0"
"hungarumlaut\0" "ogonek\0" "caron\0" "emdash\0" "AE\0" "ordfeminine\0"
"Lslash\0" "Oslash\0" "OE\0" "ordmasculine\0" "ae\0" "dotlessi\0" "lslash\0"
"oslash\0" "oe\0" "germandbls\0"
};
static const int16_t ps_standard_encoding_offset[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1/*space*/, 7/*exclam*/, 14/*quotedbl*/, 23/*numbersign*/,
34/*dollar*/, 41/*percent*/, 49/*ampersand*/, 59/*quoteright*/,
70/*parenleft*/, 80/*parenright*/, 91/*asterisk*/, 100/*plus*/, 105/*comma*/,
111/*hyphen*/, 118/*period*/, 125/*slash*/, 131/*zero*/, 136/*one*/,
140/*two*/, 144/*three*/, 150/*four*/, 155/*five*/, 160/*six*/, 164/*seven*/,
170/*eight*/, 176/*nine*/, 181/*colon*/, 187/*semicolon*/, 197/*less*/,
202/*equal*/, 208/*greater*/, 216/*question*/, 225/*at*/, 228/*A*/, 230/*B*/,
232/*C*/, 234/*D*/, 236/*E*/, 238/*F*/, 240/*G*/, 242/*H*/, 244/*I*/,
246/*J*/, 248/*K*/, 250/*L*/, 252/*M*/, 254/*N*/, 256/*O*/, 258/*P*/,
260/*Q*/, 262/*R*/, 264/*S*/, 266/*T*/, 268/*U*/, 270/*V*/, 272/*W*/,
274/*X*/, 276/*Y*/, 278/*Z*/, 280/*bracketleft*/, 292/*backslash*/,
302/*bracketright*/, 315/*asciicircum*/, 327/*underscore*/, 338/*quoteleft*/,
348/*a*/, 350/*b*/, 352/*c*/, 354/*d*/, 356/*e*/, 358/*f*/, 360/*g*/,
362/*h*/, 364/*i*/, 366/*j*/, 368/*k*/, 370/*l*/, 372/*m*/, 374/*n*/,
376/*o*/, 378/*p*/, 380/*q*/, 382/*r*/, 384/*s*/, 386/*t*/, 388/*u*/,
390/*v*/, 392/*w*/, 394/*x*/, 396/*y*/, 398/*z*/, 400/*braceleft*/,
410/*bar*/, 414/*braceright*/, 425/*asciitilde*/, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
436/*exclamdown*/, 447/*cent*/, 452/*sterling*/, 461/*fraction*/, 470/*yen*/,
474/*florin*/, 481/*section*/, 489/*currency*/, 498/*quotesingle*/,
510/*quotedblleft*/, 523/*guillemotleft*/, 537/*guilsinglleft*/,
551/*guilsinglright*/, 566/*fi*/, 569/*fl*/, 0, 572/*endash*/, 579/*dagger*/,
586/*daggerdbl*/, 596/*periodcentered*/, 0, 611/*paragraph*/, 621/*bullet*/,
628/*quotesinglbase*/, 643/*quotedblbase*/, 656/*quotedblright*/,
670/*guillemotright*/, 685/*ellipsis*/, 694/*perthousand*/, 0,
706/*questiondown*/, 0, 719/*grave*/, 725/*acute*/, 731/*circumflex*/,
742/*tilde*/, 748/*macron*/, 755/*breve*/, 761/*dotaccent*/, 771/*dieresis*/,
0, 780/*ring*/, 785/*cedilla*/, 0, 793/*hungarumlaut*/, 806/*ogonek*/,
813/*caron*/, 819/*emdash*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
826/*AE*/, 0, 829/*ordfeminine*/, 0, 0, 0, 0, 841/*Lslash*/, 848/*Oslash*/,
855/*OE*/, 858/*ordmasculine*/, 0, 0, 0, 0, 0, 871/*ae*/, 0, 0, 0,
874/*dotlessi*/, 0, 0, 883/*lslash*/, 890/*oslash*/, 897/*oe*/,
900/*germandbls*/, 0, 0, 0, 0,
};
#define ps_standard_encoding(index) ((index) ? ps_standard_encoding_symbol+ps_standard_encoding_offset[(index)] : NULL)
static void
use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
{
@ -573,7 +676,7 @@ use_standard_encoding_glyph (cairo_type1_font_subset_t *font, int index)
if (index < 0 || index > 255)
return;
glyph_name = ps_standard_encoding[index];
glyph_name = ps_standard_encoding(index);
if (glyph_name == NULL)
return;

View file

@ -214,7 +214,7 @@ _utf8_get_char_extended (const unsigned char *p,
* consist entirely of valid Unicode characters.
*
* Return value: %CAIRO_STATUS_SUCCESS if the entire string was
* succesfully converted. %CAIRO_STATUS_INVALID_STRING if an
* successfully converted. %CAIRO_STATUS_INVALID_STRING if an
* an invalid sequence was found.
**/
cairo_status_t
@ -278,7 +278,7 @@ _cairo_utf8_to_ucs4 (const unsigned char *str,
* consist entirely of valid Unicode characters.
*
* Return value: %CAIRO_STATUS_SUCCESS if the entire string was
* succesfully converted. %CAIRO_STATUS_INVALID_STRING if an
* successfully converted. %CAIRO_STATUS_INVALID_STRING if an
* an invalid sequence was found.
**/
cairo_status_t

View file

@ -663,7 +663,7 @@ _cairo_int128_divrem (cairo_int128_t num, cairo_int128_t den)
* Compute a 32 bit quotient and 64 bit remainder of a 96 bit unsigned
* dividend and 64 bit divisor. If the quotient doesn't fit into 32
* bits then the returned remainder is equal to the divisor, and the
* qoutient is the largest representable 64 bit integer. It is an
* quotient is the largest representable 64 bit integer. It is an
* error to call this function with the high 32 bits of @num being
* non-zero. */
cairo_uquorem64_t
@ -781,7 +781,7 @@ _cairo_int_96by64_32x64_divrem (cairo_int128_t num, cairo_int64_t den)
{
int num_neg = _cairo_int128_negative (num);
int den_neg = _cairo_int64_negative (den);
cairo_int64_t nonneg_den = den;
cairo_uint64_t nonneg_den;
cairo_uquorem64_t uqr;
cairo_quorem64_t qr;
@ -789,6 +789,8 @@ _cairo_int_96by64_32x64_divrem (cairo_int128_t num, cairo_int64_t den)
num = _cairo_int128_negate (num);
if (den_neg)
nonneg_den = _cairo_int64_negate (den);
else
nonneg_den = den;
uqr = _cairo_uint_96by64_32x64_divrem (num, nonneg_den);
if (_cairo_uint64_eq (uqr.rem, nonneg_den)) {

View file

@ -36,6 +36,16 @@
* Vladimir Vukicevic <vladimir@pobox.com>
*/
#define WIN32_LEAN_AND_MEAN
/* We require Windows 2000 features such as ETO_PDY */
#if !defined(WINVER) || (WINVER < 0x0500)
# define WINVER 0x0500
#endif
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
# define _WIN32_WINNT 0x0500
#endif
#include <windows.h>
#include <stdio.h>
#include "cairoint.h"
#include "cairo-clip-private.h"
@ -1702,7 +1712,7 @@ cairo_win32_surface_create (HDC hdc)
*
* Creates a device-independent-bitmap surface not associated with
* any particular existing surface or device context. The created
* bitmap will be unititialized.
* bitmap will be uninitialized.
*
* Return value: the newly created surface
*
@ -1724,7 +1734,7 @@ cairo_win32_surface_create_with_dib (cairo_format_t format,
*
* Creates a device-independent-bitmap surface not associated with
* any particular existing surface or device context. The created
* bitmap will be unititialized.
* bitmap will be uninitialized.
*
* Return value: the newly created surface
*
@ -1818,7 +1828,7 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
}
/**
* cario_win32_surface_get_image
* cairo_win32_surface_get_image
* @surface: a #cairo_surface_t
*
* Returns a #cairo_surface_t image surface that refers to the same bits

View file

@ -40,16 +40,6 @@
#if CAIRO_HAS_WIN32_SURFACE
#define WIN32_LEAN_AND_MEAN
/* We require Windows 2000 features. Although we don't use them here, things
* should still work if this header file ends up being the one to include
* windows.h into a source file, so: */
#if !defined(WINVER) || (WINVER < 0x0500)
# define WINVER 0x0500
#endif
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
# define _WIN32_WINNT 0x0500
#endif
#include <windows.h>
CAIRO_BEGIN_DECLS

View file

@ -926,7 +926,7 @@ _operator_needs_alpha_composite (cairo_operator_t op,
/* There is a bug in most older X servers with compositing using a
* untransformed repeating source pattern when the source is in off-screen
* video memory, and another with repeated transformed images using a
* general tranform matrix. When these bugs could be triggered, we need a
* general transform matrix. When these bugs could be triggered, we need a
* fallback: in the common case where we have no transformation and the
* source and destination have the same format/visual, we can do the
* operation using the core protocol for the first bug, otherwise, we need
@ -2020,7 +2020,7 @@ _cairo_xcb_surface_add_glyph (xcb_connection_t *dpy,
*
* This is a postscript-y model, where each glyph has its own
* coordinate space, so it's what we expose in terms of metrics. It's
* apparantly what everyone's expecting. Everyone except the Render
* apparently what everyone's expecting. Everyone except the Render
* extension. Render wants to see a glyph tile starting at (0,0), with
* an origin offset inside, like this:
*

View file

@ -1106,7 +1106,7 @@ _operator_needs_alpha_composite (cairo_operator_t op,
/* There is a bug in most older X servers with compositing using a
* untransformed repeating source pattern when the source is in off-screen
* video memory, and another with repeated transformed images using a
* general tranform matrix. When these bugs could be triggered, we need a
* general transform matrix. When these bugs could be triggered, we need a
* fallback: in the common case where we have no transformation and the
* source and destination have the same format/visual, we can do the
* operation using the core protocol for the first bug, otherwise, we need
@ -1166,7 +1166,7 @@ _categorize_composite_operation (cairo_xlib_surface_t *dst,
/* If these are on the same screen but otherwise incompatible,
* make a copy as core drawing can't cross depths and doesn't
* work rightacross visuals of the same depth
* work right across visuals of the same depth
*/
if (_cairo_xlib_surface_same_screen (dst, src) &&
!_surfaces_compatible (dst, src))
@ -2390,7 +2390,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
*
* This is a postscript-y model, where each glyph has its own
* coordinate space, so it's what we expose in terms of metrics. It's
* apparantly what everyone's expecting. Everyone except the Render
* apparently what everyone's expecting. Everyone except the Render
* extension. Render wants to see a glyph tile starting at (0,0), with
* an origin offset inside, like this:
*
@ -2694,9 +2694,9 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
* the first zero-size glyph. However, we don't skip all size-zero
* glyphs, since that will force a new element at every space. We
* skip initial size-zero glyphs and hope that it's enough. Since
* Xft never exposed that bug, this assumptation should be correct.
* Xft never exposed that bug, this assumption should be correct.
*
* We also skip any glyph that hav troublesome coordinates. We want
* We also skip any glyphs that have troublesome coordinates. We want
* to make sure that (glyph2.x - (glyph1.x + glyph1.width)) fits in
* a signed 16bit integer, otherwise it will overflow in the render
* protocol.

View file

@ -953,26 +953,18 @@ cairo_set_dash (cairo_t *cr,
/**
* cairo_get_dash_count:
* @cr: a #cairo_t
* @count: return value for the number of dash values, or %NULL
*
* Gets the length of the dash array in @cr.
* Returns the length of the dash array in @cr (0 if dashing is not
* currently in effect).
*
* Return value: %CAIRO_STATUS_SUCCESS, or error status set on
* @cr.
* See also cairo_set_dash() and cairo_get_dash().
*
* Since: 1.4
*/
cairo_status_t
cairo_get_dash_count (cairo_t *cr,
int *count)
int
cairo_get_dash_count (cairo_t *cr)
{
if (cr->status)
return cr->status;
if (count)
*count = cr->gstate->stroke_style.num_dashes;
return CAIRO_STATUS_SUCCESS;
return cr->gstate->stroke_style.num_dashes;
}
/**
@ -985,27 +977,20 @@ cairo_get_dash_count (cairo_t *cr,
* enough to hold at least the number of values returned by
* cairo_get_dash_count().
*
* Return value: %CAIRO_STATUS_SUCCESS, or error status set on
* @cr.
*
* Since: 1.4
**/
cairo_status_t
void
cairo_get_dash (cairo_t *cr,
double *dashes,
double *offset)
{
if (cr->status)
return cr->status;
memcpy (dashes,
cr->gstate->stroke_style.dash,
sizeof(double) * cr->gstate->stroke_style.num_dashes);
if (dashes)
memcpy (dashes,
cr->gstate->stroke_style.dash,
sizeof (double) * cr->gstate->stroke_style.num_dashes);
if (offset)
*offset = cr->gstate->stroke_style.dash_offset;
return CAIRO_STATUS_SUCCESS;
}
void
@ -2265,7 +2250,7 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status)
}
/**
* cairo_copy_clip_rectangles:
* cairo_copy_clip_rectangle_list:
*
* Returns the current clip region as a list of rectangles in user coordinates.
* Never returns %NULL.
@ -2281,12 +2266,12 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status)
* Since: 1.4
**/
cairo_rectangle_list_t *
cairo_copy_clip_rectangles (cairo_t *cr)
cairo_copy_clip_rectangle_list (cairo_t *cr)
{
if (cr->status)
return _cairo_rectangle_list_create_in_error (cr->status);
return _cairo_gstate_copy_clip_rectangles (cr->gstate);
return _cairo_gstate_copy_clip_rectangle_list (cr->gstate);
}
/**

View file

@ -622,7 +622,7 @@ typedef struct _cairo_rectangle_list {
} cairo_rectangle_list_t;
cairo_public cairo_rectangle_list_t *
cairo_copy_clip_rectangles (cairo_t *cr);
cairo_copy_clip_rectangle_list (cairo_t *cr);
cairo_public void
cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list);
@ -1113,10 +1113,10 @@ cairo_get_line_join (cairo_t *cr);
cairo_public double
cairo_get_miter_limit (cairo_t *cr);
cairo_public cairo_status_t
cairo_get_dash_count (cairo_t *cr, int *count);
cairo_public int
cairo_get_dash_count (cairo_t *cr);
cairo_public cairo_status_t
cairo_public void
cairo_get_dash (cairo_t *cr, double *dashes, double *offset);
cairo_public void

View file

@ -1380,7 +1380,7 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
double *y2);
cairo_private cairo_rectangle_list_t*
_cairo_gstate_copy_clip_rectangles (cairo_gstate_t *gstate);
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate);
cairo_private cairo_status_t
_cairo_gstate_show_surface (cairo_gstate_t *gstate,

3
test/.gitignore vendored
View file

@ -107,6 +107,7 @@ pthread-show-text
rectangle-rounding-error
rectilinear-stroke
rel-path
scale-down-source-surface-paint
scale-source-surface-paint
select-font-face
select-font-no-show-text
@ -124,8 +125,10 @@ text-antialias-gray
text-antialias-none
text-antialias-subpixel
text-cache-crash
text-glyph-range
text-pattern
text-rotate
text-zero-len
transforms
translate-show-surface
trap-clip

View file

@ -72,6 +72,7 @@ pixman-rotate \
random-intersections \
rectangle-rounding-error \
rectilinear-stroke \
scale-down-source-surface-paint \
scale-source-surface-paint \
select-font-face \
select-font-no-show-text \
@ -88,8 +89,10 @@ text-antialias-gray \
text-antialias-none \
text-antialias-subpixel \
text-cache-crash \
text-glyph-range \
text-pattern \
text-rotate \
text-zero-len \
transforms \
translate-show-surface \
trap-clip \
@ -291,6 +294,7 @@ rectilinear-stroke-ref.png \
rel-path-ref.png \
rel-path-rgb24-ref.png \
romedalen.png \
scale-down-source-surface-paint-ref.png \
scale-source-surface-paint-ref.png \
scale-source-surface-paint-rgb24-ref.png \
scale-source-surface-paint-pdf-argb32-ref.png \
@ -314,12 +318,15 @@ surface-pattern-ref.png \
text-antialias-gray-ref.png \
text-antialias-none-ref.png \
text-antialias-subpixel-ref.png \
text-glyph-range-ref.png \
text-glyph-range-rgb24-ref.png \
text-pattern-ref.png \
text-pattern-rgb24-ref.png \
text-pattern-svg-argb32-ref.png \
text-pattern-svg-rgb24-ref.png \
text-rotate-ref.png \
text-rotate-rgb24-ref.png \
text-zero-len-ref.png \
transforms-ref.png \
translate-show-surface-ref.png \
trap-clip-ref.png \
@ -351,6 +358,7 @@ ft-text-vertical-layout-type1 \
leaky-dash \
long-lines \
self-intersecting \
text-glyph-range \
text-rotate
# Any test that doesn't generate a log file goes here

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -93,6 +93,8 @@ settings_set (cairo_t *cr, settings_t *settings)
static int
settings_get (cairo_t *cr, settings_t *settings)
{
int count;
settings->op = cairo_get_operator (cr);
settings->tolerance = cairo_get_tolerance (cr);
settings->fill_rule = cairo_get_fill_rule (cr);
@ -102,18 +104,11 @@ settings_get (cairo_t *cr, settings_t *settings)
settings->miter_limit = cairo_get_miter_limit (cr);
cairo_get_matrix (cr, &settings->matrix);
{
cairo_status_t status;
int count;
count = cairo_get_dash_count (cr);
if (count != 5)
return -1;
status = cairo_get_dash_count (cr, &count);
if (status || count != 5)
return -1;
status = cairo_get_dash (cr, settings->dash, &settings->dash_offset);
if (status)
return -1;
}
cairo_get_dash (cr, settings->dash, &settings->dash_offset);
return 0;
}

View file

@ -30,7 +30,7 @@ static cairo_test_draw_function_t draw;
cairo_test_t test = {
"get-clip",
"Test cairo_copy_clip_rectangles and cairo_clip_extents",
"Test cairo_copy_clip_rectangle_list and cairo_clip_extents",
0, 0,
draw
};
@ -46,13 +46,13 @@ check_count (const char *message, cairo_bool_t uses_clip_rects,
return 1;
if (list->status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
return 1;
cairo_test_log ("Error: %s; cairo_copy_clip_rectangles unexpectedly got %d rectangles\n",
cairo_test_log ("Error: %s; cairo_copy_clip_rectangle_list unexpectedly got %d rectangles\n",
message, list->num_rectangles);
return 0;
}
if (list->status != CAIRO_STATUS_SUCCESS) {
cairo_test_log ("Error: %s; cairo_copy_clip_rectangles failed with \"%s\"\n",
cairo_test_log ("Error: %s; cairo_copy_clip_rectangle_list failed with \"%s\"\n",
message, cairo_status_to_string(list->status));
return 0;
}
@ -68,7 +68,7 @@ static cairo_bool_t
check_unrepresentable (const char *message, cairo_rectangle_list_t *list)
{
if (list->status != CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) {
cairo_test_log ("Error: %s; cairo_copy_clip_rectangles got unexpected result \"%s\"\n"
cairo_test_log ("Error: %s; cairo_copy_clip_rectangle_list got unexpected result \"%s\"\n"
" (we expected CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)",
message, cairo_status_to_string(list->status));
return 0;
@ -126,7 +126,7 @@ draw (cairo_t *cr, int width, int height)
cr2 = cairo_create (surface);
cairo_surface_destroy (surface);
/* Check the surface type so we ignore cairo_copy_clip_rectangles failures
/* Check the surface type so we ignore cairo_copy_clip_rectangle_list failures
* on surface types that don't use rectangle lists for clipping.
* Default to FALSE for the internal surface types, (meta, test-fallback, etc.)
*/
@ -154,7 +154,7 @@ draw (cairo_t *cr, int width, int height)
/* first, test basic stuff. This should not be clipped, it should
return the surface rectangle. */
phase = "No clip set";
rectangle_list = cairo_copy_clip_rectangles (cr2);
rectangle_list = cairo_copy_clip_rectangle_list (cr2);
if (!check_count (phase, uses_clip_rects, rectangle_list, 1) ||
!check_clip_extents (phase, cr2, 0, 0, 100, 100) ||
!check_rectangles_contain(phase, uses_clip_rects, rectangle_list, 0, 0, 100, 100)) {
@ -168,7 +168,7 @@ draw (cairo_t *cr, int width, int height)
cairo_save (cr2);
cairo_rectangle (cr2, 10, 10, 80, 80);
cairo_clip (cr2);
rectangle_list = cairo_copy_clip_rectangles (cr2);
rectangle_list = cairo_copy_clip_rectangle_list (cr2);
if (!check_count (phase, uses_clip_rects, rectangle_list, 1) ||
!check_clip_extents (phase, cr2, 10, 10, 80, 80) ||
!check_rectangles_contain(phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) {
@ -182,7 +182,7 @@ draw (cairo_t *cr, int width, int height)
phase = "All clipped out";
cairo_save (cr2);
cairo_clip (cr2);
rectangle_list = cairo_copy_clip_rectangles (cr2);
rectangle_list = cairo_copy_clip_rectangle_list (cr2);
if (!check_count (phase, uses_clip_rects, rectangle_list, 0)) {
cairo_rectangle_list_destroy (rectangle_list);
return CAIRO_TEST_FAILURE;
@ -198,7 +198,7 @@ draw (cairo_t *cr, int width, int height)
cairo_clip (cr2);
cairo_rectangle (cr2, 15, 15, 10, 10);
cairo_clip (cr2);
rectangle_list = cairo_copy_clip_rectangles (cr2);
rectangle_list = cairo_copy_clip_rectangle_list (cr2);
if (!check_count (phase, uses_clip_rects, rectangle_list, 2) ||
!check_clip_extents (phase, cr2, 15, 15, 10, 10) ||
!check_rectangles_contain(phase, uses_clip_rects, rectangle_list, 15, 15, 5, 5) ||
@ -217,7 +217,7 @@ draw (cairo_t *cr, int width, int height)
cairo_line_to (cr2, 100, 0);
cairo_close_path (cr2);
cairo_clip (cr2);
rectangle_list = cairo_copy_clip_rectangles (cr2);
rectangle_list = cairo_copy_clip_rectangle_list (cr2);
/* can't get this in one tight user-space rectangle */
if (!check_unrepresentable (phase, rectangle_list) ||
!check_clip_extents (phase, cr2, 0, 0, 100, 100)) {
@ -232,7 +232,7 @@ draw (cairo_t *cr, int width, int height)
cairo_scale (cr2, 2, 2);
cairo_rectangle (cr2, 5, 5, 40, 40);
cairo_clip (cr2);
rectangle_list = cairo_copy_clip_rectangles (cr2);
rectangle_list = cairo_copy_clip_rectangle_list (cr2);
if (!check_count (phase, uses_clip_rects, rectangle_list, 1) ||
!check_clip_extents (phase, cr2, 5, 5, 40, 40) ||
!check_rectangles_contain(phase, uses_clip_rects, rectangle_list, 5, 5, 40, 40)) {
@ -249,7 +249,7 @@ draw (cairo_t *cr, int width, int height)
cairo_rectangle (cr2, 5, 5, 40, 40);
cairo_restore (cr2);
cairo_clip (cr2);
rectangle_list = cairo_copy_clip_rectangles (cr2);
rectangle_list = cairo_copy_clip_rectangle_list (cr2);
if (!check_count (phase, uses_clip_rects, rectangle_list, 1) ||
!check_clip_extents (phase, cr2, 10, 10, 80, 80) ||
!check_rectangles_contain(phase, uses_clip_rects, rectangle_list, 10, 10, 80, 80)) {
@ -266,7 +266,7 @@ draw (cairo_t *cr, int width, int height)
cairo_rectangle (cr2, 5, 5, 40, 40);
cairo_restore (cr2);
cairo_clip (cr2);
rectangle_list = cairo_copy_clip_rectangles (cr2);
rectangle_list = cairo_copy_clip_rectangle_list (cr2);
if (!check_unrepresentable (phase, rectangle_list)) {
cairo_rectangle_list_destroy (rectangle_list);
return CAIRO_TEST_FAILURE;

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

View file

@ -0,0 +1,72 @@
/*
* Copyright © 2005,2007 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Red Hat, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Red Hat, Inc. makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Carl D. Worth <cworth@cworth.org>
*/
#include "cairo-test.h"
static cairo_test_draw_function_t draw;
cairo_test_t test = {
"scale-down-source-surface-paint",
"Test call sequence: cairo_scale; cairo_set_source_surface; cairo_paint, with a scale < 1.0",
6, 6,
draw
};
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_surface_t *surface;
static uint32_t data[16] = {
0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000,
0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000,
0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff,
0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff
};
/* First paint opaque background (black) so we don't need separate
* ARGB32 and RGB24 reference images. */
cairo_set_source_rgb (cr, 0, 0, 0); /* black */
cairo_paint (cr);
surface = cairo_image_surface_create_for_data ((unsigned char *) data,
CAIRO_FORMAT_RGB24, 4, 4, 16);
cairo_scale (cr, 0.5, 0.5);
cairo_set_source_surface (cr, surface, 4, 4);
cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
cairo_paint (cr);
cairo_surface_destroy (surface);
return CAIRO_TEST_SUCCESS;
}
int
main (void)
{
return cairo_test (&test);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

133
test/text-glyph-range.c Normal file
View file

@ -0,0 +1,133 @@
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Brian Ewins.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Brian Ewins not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Brian Ewins makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* BRIAN EWINS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL BRIAN EWINS BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Brian Ewins <Brian.Ewins@gmail.com>
*/
/* Related to bug 9530
*
* cairo_glyph_t can contain any unsigned long in its 'index', the intention
* being that it is large enough to hold a pointer. However, this means that
* it can specify many glyph indexes which don't exist in the font, and may
* exceed the range of legal glyph indexes for the font backend. It may
* also contain special values that are not usable as indexes - e.g. 0xffff is
* kATSDeletedGlyphcode in ATSUI, a glyph that should not be drawn.
* The font backends should handle all legal and out-of-range values consistently.
*
* This test expects that operations on out-of-range and missing glyphs should
* act as if they were zero-width.
*/
#include "cairo-test.h"
#define WIDTH 100
#define HEIGHT 75
#define NUM_TEXT 20
#define TEXT_SIZE 12
static cairo_test_draw_function_t draw;
cairo_test_t test = {
"text-glyph-range",
"Tests show_glyphs, glyph_path, glyph_extents with out of range glyph ids."
"\nft and atsui font backends fail, misreporting errors from FT_Load_Glyph and ATSUGlyphGetCubicPaths",
WIDTH, HEIGHT,
draw
};
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_text_extents_t extents;
int i;
/* Glyphs with no paths followed by 'cairo', the additional
* text is to make the space obvious.
*/
long int index[] = {
0, /* 'no matching glyph' */
0xffff, /* kATSDeletedGlyphCode */
0x1ffff, /* out of range */
-1L, /* out of range */
70, 68, 76, 85, 82 /* 'cairo' */
};
/* We draw in the default black, so paint white first. */
cairo_save (cr);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
cairo_paint (cr);
cairo_restore (cr);
cairo_select_font_face (cr, "Bitstream Vera Sans",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, 16);
for (i = 0; i < 9; i++) {
/* since we're just drawing glyphs directly we need to position them. */
cairo_glyph_t glyph = {
index[i], 10 * i, 25
};
/* test cairo_glyph_extents. Every glyph index should
* have extents, invalid glyphs should be zero-width.
*/
cairo_move_to (cr, glyph.x, glyph.y);
cairo_set_line_width (cr, 1.0);
cairo_glyph_extents (cr, &glyph, 1, &extents);
cairo_rectangle (cr,
glyph.x + extents.x_bearing - 0.5,
glyph.y + extents.y_bearing - 0.5,
extents.width + 1,
extents.height + 1);
cairo_set_source_rgb (cr, 1, 0, 0); /* red */
cairo_stroke (cr);
/* test cairo_show_glyphs. Every glyph index should be
* drawable, invalid glyph indexes should draw nothing.
*/
cairo_set_source_rgb (cr, 0, 0, 0); /* black */
cairo_show_glyphs (cr, &glyph, 1);
cairo_move_to (cr, glyph.x, glyph.y);
/* test cairo_glyph_path. Every glyph index should produce
* a path, invalid glyph indexes should have empty paths.
*/
/* Change the glyph position
* so that the paths are visible.
*/
glyph.y = 55;
cairo_move_to (cr, glyph.x, glyph.y);
cairo_glyph_path (cr, &glyph, 1);
cairo_fill (cr);
}
return CAIRO_TEST_SUCCESS;
}
int
main (void)
{
return cairo_test (&test);
}

BIN
test/text-zero-len-ref.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

88
test/text-zero-len.c Normal file
View file

@ -0,0 +1,88 @@
/*
* Copyright © 2006 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Red Hat, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Red Hat, Inc. makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Behdad Esfahbod <behdad@behdad.org>
*/
/* Related bug 5177
*
* In short:
*
* _cairo_atsui_font_text_to_glyph with a zero-sized string crashes.
*
* Moreover, the fallback path in cairo_scaled_font_text_to_glyphs()
* when handling a zero-sized string, allocates a zero-sized glyph array
* and when NULL is returned by malloc, recognizes that as an out-of-memory
* error. The glibc implementation of malloc() does not return NULL from
* malloc(0), but I don't think it's a safe assumption.
*
* By just bailing out on zero-sized text, we fix both issues.
*/
#include "cairo-test.h"
#define WIDTH 60
#define HEIGHT 60
#define NUM_TEXT 20
#define TEXT_SIZE 12
static cairo_test_draw_function_t draw;
cairo_test_t test = {
"text-zero-len",
"Tests show_text and text_path with a zero-sized string",
WIDTH, HEIGHT,
draw
};
/* Draw the word cairo at NUM_TEXT different angles */
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_text_extents_t extents;
cairo_select_font_face (cr, "Bitstream Vera Sans",
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, 16);
cairo_move_to (cr, 10, 25);
cairo_show_text (cr, "");
cairo_show_glyphs (cr, NULL, 0);
cairo_show_glyphs (cr, (void*)8, 0);
cairo_move_to (cr, 10, 55);
cairo_text_path (cr, "");
cairo_glyph_path (cr, (void*)8, 0);
cairo_fill (cr);
cairo_text_extents (cr, "", &extents);
cairo_glyph_extents (cr, (void*)8, 0, &extents);
return CAIRO_TEST_SUCCESS;
}
int
main (void)
{
return cairo_test (&test);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB