diff --git a/NEWS b/NEWS index 29efdb45d..b373fe6ae 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,96 @@ +Snapshot 1.3.12 (2007-01-20 Carl Worth ) +=========================================================== +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 ) =========================================================== Santa Claus is coming just a little bit early this year, and he's diff --git a/ROADMAP b/ROADMAP index b5a539f91..06aa816a1 100644 --- a/ROADMAP +++ b/ROADMAP @@ -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 diff --git a/TODO b/TODO index c44c5f4c5..cc82af67c 100644 --- a/TODO +++ b/TODO @@ -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. + diff --git a/acinclude.m4 b/acinclude.m4 index a8c4743b8..3cfe41093 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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 diff --git a/configure.in b/configure.in index 449245aed..ecb124b76 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/doc/public/tmpl/cairo-version.sgml b/doc/public/tmpl/cairo-version.sgml index e79ee3fc6..012b5fafd 100644 --- a/doc/public/tmpl/cairo-version.sgml +++ b/doc/public/tmpl/cairo-version.sgml @@ -8,14 +8,14 @@ Compile-time and run-time version checks. 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). _____ 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 @@ -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". 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. diff --git a/doc/public/tmpl/cairo.sgml b/doc/public/tmpl/cairo.sgml index 739f74bba..4b9dc0e7a 100644 --- a/doc/public/tmpl/cairo.sgml +++ b/doc/public/tmpl/cairo.sgml @@ -233,7 +233,6 @@ The cairo drawing context @cr: -@count: @Returns: @@ -245,7 +244,6 @@ The cairo drawing context @cr: @dashes: @offset: -@Returns: @@ -483,15 +481,6 @@ The cairo drawing context @rectangle_list: - - - - - -@cr: -@Returns: - - diff --git a/perf/Makefile.am b/perf/Makefile.am index 7e53420df..1ed4c81aa 100644 --- a/perf/Makefile.am +++ b/perf/Makefile.am @@ -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 diff --git a/perf/cairo-perf-diff b/perf/cairo-perf-diff index 47ac456b0..f87391732 100755 --- a/perf/cairo-perf-diff +++ b/perf/cairo-perf-diff @@ -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 diff --git a/perf/cairo-perf-diff-files.c b/perf/cairo-perf-diff-files.c index e6bb09585..8b6292a40 100644 --- a/perf/cairo-perf-diff-files.c +++ b/perf/cairo-perf-diff-files.c @@ -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; iuse_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; } diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c index 1b6363550..18cc652ea 100644 --- a/perf/cairo-perf.c +++ b/perf/cairo-perf.c @@ -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 } }; diff --git a/perf/cairo-perf.h b/perf/cairo-perf.h index bf56e8b4d..1ef9600aa 100644 --- a/perf/cairo-perf.h +++ b/perf/cairo-perf.h @@ -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 diff --git a/perf/long-lines.c b/perf/long-lines.c new file mode 100644 index 000000000..62e8e16f9 --- /dev/null +++ b/perf/long-lines.c @@ -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 + */ + +#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); +} diff --git a/perf/unaligned-clip.c b/perf/unaligned-clip.c new file mode 100644 index 000000000..c7b9d219e --- /dev/null +++ b/perf/unaligned-clip.c @@ -0,0 +1,66 @@ +/* + * Copyright © 2006 Jeff Muizelaar + * 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 + * Carl Worth + */ + +#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); +} diff --git a/pixman/src/fbmmx.c b/pixman/src/fbmmx.c index a99168c58..9c263f876 100644 --- a/pixman/src/fbmmx.c +++ b/pixman/src/fbmmx.c @@ -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--) { diff --git a/pixman/src/fbmmx.h b/pixman/src/fbmmx.h index 531bcbab4..054ac0b73 100644 --- a/pixman/src/fbmmx.h +++ b/pixman/src/fbmmx.h @@ -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, diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c index 0cdec3ffc..63b1cbcf0 100644 --- a/pixman/src/fbpict.c +++ b/pixman/src/fbpict.c @@ -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: diff --git a/pixman/src/iccolor.c b/pixman/src/iccolor.c index 26b4aaf57..9dd8f5e42 100644 --- a/pixman/src/iccolor.c +++ b/pixman/src/iccolor.c @@ -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); diff --git a/pixman/src/icint.h b/pixman/src/icint.h index 17b13b491..93795b056 100644 --- a/pixman/src/icint.h +++ b/pixman/src/icint.h @@ -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 */ diff --git a/pixman/src/pixman-remap.h b/pixman/src/pixman-remap.h index 45a4477af..290df3281 100644 --- a/pixman/src/pixman-remap.h +++ b/pixman/src/pixman-remap.h @@ -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 diff --git a/pixman/src/pixregion.c b/pixman/src/pixregion.c index 5112157ca..0404dff44 100644 --- a/pixman/src/pixregion.c +++ b/pixman/src/pixregion.c @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index 907658a37..598386743 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/cairo-array.c b/src/cairo-array.c index 1d9354a89..ff8cce409 100644 --- a/src/cairo-array.c +++ b/src/cairo-array.c @@ -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. * diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c index 75530d33f..8d95b8eb8 100644 --- a/src/cairo-atsui-font.c +++ b/src/cairo-atsui-font.c @@ -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, diff --git a/src/cairo-cache.c b/src/cairo-cache.c index feac8c775..fa1f003a6 100644 --- a/src/cairo-cache.c +++ b/src/cairo-cache.c @@ -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); diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h index d3255fae6..3c4ff0d42 100644 --- a/src/cairo-clip-private.h +++ b/src/cairo-clip-private.h @@ -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 */ diff --git a/src/cairo-clip.c b/src/cairo-clip.c index 83dda7b6a..605589bb9 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -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; diff --git a/src/cairo-deflate-stream.c b/src/cairo-deflate-stream.c new file mode 100644 index 000000000..816f5c57c --- /dev/null +++ b/src/cairo-deflate-stream.c @@ -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 + */ + +#include "cairoint.h" +#include "cairo-output-stream-private.h" +#include + +#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; +} diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c index 2b0cd988b..316299b05 100644 --- a/src/cairo-font-options.c +++ b/src/cairo-font-options.c @@ -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 **/ diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index bea639e97..57e3853b0 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -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 diff --git a/src/cairo-glitz-surface.c b/src/cairo-glitz-surface.c index f5ca50374..f49273917 100644 --- a/src/cairo-glitz-surface.c +++ b/src/cairo-glitz-surface.c @@ -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, diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index f3621dd7f..18dabd902 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -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 diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 0021ae936..1b5215f9b 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -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 diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c index ac9ef41bd..370d258b5 100644 --- a/src/cairo-lzw.c +++ b/src/cairo-lzw.c @@ -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. * diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c index d4f4bf776..b689f2aaf 100644 --- a/src/cairo-matrix.c +++ b/src/cairo-matrix.c @@ -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(). * * diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c index a82ab8fa8..e196df29c 100644 --- a/src/cairo-meta-surface.c +++ b/src/cairo-meta-surface.c @@ -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 diff --git a/src/cairo-nquartz-surface.c b/src/cairo-nquartz-surface.c index 15b3d61b4..dd05c3849 100644 --- a/src/cairo-nquartz-surface.c +++ b/src/cairo-nquartz-surface.c @@ -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) { diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c index 59718bb38..92bd711c6 100644 --- a/src/cairo-os2-surface.c +++ b/src/cairo-os2-surface.c @@ -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; diff --git a/src/cairo-output-stream-private.h b/src/cairo-output-stream-private.h index 913fb6075..d68fbb480 100644 --- a/src/cairo-output-stream-private.h +++ b/src/cairo-output-stream-private.h @@ -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 */ diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c index 71d646b80..3505c668b 100644 --- a/src/cairo-path-fixed.c +++ b/src/cairo-path-fixed.c @@ -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; diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index 63f0f4df3..519434c40 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -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 diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 3c7f483af..b488d1fd5 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -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. diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index a59cd99c6..722372645 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -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, diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 9315c83bc..45d9fe70b 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -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); diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 73afb5ff0..92d1d4f2e 100755 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -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. **/ diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 02033c8c1..1a7d6663c 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -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 diff --git a/src/cairo-surface.c b/src/cairo-surface.c index ee9a28992..2bff0da23 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -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 diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 573fb3c06..534ba01f9 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -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, "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); diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c index 4bfe44ab2..4776faf6d 100644 --- a/src/cairo-type1-fallback.c +++ b/src/cairo-type1-fallback.c @@ -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 diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c index 08a2d22f3..4455ca59f 100644 --- a/src/cairo-type1-subset.c +++ b/src/cairo-type1-subset.c @@ -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; diff --git a/src/cairo-unicode.c b/src/cairo-unicode.c index 8f99e82e2..5ca51e1e2 100644 --- a/src/cairo-unicode.c +++ b/src/cairo-unicode.c @@ -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 diff --git a/src/cairo-wideint.c b/src/cairo-wideint.c index 62944ed83..e8d3ab69a 100644 --- a/src/cairo-wideint.c +++ b/src/cairo-wideint.c @@ -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)) { diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c index 4fb09df14..be7e70621 100644 --- a/src/cairo-win32-surface.c +++ b/src/cairo-win32-surface.c @@ -36,6 +36,16 @@ * Vladimir Vukicevic */ +#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 + #include #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 diff --git a/src/cairo-win32.h b/src/cairo-win32.h index 17d02c547..8719d338b 100644 --- a/src/cairo-win32.h +++ b/src/cairo-win32.h @@ -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 CAIRO_BEGIN_DECLS diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c index 8b8ba1d5b..2fdf8a1d5 100644 --- a/src/cairo-xcb-surface.c +++ b/src/cairo-xcb-surface.c @@ -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: * diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index fbfae75de..6a0d3e441 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -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. diff --git a/src/cairo.c b/src/cairo.c index d842d7570..2e522a63b 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -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); } /** diff --git a/src/cairo.h b/src/cairo.h index 5e58244d4..1c3fb25ea 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -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 diff --git a/src/cairoint.h b/src/cairoint.h index 80ddb002c..060b98812 100755 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -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, diff --git a/test/.gitignore b/test/.gitignore index c6e2c407b..36ea1d0a8 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -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 diff --git a/test/Makefile.am b/test/Makefile.am index 16237dc03..4f432ada8 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -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 diff --git a/test/caps-joins-alpha-nquartz-ref.png b/test/caps-joins-alpha-nquartz-ref.png new file mode 100644 index 000000000..190c1e96c Binary files /dev/null and b/test/caps-joins-alpha-nquartz-ref.png differ diff --git a/test/clip-nesting-nquartz-ref.png b/test/clip-nesting-nquartz-ref.png new file mode 100644 index 000000000..5a3db7b3a Binary files /dev/null and b/test/clip-nesting-nquartz-ref.png differ diff --git a/test/clip-nesting-nquartz-rgb24-ref.png b/test/clip-nesting-nquartz-rgb24-ref.png new file mode 100644 index 000000000..b55d116b4 Binary files /dev/null and b/test/clip-nesting-nquartz-rgb24-ref.png differ diff --git a/test/clip-push-group-nquartz-ref.png b/test/clip-push-group-nquartz-ref.png new file mode 100644 index 000000000..93c526809 Binary files /dev/null and b/test/clip-push-group-nquartz-ref.png differ diff --git a/test/clip-twice-nquartz-ref.png b/test/clip-twice-nquartz-ref.png new file mode 100644 index 000000000..f8231b31a Binary files /dev/null and b/test/clip-twice-nquartz-ref.png differ diff --git a/test/clip-twice-nquartz-rgb24-ref.png b/test/clip-twice-nquartz-rgb24-ref.png new file mode 100644 index 000000000..65cd80fa7 Binary files /dev/null and b/test/clip-twice-nquartz-rgb24-ref.png differ diff --git a/test/dash-caps-joins-nquartz-ref.png b/test/dash-caps-joins-nquartz-ref.png new file mode 100644 index 000000000..5e4aa76cf Binary files /dev/null and b/test/dash-caps-joins-nquartz-ref.png differ diff --git a/test/degenerate-path-nquartz-rgb24-ref.png b/test/degenerate-path-nquartz-rgb24-ref.png new file mode 100644 index 000000000..6be052e95 Binary files /dev/null and b/test/degenerate-path-nquartz-rgb24-ref.png differ diff --git a/test/fill-and-stroke-alpha-add-nquartz-ref.png b/test/fill-and-stroke-alpha-add-nquartz-ref.png new file mode 100644 index 000000000..d648eec33 Binary files /dev/null and b/test/fill-and-stroke-alpha-add-nquartz-ref.png differ diff --git a/test/fill-and-stroke-alpha-nquartz-ref.png b/test/fill-and-stroke-alpha-nquartz-ref.png new file mode 100644 index 000000000..012147905 Binary files /dev/null and b/test/fill-and-stroke-alpha-nquartz-ref.png differ diff --git a/test/fill-and-stroke-nquartz-ref.png b/test/fill-and-stroke-nquartz-ref.png new file mode 100644 index 000000000..4c48d2426 Binary files /dev/null and b/test/fill-and-stroke-nquartz-ref.png differ diff --git a/test/fill-and-stroke-nquartz-rgb24-ref.png b/test/fill-and-stroke-nquartz-rgb24-ref.png new file mode 100644 index 000000000..5972d5604 Binary files /dev/null and b/test/fill-and-stroke-nquartz-rgb24-ref.png differ diff --git a/test/fill-degenerate-sort-order-nquartz-ref.png b/test/fill-degenerate-sort-order-nquartz-ref.png new file mode 100644 index 000000000..0ea4a67cc Binary files /dev/null and b/test/fill-degenerate-sort-order-nquartz-ref.png differ diff --git a/test/fill-degenerate-sort-order-nquartz-rgb24-ref.png b/test/fill-degenerate-sort-order-nquartz-rgb24-ref.png new file mode 100644 index 000000000..59e1cb6c8 Binary files /dev/null and b/test/fill-degenerate-sort-order-nquartz-rgb24-ref.png differ diff --git a/test/fill-rule-nquartz-ref.png b/test/fill-rule-nquartz-ref.png new file mode 100644 index 000000000..f7e616c9f Binary files /dev/null and b/test/fill-rule-nquartz-ref.png differ diff --git a/test/fill-rule-nquartz-rgb24-ref.png b/test/fill-rule-nquartz-rgb24-ref.png new file mode 100644 index 000000000..8b180c534 Binary files /dev/null and b/test/fill-rule-nquartz-rgb24-ref.png differ diff --git a/test/get-and-set.c b/test/get-and-set.c index ec35834fe..c23707e4c 100644 --- a/test/get-and-set.c +++ b/test/get-and-set.c @@ -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; } diff --git a/test/get-clip.c b/test/get-clip.c index b2a001ca4..f6a2f5a4d 100644 --- a/test/get-clip.c +++ b/test/get-clip.c @@ -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; diff --git a/test/new-sub-path-nquartz-ref.png b/test/new-sub-path-nquartz-ref.png new file mode 100644 index 000000000..e9c40b936 Binary files /dev/null and b/test/new-sub-path-nquartz-ref.png differ diff --git a/test/new-sub-path-nquartz-rgb24-ref.png b/test/new-sub-path-nquartz-rgb24-ref.png new file mode 100644 index 000000000..efc907e83 Binary files /dev/null and b/test/new-sub-path-nquartz-rgb24-ref.png differ diff --git a/test/operator-clear-nquartz-ref.png b/test/operator-clear-nquartz-ref.png new file mode 100644 index 000000000..d79d4c3f4 Binary files /dev/null and b/test/operator-clear-nquartz-ref.png differ diff --git a/test/operator-clear-nquartz-rgb24-ref.png b/test/operator-clear-nquartz-rgb24-ref.png new file mode 100644 index 000000000..d47ce7520 Binary files /dev/null and b/test/operator-clear-nquartz-rgb24-ref.png differ diff --git a/test/random-intersections-nquartz-ref.png b/test/random-intersections-nquartz-ref.png new file mode 100644 index 000000000..a687088c0 Binary files /dev/null and b/test/random-intersections-nquartz-ref.png differ diff --git a/test/random-intersections-nquartz-rgb24-ref.png b/test/random-intersections-nquartz-rgb24-ref.png new file mode 100644 index 000000000..77f73cd53 Binary files /dev/null and b/test/random-intersections-nquartz-rgb24-ref.png differ diff --git a/test/rel-path-nquartz-ref.png b/test/rel-path-nquartz-ref.png new file mode 100644 index 000000000..5878ce4d3 Binary files /dev/null and b/test/rel-path-nquartz-ref.png differ diff --git a/test/rel-path-nquartz-rgb24-ref.png b/test/rel-path-nquartz-rgb24-ref.png new file mode 100644 index 000000000..0e33b6688 Binary files /dev/null and b/test/rel-path-nquartz-rgb24-ref.png differ diff --git a/test/scale-down-source-surface-paint-ref.png b/test/scale-down-source-surface-paint-ref.png new file mode 100644 index 000000000..5c969d2c5 Binary files /dev/null and b/test/scale-down-source-surface-paint-ref.png differ diff --git a/test/scale-down-source-surface-paint.c b/test/scale-down-source-surface-paint.c new file mode 100644 index 000000000..f5effabfe --- /dev/null +++ b/test/scale-down-source-surface-paint.c @@ -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 + */ + +#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); +} diff --git a/test/source-clip-scale-nquartz-ref.png b/test/source-clip-scale-nquartz-ref.png new file mode 100644 index 000000000..f21ae4bb3 Binary files /dev/null and b/test/source-clip-scale-nquartz-ref.png differ diff --git a/test/text-glyph-range-ref.png b/test/text-glyph-range-ref.png new file mode 100644 index 000000000..086aa4a4b Binary files /dev/null and b/test/text-glyph-range-ref.png differ diff --git a/test/text-glyph-range-rgb24-ref.png b/test/text-glyph-range-rgb24-ref.png new file mode 100644 index 000000000..9e8232c4d Binary files /dev/null and b/test/text-glyph-range-rgb24-ref.png differ diff --git a/test/text-glyph-range.c b/test/text-glyph-range.c new file mode 100644 index 000000000..2af48a26d --- /dev/null +++ b/test/text-glyph-range.c @@ -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 + */ + +/* 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); +} diff --git a/test/text-zero-len-ref.png b/test/text-zero-len-ref.png new file mode 100644 index 000000000..4bd2d04ff Binary files /dev/null and b/test/text-zero-len-ref.png differ diff --git a/test/text-zero-len.c b/test/text-zero-len.c new file mode 100644 index 000000000..57c36fdb8 --- /dev/null +++ b/test/text-zero-len.c @@ -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 + */ + +/* 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); +} diff --git a/test/trap-clip-nquartz-ref.png b/test/trap-clip-nquartz-ref.png new file mode 100644 index 000000000..28f59778a Binary files /dev/null and b/test/trap-clip-nquartz-ref.png differ diff --git a/test/trap-clip-nquartz-rgb24-ref.png b/test/trap-clip-nquartz-rgb24-ref.png new file mode 100644 index 000000000..24da4b9aa Binary files /dev/null and b/test/trap-clip-nquartz-rgb24-ref.png differ