Merge branch 'master' of ssh+git://git.cairographics.org/git/cairo
93
NEWS
|
|
@ -1,3 +1,96 @@
|
|||
Snapshot 1.3.12 (2007-01-20 Carl Worth <cworth@cworth.org>)
|
||||
===========================================================
|
||||
The relentless march toward the cairo 1.4 release continues, (even if
|
||||
slightly late out of the starting blocks in 2007). This is the sixth
|
||||
development snapshot in the 1.3 series. It comes 4 weeks after the
|
||||
1.3.10 snapshot.
|
||||
|
||||
Performance
|
||||
-----------
|
||||
As usual, this snapshot has some fun performance improvements to show
|
||||
off:
|
||||
|
||||
image-rgba long-lines-uncropped-100 470.08 -> 4.95: 94.91x speedup
|
||||
███████████████████████████████████████████████
|
||||
image-rgb long-lines-uncropped-100 461.60 -> 4.96: 93.02x speedup
|
||||
██████████████████████████████████████████████
|
||||
|
||||
This 100x improvement, (and yes, that's 100x, not 100%), in the image
|
||||
backend occurs when drawing large shapes where only a fraction of the
|
||||
shape actually appears in the final result, (the rest being outside
|
||||
the bounds of the destination surface). Many applications should see
|
||||
speedups here, and the actual amount of speedup depends on the ratio
|
||||
of non-visible to visible portions of geometry.
|
||||
|
||||
[Note: There remains a similar performance bug when drawing mostly
|
||||
non-visible objects with the xlib backend. This is due to a similar
|
||||
bug in the X server itself, but we hope a future cairo snapshot will
|
||||
workaround that bug to get a similar speedup with the xlib backend.]
|
||||
|
||||
image-rgba unaligned_clip-100 0.09 -> 0.06: 1.67x speedup
|
||||
▍
|
||||
image-rgb unaligned_clip-100 0.09 -> 0.06: 1.66x speedup
|
||||
▍
|
||||
|
||||
This speedup is due to further MMX optimization by Soeren Sandmann for
|
||||
a case commonly hit when rendering PDF files, (and thanks to Jeff
|
||||
Muizelaar for writing code to extract the test case for us).
|
||||
|
||||
There's another MMX optimization in this snapshot (without a fancy
|
||||
speedup chart) by Dan Williams which improves compositing performance
|
||||
specifically for the OLPC machine.
|
||||
|
||||
Thanks to Adrian Johnson, cairo's PDF output is now much more
|
||||
efficient in the way it encodes text output. By reducing redundant
|
||||
information and adding compression to text output streams, Adrian
|
||||
achieved a ~25x improvement in the efficiency of encoding text in PDF
|
||||
files, (was ~45 bytes per glyph and is now ~1.6 bytes per glyph).
|
||||
|
||||
Bug fixes
|
||||
---------
|
||||
In addition to those performance improvements, this snapshot includes
|
||||
several bug fixes:
|
||||
|
||||
* A huge number of bug fixes for cairo-atsui text rendering, (for mac
|
||||
OS X). These bugs affect font selection, glyph positioning, glyph
|
||||
rendering, etc. One noteworthy bug fixes is that
|
||||
cairo_select_font_face will no longer arbitrarily select bold nor
|
||||
italic when not requested, (at least not when using a standard CSS2
|
||||
font family name such as "serif", "sans-serif", "monospace", etc.).
|
||||
All these fixes are thanks to Brian Ewins who continues to do a
|
||||
great job as the new cairo-atsui maintainer.
|
||||
|
||||
* Fix PDF output so that images that are scaled down no longer
|
||||
mysteriously repeat (Carl Worth).
|
||||
|
||||
* Fix segfault on Mac OS X dues to attempt to measure extents of a
|
||||
zero-length string (Behdad Esfahbod).
|
||||
|
||||
* Fix text extents to not include the size of initial/trailing
|
||||
non-inked characters (Behdad Esfahbod).
|
||||
|
||||
API tweaks
|
||||
----------
|
||||
Three functions have had API changes to improve consistency. Note that
|
||||
the API functions being changed here are all functions that were
|
||||
introduced as new functions during these 1.3.x snapshots. As always,
|
||||
there will not be any API changes to functions included in a major
|
||||
release (1.2.x, 1.4.x, etc.) of cairo.
|
||||
|
||||
The changes are as follows:
|
||||
|
||||
* Rename of cairo_copy_clip_rectangles to cairo_copy_clip_rectangle_list.
|
||||
|
||||
* Change cairo_get_dash_count to return an int rather than accepting a
|
||||
pointer to an int for the return value.
|
||||
|
||||
* Change cairo_get_dash to have a void return type rather than
|
||||
returning cairo_status_t.
|
||||
|
||||
It's possible there will be one more round of changes to these
|
||||
functions, (and perhaps cairo_get_color_stop as well), as we seek to
|
||||
establish a unifying convention for returning lists of values.
|
||||
|
||||
Snapshot 1.3.10 (2006-12-23 Carl Worth <cworth@cworth.org>)
|
||||
===========================================================
|
||||
Santa Claus is coming just a little bit early this year, and he's
|
||||
|
|
|
|||
24
ROADMAP
|
|
@ -36,6 +36,13 @@ cairo-1.4 (January 2006): Better performance
|
|||
- New rasterization
|
||||
- Finer-grained fallbacks for PS/PDF
|
||||
|
||||
cairo 1.3.14
|
||||
============
|
||||
Bugs to fix:
|
||||
"issue with rotated image sources" from Benjamin Otte on mailing list
|
||||
"Problem with linear gradients and reflect mode post-rewrite" from T Rowley on list
|
||||
8801 text rendering lacking locking in multithreaded apps
|
||||
|
||||
cairo 1.3.6
|
||||
===========
|
||||
✓ Bankers' rounding bug in _cairo_lround (https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=217819)
|
||||
|
|
@ -65,23 +72,6 @@ cairo 1.4.0 ideas (think performance!)
|
|||
|
||||
✓ New tessellator
|
||||
|
||||
Look into using alloca instead of malloc when copying glyphs/path/etc to edit
|
||||
and use in one function and deallocate upon return.
|
||||
|
||||
Look into generating EPS. That may be done using a new constructor for the
|
||||
PS backend, or better, using an API similar to
|
||||
cairo_svg_surface_restrict_to_version. The PDF backend needs a restrict_to
|
||||
API at some point too.
|
||||
|
||||
Look into the glyph cache. Moreover, make sure we are reusing scaled fonts
|
||||
enough.
|
||||
|
||||
User-font API---a couple of threads of interest:
|
||||
http://lists.freedesktop.org/archives/cairo/2006-May/006893.html
|
||||
http://lists.freedesktop.org/archives/cairo/2006-May/006888.html
|
||||
|
||||
Polling API (cairo_get_serial and cairo_changed)
|
||||
|
||||
Bugs to fix
|
||||
-----------
|
||||
CAIRO_EXTEND_PAD is not implemented for surface patterns
|
||||
|
|
|
|||
40
TODO
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
40
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
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@ Compile-time and run-time version checks.
|
|||
<para>
|
||||
Cairo has a three-part version number scheme. In this scheme, we use
|
||||
even vs. odd numbers to distinguish fixed points in the software
|
||||
vs. in-progress development, (such as from CVS instead of a tar file,
|
||||
vs. in-progress development, (such as from git instead of a tar file,
|
||||
or as a "snapshot" tar file as opposed to a "release" tar file).
|
||||
</para>
|
||||
<para>
|
||||
<informalexample><programlisting>
|
||||
_____ Major. Always 1, until we invent a new scheme.
|
||||
/ ___ Minor. Even/Odd = Release/Snapshot (tar files) or Branch/Head (CVS)
|
||||
| / _ Micro. Even/Odd = Tar-file/CVS
|
||||
/ ___ Minor. Even/Odd = Release/Snapshot (tar files) or Branch/Head (git)
|
||||
| / _ Micro. Even/Odd = Tar-file/git
|
||||
| | /
|
||||
1.0.0
|
||||
</programlisting></informalexample>
|
||||
|
|
@ -33,7 +33,7 @@ Snapshots
|
|||
---------
|
||||
1.1.2 - A snapshot (working toward the 1.2.0 release)
|
||||
|
||||
In-progress development (eg. from CVS)
|
||||
In-progress development (eg. from git)
|
||||
--------------------------------------
|
||||
1.0.1 - Development on a maintenance branch (toward 1.0.2 release)
|
||||
1.1.1 - Development on head (toward 1.1.2 snapshot and 1.2.0 release)
|
||||
|
|
@ -157,7 +157,7 @@ at compile-time, in the form of "X.Y.Z".
|
|||
<!-- ##### MACRO CAIRO_VERSION_ENCODE ##### -->
|
||||
<para>
|
||||
This macro encodes the given cairo version into an integer. The numbers
|
||||
returned by %CAIRO_VERSION and pango_version() are encoded using this macro.
|
||||
returned by %CAIRO_VERSION and cairo_version() are encoded using this macro.
|
||||
Two encoded version numbers can be compared as integers. The encoding ensures
|
||||
that later versions compare greater than earlier versions.
|
||||
</para>
|
||||
|
|
|
|||
|
|
@ -233,7 +233,6 @@ The cairo drawing context
|
|||
</para>
|
||||
|
||||
@cr:
|
||||
@count:
|
||||
@Returns:
|
||||
|
||||
|
||||
|
|
@ -245,7 +244,6 @@ The cairo drawing context
|
|||
@cr:
|
||||
@dashes:
|
||||
@offset:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### ENUM cairo_fill_rule_t ##### -->
|
||||
|
|
@ -483,15 +481,6 @@ The cairo drawing context
|
|||
@rectangle_list:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_copy_clip_rectangles ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@cr:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION cairo_fill ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -129,6 +129,15 @@ typedef enum {
|
|||
TEST_REPORT_STATUS_ERROR
|
||||
} test_report_status_t;
|
||||
|
||||
typedef struct _cairo_perf_diff_files_args {
|
||||
char const *old_filename;
|
||||
char const *new_filename;
|
||||
double min_change;
|
||||
int use_utf;
|
||||
int print_change_bars;
|
||||
int use_ms;
|
||||
} cairo_perf_diff_files_args_t;
|
||||
|
||||
/* Ad-hoc parsing, macros with a strong dependence on the calling
|
||||
* context, and plenty of other ugliness is here. But at least it's
|
||||
* not perl... */
|
||||
|
|
@ -429,46 +438,55 @@ cairo_perf_report_sort_and_compute_stats (cairo_perf_report_t *report)
|
|||
|
||||
#define CHANGE_BAR_WIDTH 70
|
||||
static void
|
||||
print_change_bar (double change, double max_change)
|
||||
print_change_bar (double change, double max_change, int use_utf)
|
||||
{
|
||||
int units_per_cell = (int) ceil (max_change / CHANGE_BAR_WIDTH);
|
||||
static char const *ascii_boxes[8] = {
|
||||
"****","***" ,"***", "**",
|
||||
"**", "*", "*", ""
|
||||
};
|
||||
static char const *utf_boxes[8] = {
|
||||
"█", "▉", "▊", "▋",
|
||||
"▌", "▍", "▎", "▏"
|
||||
};
|
||||
char const **boxes = use_utf ? utf_boxes : ascii_boxes;
|
||||
|
||||
/* For a 1.0x speedup we want a zero-size bar to show "no
|
||||
* change". */
|
||||
change -= 1.0;
|
||||
|
||||
while (change > units_per_cell) {
|
||||
printf("█");
|
||||
printf(boxes[0]);
|
||||
change -= units_per_cell;
|
||||
}
|
||||
|
||||
change /= units_per_cell;
|
||||
|
||||
if (change > 7.5/8.0)
|
||||
printf("█");
|
||||
printf(boxes[0]);
|
||||
else if (change > 6.5/8.0)
|
||||
printf("▉");
|
||||
printf(boxes[1]);
|
||||
else if (change > 5.5/8.0)
|
||||
printf("▊");
|
||||
printf(boxes[2]);
|
||||
else if (change > 4.5/8.0)
|
||||
printf("▋");
|
||||
printf(boxes[3]);
|
||||
else if (change > 3.5/8.0)
|
||||
printf("▌");
|
||||
printf(boxes[4]);
|
||||
else if (change > 2.5/8.0)
|
||||
printf("▍");
|
||||
printf(boxes[5]);
|
||||
else if (change > 1.5/8.0)
|
||||
printf("▎");
|
||||
printf(boxes[6]);
|
||||
else if (change > 0.5/8.0)
|
||||
printf("▏");
|
||||
printf(boxes[7]);
|
||||
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
static void
|
||||
cairo_perf_report_diff (cairo_perf_report_t *old,
|
||||
cairo_perf_report_t *new,
|
||||
double min_change)
|
||||
cairo_perf_report_diff (cairo_perf_report_t *old,
|
||||
cairo_perf_report_t *new,
|
||||
cairo_perf_diff_files_args_t const *args)
|
||||
{
|
||||
int i, i_old, i_new;
|
||||
test_report_t *o, *n;
|
||||
|
|
@ -476,7 +494,7 @@ cairo_perf_report_diff (cairo_perf_report_t *old,
|
|||
test_diff_t *diff, *diffs;
|
||||
int num_diffs = 0;
|
||||
int printed_speedup = 0, printed_slowdown = 0;
|
||||
double change, max_change;
|
||||
double min_change = args->min_change, change, max_change;
|
||||
|
||||
diffs = xmalloc (MAX (old->tests_count, new->tests_count) * sizeof (test_diff_t));
|
||||
|
||||
|
|
@ -516,7 +534,14 @@ cairo_perf_report_diff (cairo_perf_report_t *old,
|
|||
|
||||
diffs[num_diffs].old = o;
|
||||
diffs[num_diffs].new = n;
|
||||
diffs[num_diffs].speedup = (double) o->stats.min_ticks / n->stats.min_ticks;
|
||||
if (args->use_ms) {
|
||||
diffs[num_diffs].speedup =
|
||||
(double) (o->stats.min_ticks / o->stats.ticks_per_ms)
|
||||
/ (n->stats.min_ticks / n->stats.ticks_per_ms);
|
||||
} else {
|
||||
diffs[num_diffs].speedup =
|
||||
(double) o->stats.min_ticks / n->stats.min_ticks;
|
||||
}
|
||||
num_diffs++;
|
||||
|
||||
i_old++;
|
||||
|
|
@ -577,7 +602,8 @@ cairo_perf_report_diff (cairo_perf_report_t *old,
|
|||
else
|
||||
printf ("slowdown\n");
|
||||
|
||||
print_change_bar (change, max_change);
|
||||
if (args->print_change_bars)
|
||||
print_change_bar (change, max_change, args->use_utf);
|
||||
}
|
||||
|
||||
free (diffs);
|
||||
|
|
@ -586,42 +612,91 @@ cairo_perf_report_diff (cairo_perf_report_t *old,
|
|||
static void
|
||||
usage (const char *argv0)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s file1 file2 [minimum_significant_change[%%]]\n", argv0);
|
||||
char const *basename = strrchr(argv0, '/');
|
||||
basename = basename ? basename+1 : argv0;
|
||||
fprintf (stderr,
|
||||
"Usage: %s [--no-utf] [--no-bars] file1 file2 [minimum_significant_change[%%]]\n\n",
|
||||
basename);
|
||||
fprintf (stderr,
|
||||
"Computes significant performance differences for cairo performance reports.\n"
|
||||
"Each file should be the output of the cairo-perf program (or \"make perf\").\n"
|
||||
"The third argument is used to supress all changes below some threshold.\n"
|
||||
"The default value of 5%% ignores any speeedup or slowdown of 5%% or less,\n"
|
||||
"A value of 0 will cause all output to be reported.\n");
|
||||
"A value of 0 will cause all output to be reported.\n"
|
||||
"\n"
|
||||
"--no-utf Use ascii stars instead of utf-8 change bars.\n"
|
||||
" Four stars are printed per factor of speedup.\n"
|
||||
"--no-bars Don't display change bars at all.\n"
|
||||
"--use-ms Use milliseconds to calculate differences.\n"
|
||||
" (instead of ticks which are hardware dependant)\n"
|
||||
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
parse_args(int argc,
|
||||
char const **argv,
|
||||
cairo_perf_diff_files_args_t *args)
|
||||
{
|
||||
#define is_yesno_opt(opt) !(strcmp ("--no-" opt, argv[i]) && strcmp ("--" opt, argv[i]))
|
||||
int i;
|
||||
int have_minchange = 0;
|
||||
|
||||
for (i=1; i<argc; i++) {
|
||||
if (is_yesno_opt("utf")) {
|
||||
args->use_utf = 0 != strncmp ("--no-", argv[i], 4);
|
||||
}
|
||||
else if (is_yesno_opt("bars")) {
|
||||
args->print_change_bars = 0 != strncmp ("--no-", argv[i], 4);
|
||||
}
|
||||
else if (strcmp(argv[i], "--use-ms") == 0) {
|
||||
args->use_ms = 1;
|
||||
}
|
||||
else if (!args->old_filename) {
|
||||
args->old_filename = argv[i];
|
||||
}
|
||||
else if (!args->new_filename) {
|
||||
args->new_filename = argv[i];
|
||||
}
|
||||
else if (!have_minchange) {
|
||||
char *end = NULL;
|
||||
args->min_change = strtod (argv[i], &end);
|
||||
if (*end && *end) {
|
||||
if (0 == strcmp (end, "%")) {
|
||||
args->min_change /= 100;
|
||||
} else {
|
||||
usage (argv[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
usage (argv[0]);
|
||||
}
|
||||
}
|
||||
if ( !args->old_filename || !args->new_filename )
|
||||
usage (argv[0]);
|
||||
#undef is_yesno_opt
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, const char *argv[])
|
||||
{
|
||||
const char *old_filename, *new_filename;
|
||||
cairo_perf_diff_files_args_t args = {
|
||||
NULL, /* old filename */
|
||||
NULL, /* new filename */
|
||||
0.05, /* min change */
|
||||
1, /* use UTF-8? */
|
||||
1, /* display change bars? */
|
||||
};
|
||||
cairo_perf_report_t old, new;
|
||||
double min_change;
|
||||
char *end;
|
||||
|
||||
if (argc < 3) {
|
||||
usage (argv[0]);
|
||||
return 1;
|
||||
}
|
||||
parse_args (argc, argv, &args);
|
||||
|
||||
old_filename = argv[1];
|
||||
new_filename = argv[2];
|
||||
cairo_perf_report_load (&old, args.old_filename);
|
||||
cairo_perf_report_load (&new, args.new_filename);
|
||||
|
||||
min_change = 0.05;
|
||||
if (argc >= 4) {
|
||||
min_change = strtod (argv[3], &end);
|
||||
if (*end && *end == '%')
|
||||
min_change = min_change / 100.0;
|
||||
}
|
||||
|
||||
cairo_perf_report_load (&old, old_filename);
|
||||
cairo_perf_report_load (&new, new_filename);
|
||||
|
||||
cairo_perf_report_diff (&old, &new, min_change);
|
||||
cairo_perf_report_diff (&old, &new, &args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -103,5 +103,7 @@ CAIRO_PERF_DECL (zrusin);
|
|||
CAIRO_PERF_DECL (world_map);
|
||||
CAIRO_PERF_DECL (box_outline);
|
||||
CAIRO_PERF_DECL (mosaic);
|
||||
CAIRO_PERF_DECL (long_lines);
|
||||
CAIRO_PERF_DECL (unaligned_clip);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
117
perf/long-lines.c
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright © 2006 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairo-perf.h"
|
||||
|
||||
/* This test case is designed to illustrate a performance bug in
|
||||
* drawing very long lines, where most of the line is out of bounds of
|
||||
* the destination surface, (but some portion of the line is
|
||||
* visibile). These results are in the "long-lines-uncropped" report.
|
||||
*
|
||||
* For comparison, this test also renders the visible portions of the
|
||||
* same lines, (this is the "long-lines-cropped" report).
|
||||
*/
|
||||
|
||||
typedef enum { LONG_LINES_UNCROPPED, LONG_LINES_CROPPED } long_lines_crop_t;
|
||||
#define NUM_LINES 20
|
||||
#define LONG_FACTOR 50.0
|
||||
|
||||
static cairo_perf_ticks_t
|
||||
do_long_lines (cairo_t *cr, int width, int height, long_lines_crop_t crop)
|
||||
{
|
||||
int i;
|
||||
double x, y, dx, dy, min_x, min_y, max_x, max_y;
|
||||
double outer_width, outer_height;
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_translate (cr, width / 2, height / 2);
|
||||
|
||||
if (crop == LONG_LINES_UNCROPPED) {
|
||||
outer_width = LONG_FACTOR * width;
|
||||
outer_height = LONG_FACTOR * height;
|
||||
cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); /* red */
|
||||
} else {
|
||||
outer_width = width;
|
||||
outer_height = height;
|
||||
cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); /* green */
|
||||
}
|
||||
|
||||
min_x = x = - outer_width / 2.0;
|
||||
min_y = y = - outer_height / 2.0;
|
||||
max_x = outer_width / 2.0;
|
||||
max_y = outer_width / 2.0;
|
||||
dx = outer_width / NUM_LINES;
|
||||
dy = outer_height / NUM_LINES;
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
for (i = 0; i < NUM_LINES; i++) {
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, x, min_y);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, x, max_y);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, min_x, y);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, max_x, y);
|
||||
cairo_stroke (cr);
|
||||
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_restore (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_perf_ticks_t
|
||||
long_lines_uncropped (cairo_t *cr, int width, int height)
|
||||
{
|
||||
return do_long_lines (cr, width, height, LONG_LINES_UNCROPPED);
|
||||
}
|
||||
|
||||
static cairo_perf_ticks_t
|
||||
long_lines_cropped (cairo_t *cr, int width, int height)
|
||||
{
|
||||
return do_long_lines (cr, width, height, LONG_LINES_CROPPED);
|
||||
}
|
||||
|
||||
void
|
||||
long_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped);
|
||||
cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped);
|
||||
}
|
||||
66
perf/unaligned-clip.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright © 2006 Jeff Muizelaar <jeff@infidigm.net>
|
||||
* Copyright © 2006 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors: Jeff Muizelaar <jeff@infidigm.net>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairo-perf.h"
|
||||
|
||||
static cairo_perf_ticks_t
|
||||
do_unaligned_clip (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
/* First a triangular clip that obviously isn't along device-pixel
|
||||
* boundaries. */
|
||||
cairo_move_to (cr, 50, 50);
|
||||
cairo_line_to (cr, 50, 90);
|
||||
cairo_line_to (cr, 90, 90);
|
||||
cairo_close_path (cr);
|
||||
cairo_clip (cr);
|
||||
|
||||
/* Then a rectangular clip that would be but for the non-integer
|
||||
* scaling. */
|
||||
cairo_scale (cr, 1.1, 1.1);
|
||||
cairo_move_to (cr, 55, 55);
|
||||
cairo_line_to (cr, 90, 55);
|
||||
cairo_line_to (cr, 90, 90);
|
||||
cairo_line_to (cr, 90, 55);
|
||||
cairo_close_path (cr);
|
||||
|
||||
cairo_clip (cr);
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_restore (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
void
|
||||
unaligned_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_perf_run (perf, "unaligned_clip", do_unaligned_clip);
|
||||
}
|
||||
|
|
@ -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--)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ _cairo_clip_rect_to_user (cairo_gstate_t *gstate,
|
|||
}
|
||||
|
||||
cairo_private cairo_rectangle_list_t*
|
||||
_cairo_clip_copy_rectangles (cairo_clip_t *clip, cairo_gstate_t *gstate)
|
||||
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
|
||||
{
|
||||
cairo_rectangle_list_t *list;
|
||||
cairo_rectangle_t *rectangles;
|
||||
|
|
|
|||
142
src/cairo-deflate-stream.c
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/* cairo_deflate_stream.c: Output stream abstraction
|
||||
*
|
||||
* Copyright © 2006 Adrian Johnson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is cairo_output_stream.c as distributed with the
|
||||
* cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Adrian Johnson.
|
||||
*
|
||||
* Author(s):
|
||||
* Adrian Johnson <ajohnson@redneon.com>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#define BUFFER_SIZE 16384
|
||||
|
||||
typedef struct _cairo_deflate_stream {
|
||||
cairo_output_stream_t base;
|
||||
cairo_output_stream_t *output;
|
||||
z_stream zlib_stream;
|
||||
unsigned char input_buf[BUFFER_SIZE];
|
||||
unsigned char output_buf[BUFFER_SIZE];
|
||||
} cairo_deflate_stream_t;
|
||||
|
||||
static void
|
||||
cairo_deflate_stream_deflate (cairo_deflate_stream_t *stream, cairo_bool_t flush)
|
||||
{
|
||||
int ret;
|
||||
cairo_bool_t finished;
|
||||
|
||||
do {
|
||||
ret = deflate (&stream->zlib_stream, flush ? Z_FINISH : Z_NO_FLUSH);
|
||||
if (flush || stream->zlib_stream.avail_out == 0)
|
||||
{
|
||||
_cairo_output_stream_write (stream->output,
|
||||
stream->output_buf,
|
||||
BUFFER_SIZE - stream->zlib_stream.avail_out);
|
||||
stream->zlib_stream.next_out = stream->output_buf;
|
||||
stream->zlib_stream.avail_out = BUFFER_SIZE;
|
||||
}
|
||||
|
||||
finished = TRUE;
|
||||
if (stream->zlib_stream.avail_in != 0)
|
||||
finished = FALSE;
|
||||
if (flush && ret != Z_STREAM_END)
|
||||
finished = FALSE;
|
||||
|
||||
} while (!finished);
|
||||
|
||||
stream->zlib_stream.next_in = stream->input_buf;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_deflate_stream_write (cairo_output_stream_t *base,
|
||||
const unsigned char *data,
|
||||
unsigned int length)
|
||||
{
|
||||
cairo_deflate_stream_t *stream = (cairo_deflate_stream_t *) base;
|
||||
unsigned int count;
|
||||
const unsigned char *p = data;
|
||||
|
||||
while (length) {
|
||||
count = length;
|
||||
if (count > BUFFER_SIZE - stream->zlib_stream.avail_in)
|
||||
count = BUFFER_SIZE - stream->zlib_stream.avail_in;
|
||||
memcpy (stream->input_buf + stream->zlib_stream.avail_in, p, count);
|
||||
p += count;
|
||||
stream->zlib_stream.avail_in += count;
|
||||
length -= count;
|
||||
|
||||
if (stream->zlib_stream.avail_in == BUFFER_SIZE)
|
||||
cairo_deflate_stream_deflate (stream, FALSE);
|
||||
}
|
||||
|
||||
return _cairo_output_stream_get_status (stream->output);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_deflate_stream_close (cairo_output_stream_t *base)
|
||||
{
|
||||
cairo_deflate_stream_t *stream = (cairo_deflate_stream_t *) base;
|
||||
|
||||
cairo_deflate_stream_deflate (stream, TRUE);
|
||||
deflateEnd (&stream->zlib_stream);
|
||||
|
||||
return _cairo_output_stream_get_status (stream->output);
|
||||
}
|
||||
|
||||
cairo_output_stream_t *
|
||||
_cairo_deflate_stream_create (cairo_output_stream_t *output)
|
||||
{
|
||||
cairo_deflate_stream_t *stream;
|
||||
|
||||
stream = malloc (sizeof (cairo_deflate_stream_t));
|
||||
if (stream == NULL)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
|
||||
_cairo_output_stream_init (&stream->base,
|
||||
_cairo_deflate_stream_write,
|
||||
_cairo_deflate_stream_close);
|
||||
stream->output = output;
|
||||
|
||||
stream->zlib_stream.zalloc = Z_NULL;
|
||||
stream->zlib_stream.zfree = Z_NULL;
|
||||
stream->zlib_stream.opaque = Z_NULL;
|
||||
|
||||
if (deflateInit (&stream->zlib_stream, Z_DEFAULT_COMPRESSION) != Z_OK)
|
||||
return (cairo_output_stream_t *) &cairo_output_stream_nil;
|
||||
|
||||
stream->zlib_stream.next_in = stream->input_buf;
|
||||
stream->zlib_stream.avail_in = 0;
|
||||
stream->zlib_stream.next_out = stream->output_buf;
|
||||
stream->zlib_stream.avail_out = BUFFER_SIZE;
|
||||
|
||||
return &stream->base;
|
||||
}
|
||||
|
|
@ -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
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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().
|
||||
*
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -623,7 +623,7 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
|
|||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_status_t status;
|
||||
unsigned char *row, *byte;
|
||||
int rows, cols, bytes_per_row;
|
||||
int rows, cols;
|
||||
int x, y, bit;
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
|
|
@ -644,7 +644,6 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
|
|||
_cairo_output_stream_printf (document->xml_node_glyphs, "<g");
|
||||
emit_transform (document->xml_node_glyphs, " transform", ">/n", &image->base.device_transform);
|
||||
|
||||
bytes_per_row = (image->width + 7) / 8;
|
||||
for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) {
|
||||
for (x = 0, byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
|
||||
unsigned char output_byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (*byte);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,16 @@
|
|||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
/* We require Windows 2000 features such as ETO_PDY */
|
||||
#if !defined(WINVER) || (WINVER < 0x0500)
|
||||
# define WINVER 0x0500
|
||||
#endif
|
||||
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
|
||||
# define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cairoint.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
|
@ -1702,7 +1712,7 @@ cairo_win32_surface_create (HDC hdc)
|
|||
*
|
||||
* Creates a device-independent-bitmap surface not associated with
|
||||
* any particular existing surface or device context. The created
|
||||
* bitmap will be unititialized.
|
||||
* bitmap will be uninitialized.
|
||||
*
|
||||
* Return value: the newly created surface
|
||||
*
|
||||
|
|
@ -1724,7 +1734,7 @@ cairo_win32_surface_create_with_dib (cairo_format_t format,
|
|||
*
|
||||
* Creates a device-independent-bitmap surface not associated with
|
||||
* any particular existing surface or device context. The created
|
||||
* bitmap will be unititialized.
|
||||
* bitmap will be uninitialized.
|
||||
*
|
||||
* Return value: the newly created surface
|
||||
*
|
||||
|
|
@ -1818,7 +1828,7 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
|
|||
}
|
||||
|
||||
/**
|
||||
* cario_win32_surface_get_image
|
||||
* cairo_win32_surface_get_image
|
||||
* @surface: a #cairo_surface_t
|
||||
*
|
||||
* Returns a #cairo_surface_t image surface that refers to the same bits
|
||||
|
|
|
|||
|
|
@ -40,16 +40,6 @@
|
|||
|
||||
#if CAIRO_HAS_WIN32_SURFACE
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
/* We require Windows 2000 features. Although we don't use them here, things
|
||||
* should still work if this header file ends up being the one to include
|
||||
* windows.h into a source file, so: */
|
||||
#if !defined(WINVER) || (WINVER < 0x0500)
|
||||
# define WINVER 0x0500
|
||||
#endif
|
||||
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
|
||||
# define _WIN32_WINNT 0x0500
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
43
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1380,7 +1380,7 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
|
|||
double *y2);
|
||||
|
||||
cairo_private cairo_rectangle_list_t*
|
||||
_cairo_gstate_copy_clip_rectangles (cairo_gstate_t *gstate);
|
||||
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_show_surface (cairo_gstate_t *gstate,
|
||||
|
|
|
|||
3
test/.gitignore
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
BIN
test/caps-joins-alpha-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
test/clip-nesting-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 1 KiB |
BIN
test/clip-nesting-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 956 B |
BIN
test/clip-push-group-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 203 B |
BIN
test/clip-twice-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
test/clip-twice-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
test/dash-caps-joins-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
test/degenerate-path-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 188 B |
BIN
test/fill-and-stroke-alpha-add-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 603 B |
BIN
test/fill-and-stroke-alpha-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 550 B |
BIN
test/fill-and-stroke-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 286 B |
BIN
test/fill-and-stroke-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 264 B |
BIN
test/fill-degenerate-sort-order-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
test/fill-degenerate-sort-order-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
test/fill-rule-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
test/fill-rule-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
BIN
test/new-sub-path-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 386 B |
BIN
test/new-sub-path-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 357 B |
BIN
test/operator-clear-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
test/operator-clear-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
test/random-intersections-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 199 KiB |
BIN
test/random-intersections-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 175 KiB |
BIN
test/rel-path-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 212 B |
BIN
test/rel-path-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 228 B |
BIN
test/scale-down-source-surface-paint-ref.png
Normal file
|
After Width: | Height: | Size: 133 B |
72
test/scale-down-source-surface-paint.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright © 2005,2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Red Hat, Inc. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Red Hat, Inc. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
static cairo_test_draw_function_t draw;
|
||||
|
||||
cairo_test_t test = {
|
||||
"scale-down-source-surface-paint",
|
||||
"Test call sequence: cairo_scale; cairo_set_source_surface; cairo_paint, with a scale < 1.0",
|
||||
6, 6,
|
||||
draw
|
||||
};
|
||||
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
static uint32_t data[16] = {
|
||||
0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000,
|
||||
0xffffffff, 0xffffffff, 0xffff0000, 0xffff0000,
|
||||
|
||||
0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff,
|
||||
0xff00ff00, 0xff00ff00, 0xff0000ff, 0xff0000ff
|
||||
};
|
||||
|
||||
/* First paint opaque background (black) so we don't need separate
|
||||
* ARGB32 and RGB24 reference images. */
|
||||
cairo_set_source_rgb (cr, 0, 0, 0); /* black */
|
||||
cairo_paint (cr);
|
||||
|
||||
surface = cairo_image_surface_create_for_data ((unsigned char *) data,
|
||||
CAIRO_FORMAT_RGB24, 4, 4, 16);
|
||||
|
||||
cairo_scale (cr, 0.5, 0.5);
|
||||
|
||||
cairo_set_source_surface (cr, surface, 4, 4);
|
||||
cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return cairo_test (&test);
|
||||
}
|
||||
BIN
test/source-clip-scale-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 148 B |
BIN
test/text-glyph-range-ref.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
test/text-glyph-range-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
133
test/text-glyph-range.c
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2006 Brian Ewins.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Brian Ewins not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Brian Ewins makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* BRIAN EWINS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL BRIAN EWINS BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Brian Ewins <Brian.Ewins@gmail.com>
|
||||
*/
|
||||
|
||||
/* Related to bug 9530
|
||||
*
|
||||
* cairo_glyph_t can contain any unsigned long in its 'index', the intention
|
||||
* being that it is large enough to hold a pointer. However, this means that
|
||||
* it can specify many glyph indexes which don't exist in the font, and may
|
||||
* exceed the range of legal glyph indexes for the font backend. It may
|
||||
* also contain special values that are not usable as indexes - e.g. 0xffff is
|
||||
* kATSDeletedGlyphcode in ATSUI, a glyph that should not be drawn.
|
||||
* The font backends should handle all legal and out-of-range values consistently.
|
||||
*
|
||||
* This test expects that operations on out-of-range and missing glyphs should
|
||||
* act as if they were zero-width.
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
#define WIDTH 100
|
||||
#define HEIGHT 75
|
||||
#define NUM_TEXT 20
|
||||
#define TEXT_SIZE 12
|
||||
|
||||
static cairo_test_draw_function_t draw;
|
||||
|
||||
cairo_test_t test = {
|
||||
"text-glyph-range",
|
||||
"Tests show_glyphs, glyph_path, glyph_extents with out of range glyph ids."
|
||||
"\nft and atsui font backends fail, misreporting errors from FT_Load_Glyph and ATSUGlyphGetCubicPaths",
|
||||
WIDTH, HEIGHT,
|
||||
draw
|
||||
};
|
||||
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_text_extents_t extents;
|
||||
int i;
|
||||
/* Glyphs with no paths followed by 'cairo', the additional
|
||||
* text is to make the space obvious.
|
||||
*/
|
||||
long int index[] = {
|
||||
0, /* 'no matching glyph' */
|
||||
0xffff, /* kATSDeletedGlyphCode */
|
||||
0x1ffff, /* out of range */
|
||||
-1L, /* out of range */
|
||||
70, 68, 76, 85, 82 /* 'cairo' */
|
||||
};
|
||||
|
||||
/* We draw in the default black, so paint white first. */
|
||||
cairo_save (cr);
|
||||
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
|
||||
cairo_paint (cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
cairo_select_font_face (cr, "Bitstream Vera Sans",
|
||||
CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size (cr, 16);
|
||||
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
/* since we're just drawing glyphs directly we need to position them. */
|
||||
cairo_glyph_t glyph = {
|
||||
index[i], 10 * i, 25
|
||||
};
|
||||
|
||||
/* test cairo_glyph_extents. Every glyph index should
|
||||
* have extents, invalid glyphs should be zero-width.
|
||||
*/
|
||||
cairo_move_to (cr, glyph.x, glyph.y);
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_glyph_extents (cr, &glyph, 1, &extents);
|
||||
cairo_rectangle (cr,
|
||||
glyph.x + extents.x_bearing - 0.5,
|
||||
glyph.y + extents.y_bearing - 0.5,
|
||||
extents.width + 1,
|
||||
extents.height + 1);
|
||||
cairo_set_source_rgb (cr, 1, 0, 0); /* red */
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* test cairo_show_glyphs. Every glyph index should be
|
||||
* drawable, invalid glyph indexes should draw nothing.
|
||||
*/
|
||||
cairo_set_source_rgb (cr, 0, 0, 0); /* black */
|
||||
cairo_show_glyphs (cr, &glyph, 1);
|
||||
cairo_move_to (cr, glyph.x, glyph.y);
|
||||
|
||||
/* test cairo_glyph_path. Every glyph index should produce
|
||||
* a path, invalid glyph indexes should have empty paths.
|
||||
*/
|
||||
/* Change the glyph position
|
||||
* so that the paths are visible.
|
||||
*/
|
||||
glyph.y = 55;
|
||||
cairo_move_to (cr, glyph.x, glyph.y);
|
||||
cairo_glyph_path (cr, &glyph, 1);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return cairo_test (&test);
|
||||
}
|
||||
BIN
test/text-zero-len-ref.png
Normal file
|
After Width: | Height: | Size: 130 B |
88
test/text-zero-len.c
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright © 2006 Red Hat, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Red Hat, Inc. not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Red Hat, Inc. makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Behdad Esfahbod <behdad@behdad.org>
|
||||
*/
|
||||
|
||||
/* Related bug 5177
|
||||
*
|
||||
* In short:
|
||||
*
|
||||
* _cairo_atsui_font_text_to_glyph with a zero-sized string crashes.
|
||||
*
|
||||
* Moreover, the fallback path in cairo_scaled_font_text_to_glyphs()
|
||||
* when handling a zero-sized string, allocates a zero-sized glyph array
|
||||
* and when NULL is returned by malloc, recognizes that as an out-of-memory
|
||||
* error. The glibc implementation of malloc() does not return NULL from
|
||||
* malloc(0), but I don't think it's a safe assumption.
|
||||
*
|
||||
* By just bailing out on zero-sized text, we fix both issues.
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
#define WIDTH 60
|
||||
#define HEIGHT 60
|
||||
#define NUM_TEXT 20
|
||||
#define TEXT_SIZE 12
|
||||
|
||||
static cairo_test_draw_function_t draw;
|
||||
|
||||
cairo_test_t test = {
|
||||
"text-zero-len",
|
||||
"Tests show_text and text_path with a zero-sized string",
|
||||
WIDTH, HEIGHT,
|
||||
draw
|
||||
};
|
||||
|
||||
/* Draw the word cairo at NUM_TEXT different angles */
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_text_extents_t extents;
|
||||
|
||||
cairo_select_font_face (cr, "Bitstream Vera Sans",
|
||||
CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size (cr, 16);
|
||||
|
||||
cairo_move_to (cr, 10, 25);
|
||||
cairo_show_text (cr, "");
|
||||
cairo_show_glyphs (cr, NULL, 0);
|
||||
cairo_show_glyphs (cr, (void*)8, 0);
|
||||
|
||||
cairo_move_to (cr, 10, 55);
|
||||
cairo_text_path (cr, "");
|
||||
cairo_glyph_path (cr, (void*)8, 0);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_text_extents (cr, "", &extents);
|
||||
cairo_glyph_extents (cr, (void*)8, 0, &extents);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return cairo_test (&test);
|
||||
}
|
||||
BIN
test/trap-clip-nquartz-ref.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
test/trap-clip-nquartz-rgb24-ref.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |