From a0338805df9dc1fecaea5c73227920d26b22f393 Mon Sep 17 00:00:00 2001 From: Akira Kakuto Date: Sat, 20 Oct 2018 03:19:36 +0000 Subject: cairo 1.16.0 git-svn-id: svn://tug.org/texlive/trunk@48952 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/libs/README | 2 +- Build/source/libs/cairo/ChangeLog | 5 + Build/source/libs/cairo/Makefile.am | 3 + Build/source/libs/cairo/Makefile.in | 38 +- Build/source/libs/cairo/README | 4 +- Build/source/libs/cairo/TLpatches/ChangeLog | 4 + Build/source/libs/cairo/TLpatches/TL-Changes | 5 +- Build/source/libs/cairo/cairo-src/BUGS | 8 +- Build/source/libs/cairo/cairo-src/HACKING | 12 +- Build/source/libs/cairo/cairo-src/INSTALL | 4 +- Build/source/libs/cairo/cairo-src/NEWS | 791 ++++++-- Build/source/libs/cairo/cairo-src/README | 32 +- Build/source/libs/cairo/cairo-src/RELEASING | 68 +- .../libs/cairo/cairo-src/build/Makefile.am.gtk-doc | 27 +- .../cairo/cairo-src/build/Makefile.am.releasing | 2 +- .../cairo/cairo-src/build/Makefile.win32.features | 2 +- .../cairo-src/build/Makefile.win32.features-h | 6 +- .../libs/cairo/cairo-src/build/aclocal.cairo.m4 | 10 +- .../libs/cairo/cairo-src/build/aclocal.float.m4 | 2 +- .../libs/cairo/cairo-src/build/aclocal.pkg.m4 | 2 +- .../cairo/cairo-src/build/configure.ac.features | 3 +- .../libs/cairo/cairo-src/build/configure.ac.system | 2 +- .../libs/cairo/cairo-src/build/configure.ac.tools | 2 +- Build/source/libs/cairo/cairo-src/build/gtk-doc.m4 | 27 +- Build/source/libs/cairo/cairo-src/cairo-version.h | 4 +- Build/source/libs/cairo/cairo-src/config.h.in | 35 +- Build/source/libs/cairo/cairo-src/configure.ac | 86 +- .../libs/cairo/cairo-src/src/Makefile.am.features | 32 +- .../libs/cairo/cairo-src/src/Makefile.sources | 86 +- .../cairo/cairo-src/src/Makefile.win32.features | 32 +- .../cairo/cairo-src/src/cairo-analysis-surface.c | 282 ++- .../cairo/cairo-src/src/cairo-atomic-private.h | 74 +- .../source/libs/cairo/cairo-src/src/cairo-atomic.c | 14 + .../cairo/cairo-src/src/cairo-backend-private.h | 3 + .../libs/cairo/cairo-src/src/cairo-base64-stream.c | 2 +- .../libs/cairo/cairo-src/src/cairo-base85-stream.c | 2 +- .../src/cairo-bentley-ottmann-rectangular.c | 27 +- .../cairo/cairo-src/src/cairo-bentley-ottmann.c | 12 +- .../cairo-src/src/cairo-botor-scan-converter.c | 40 +- .../libs/cairo/cairo-src/src/cairo-box-inline.h | 10 + .../libs/cairo/cairo-src/src/cairo-boxes-private.h | 3 +- .../source/libs/cairo/cairo-src/src/cairo-boxes.c | 34 +- .../libs/cairo/cairo-src/src/cairo-cff-subset.c | 76 +- .../libs/cairo/cairo-src/src/cairo-clip-boxes.c | 60 +- .../cairo-src/src/cairo-clip-tor-scan-converter.c | 4 +- Build/source/libs/cairo/cairo-src/src/cairo-clip.c | 8 +- .../libs/cairo/cairo-src/src/cairo-cogl-context.c | 2 +- .../libs/cairo/cairo-src/src/cairo-cogl-gradient.c | 4 +- .../libs/cairo/cairo-src/src/cairo-cogl-surface.c | 11 +- .../cairo/cairo-src/src/cairo-compiler-private.h | 2 +- .../cairo-src/src/cairo-composite-rectangles.c | 15 +- .../source/libs/cairo/cairo-src/src/cairo-damage.c | 6 +- .../source/libs/cairo/cairo-src/src/cairo-debug.c | 21 +- .../cairo/cairo-src/src/cairo-default-context.c | 23 +- .../cairo/cairo-src/src/cairo-deflate-stream.c | 2 +- .../source/libs/cairo/cairo-src/src/cairo-device.c | 8 +- .../cairo/cairo-src/src/cairo-directfb-surface.c | 3 +- .../libs/cairo/cairo-src/src/cairo-error-private.h | 4 + .../cairo/cairo-src/src/cairo-font-face-twin.c | 4 +- .../libs/cairo/cairo-src/src/cairo-font-face.c | 4 +- .../libs/cairo/cairo-src/src/cairo-font-options.c | 97 +- .../cairo/cairo-src/src/cairo-freed-pool-private.h | 10 +- .../libs/cairo/cairo-src/src/cairo-freed-pool.c | 10 +- .../cairo/cairo-src/src/cairo-freelist-private.h | 2 +- .../libs/cairo/cairo-src/src/cairo-freelist.c | 12 +- .../libs/cairo/cairo-src/src/cairo-ft-font.c | 381 +++- .../libs/cairo/cairo-src/src/cairo-gl-composite.c | 281 ++- .../libs/cairo/cairo-src/src/cairo-gl-device.c | 145 +- .../libs/cairo/cairo-src/src/cairo-gl-dispatch.c | 20 +- .../libs/cairo/cairo-src/src/cairo-gl-glyphs.c | 46 +- .../cairo-src/src/cairo-gl-gradient-private.h | 9 +- .../libs/cairo/cairo-src/src/cairo-gl-gradient.c | 49 +- .../libs/cairo/cairo-src/src/cairo-gl-info.c | 8 +- .../cairo/cairo-src/src/cairo-gl-msaa-compositor.c | 40 +- .../libs/cairo/cairo-src/src/cairo-gl-operand.c | 113 +- .../libs/cairo/cairo-src/src/cairo-gl-private.h | 26 +- .../libs/cairo/cairo-src/src/cairo-gl-shaders.c | 185 +- .../libs/cairo/cairo-src/src/cairo-gl-source.c | 10 +- .../cairo-src/src/cairo-gl-spans-compositor.c | 59 +- .../libs/cairo/cairo-src/src/cairo-gl-surface.c | 273 ++- .../cairo-src/src/cairo-gl-traps-compositor.c | 55 +- Build/source/libs/cairo/cairo-src/src/cairo-gl.h | 2 +- .../libs/cairo/cairo-src/src/cairo-glx-context.c | 2 +- .../cairo/cairo-src/src/cairo-gstate-private.h | 9 + .../source/libs/cairo/cairo-src/src/cairo-gstate.c | 72 +- Build/source/libs/cairo/cairo-src/src/cairo-hash.c | 2 +- .../cairo/cairo-src/src/cairo-image-compositor.c | 70 +- .../libs/cairo/cairo-src/src/cairo-image-source.c | 82 +- .../cairo-src/src/cairo-image-surface-private.h | 3 +- .../libs/cairo/cairo-src/src/cairo-image-surface.c | 95 +- Build/source/libs/cairo/cairo-src/src/cairo-line.c | 8 +- Build/source/libs/cairo/cairo-src/src/cairo-lzw.c | 2 +- .../cairo/cairo-src/src/cairo-malloc-private.h | 2 +- .../source/libs/cairo/cairo-src/src/cairo-matrix.c | 6 - .../libs/cairo/cairo-src/src/cairo-mempool.c | 2 +- .../cairo-src/src/cairo-mesh-pattern-rasterizer.c | 2 +- Build/source/libs/cairo/cairo-src/src/cairo-misc.c | 179 +- .../cairo-src/src/cairo-mono-scan-converter.c | 2 +- .../libs/cairo/cairo-src/src/cairo-os2-surface.c | 7 +- .../libs/cairo/cairo-src/src/cairo-output-stream.c | 25 +- .../cairo/cairo-src/src/cairo-paginated-private.h | 20 +- .../cairo/cairo-src/src/cairo-paginated-surface.c | 113 +- .../libs/cairo/cairo-src/src/cairo-path-bounds.c | 23 + .../libs/cairo/cairo-src/src/cairo-path-fixed.c | 4 +- Build/source/libs/cairo/cairo-src/src/cairo-path.c | 4 +- .../cairo/cairo-src/src/cairo-pattern-private.h | 8 +- .../libs/cairo/cairo-src/src/cairo-pattern.c | 140 +- .../cairo/cairo-src/src/cairo-pdf-interchange.c | 1728 +++++++++++++++++ .../cairo-src/src/cairo-pdf-operators-private.h | 8 + .../libs/cairo/cairo-src/src/cairo-pdf-operators.c | 44 +- .../libs/cairo/cairo-src/src/cairo-pdf-shading.c | 2 +- .../cairo-src/src/cairo-pdf-surface-private.h | 185 +- .../libs/cairo/cairo-src/src/cairo-pdf-surface.c | 1621 +++++++++++----- Build/source/libs/cairo/cairo-src/src/cairo-pdf.h | 67 + Build/source/libs/cairo/cairo-src/src/cairo-pen.c | 2 +- Build/source/libs/cairo/cairo-src/src/cairo-png.c | 55 +- .../cairo/cairo-src/src/cairo-polygon-intersect.c | 7 +- .../cairo/cairo-src/src/cairo-polygon-reduce.c | 2 +- .../libs/cairo/cairo-src/src/cairo-polygon.c | 2 +- .../cairo/cairo-src/src/cairo-ps-surface-private.h | 27 +- .../libs/cairo/cairo-src/src/cairo-ps-surface.c | 1940 ++++++++++++++------ .../libs/cairo/cairo-src/src/cairo-qt-surface.cpp | 10 +- .../libs/cairo/cairo-src/src/cairo-quartz-font.c | 57 +- .../cairo-src/src/cairo-quartz-image-surface.c | 5 +- .../libs/cairo/cairo-src/src/cairo-quartz-image.h | 2 +- .../cairo/cairo-src/src/cairo-quartz-private.h | 12 +- .../cairo/cairo-src/src/cairo-quartz-surface.c | 26 +- .../source/libs/cairo/cairo-src/src/cairo-quartz.h | 2 +- .../src/cairo-recording-surface-private.h | 19 +- .../cairo/cairo-src/src/cairo-recording-surface.c | 267 ++- .../source/libs/cairo/cairo-src/src/cairo-region.c | 6 +- .../cairo-src/src/cairo-scaled-font-private.h | 3 + .../cairo-src/src/cairo-scaled-font-subsets.c | 14 +- .../libs/cairo/cairo-src/src/cairo-scaled-font.c | 59 +- .../cairo/cairo-src/src/cairo-script-surface.c | 26 +- Build/source/libs/cairo/cairo-src/src/cairo-skia.h | 66 - .../libs/cairo/cairo-src/src/cairo-spans-private.h | 4 + .../source/libs/cairo/cairo-src/src/cairo-spans.c | 8 + .../libs/cairo/cairo-src/src/cairo-stroke-style.c | 2 +- .../cairo-src/src/cairo-surface-backend-private.h | 12 + .../cairo/cairo-src/src/cairo-surface-observer.c | 9 +- .../cairo/cairo-src/src/cairo-surface-private.h | 1 + .../cairo/cairo-src/src/cairo-surface-snapshot.c | 12 +- .../cairo/cairo-src/src/cairo-surface-subsurface.c | 10 +- .../cairo-src/src/cairo-surface-wrapper-private.h | 12 + .../cairo/cairo-src/src/cairo-surface-wrapper.c | 66 +- .../libs/cairo/cairo-src/src/cairo-surface.c | 353 +++- .../cairo-src/src/cairo-svg-surface-private.h | 9 + .../libs/cairo/cairo-src/src/cairo-svg-surface.c | 316 +++- Build/source/libs/cairo/cairo-src/src/cairo-svg.h | 47 + .../cairo-src/src/cairo-tag-attributes-private.h | 99 + .../cairo/cairo-src/src/cairo-tag-attributes.c | 702 +++++++ .../cairo/cairo-src/src/cairo-tag-stack-private.h | 107 ++ .../libs/cairo/cairo-src/src/cairo-tag-stack.c | 280 +++ .../libs/cairo/cairo-src/src/cairo-tee-surface.c | 5 +- .../cairo/cairo-src/src/cairo-tor-scan-converter.c | 6 +- .../cairo-src/src/cairo-tor22-scan-converter.c | 6 +- .../libs/cairo/cairo-src/src/cairo-toy-font-face.c | 2 +- .../source/libs/cairo/cairo-src/src/cairo-traps.c | 2 +- .../libs/cairo/cairo-src/src/cairo-tristrip.c | 2 +- .../cairo/cairo-src/src/cairo-truetype-subset.c | 88 +- .../cairo/cairo-src/src/cairo-type1-fallback.c | 2 +- .../libs/cairo/cairo-src/src/cairo-type1-subset.c | 34 +- .../cairo-src/src/cairo-type3-glyph-surface.c | 28 +- .../libs/cairo/cairo-src/src/cairo-types-private.h | 1 + .../libs/cairo/cairo-src/src/cairo-unicode.c | 37 +- .../libs/cairo/cairo-src/src/cairo-user-font.c | 4 +- .../libs/cairo/cairo-src/src/cairo-version.c | 4 +- .../libs/cairo/cairo-src/src/cairo-vg-surface.c | 9 +- Build/source/libs/cairo/cairo-src/src/cairo-vg.h | 4 +- .../source/libs/cairo/cairo-src/src/cairo-win32.h | 4 + .../cairo/cairo-src/src/cairo-xcb-connection.c | 6 +- .../libs/cairo/cairo-src/src/cairo-xcb-screen.c | 2 +- .../libs/cairo/cairo-src/src/cairo-xcb-shm.c | 2 +- .../cairo/cairo-src/src/cairo-xcb-surface-core.c | 10 +- .../cairo/cairo-src/src/cairo-xcb-surface-render.c | 17 +- .../libs/cairo/cairo-src/src/cairo-xcb-surface.c | 5 +- .../cairo-src/src/cairo-xlib-core-compositor.c | 5 +- .../libs/cairo/cairo-src/src/cairo-xlib-display.c | 2 +- .../libs/cairo/cairo-src/src/cairo-xlib-private.h | 2 +- .../cairo-src/src/cairo-xlib-render-compositor.c | 25 +- .../libs/cairo/cairo-src/src/cairo-xlib-screen.c | 2 +- .../libs/cairo/cairo-src/src/cairo-xlib-source.c | 13 +- .../cairo/cairo-src/src/cairo-xlib-surface-shm.c | 11 +- .../libs/cairo/cairo-src/src/cairo-xlib-surface.c | 13 +- .../libs/cairo/cairo-src/src/cairo-xlib-visual.c | 2 +- .../cairo/cairo-src/src/cairo-xlib-xcb-surface.c | 7 +- .../libs/cairo/cairo-src/src/cairo-xml-surface.c | 11 +- Build/source/libs/cairo/cairo-src/src/cairo.c | 325 +++- Build/source/libs/cairo/cairo-src/src/cairo.h | 37 +- Build/source/libs/cairo/cairo-src/src/cairoint.h | 81 +- .../cairo/cairo-src/src/test-compositor-surface.c | 5 +- .../cairo-src/src/test-null-compositor-surface.c | 15 +- .../cairo/cairo-src/src/test-paginated-surface.c | 9 +- Build/source/libs/cairo/configure | 20 +- Build/source/libs/cairo/version.ac | 2 +- 196 files changed, 11015 insertions(+), 2976 deletions(-) create mode 100644 Build/source/libs/cairo/cairo-src/src/cairo-pdf-interchange.c delete mode 100644 Build/source/libs/cairo/cairo-src/src/cairo-skia.h create mode 100644 Build/source/libs/cairo/cairo-src/src/cairo-tag-attributes-private.h create mode 100644 Build/source/libs/cairo/cairo-src/src/cairo-tag-attributes.c create mode 100644 Build/source/libs/cairo/cairo-src/src/cairo-tag-stack-private.h create mode 100644 Build/source/libs/cairo/cairo-src/src/cairo-tag-stack.c (limited to 'Build') diff --git a/Build/source/libs/README b/Build/source/libs/README index 60bbe4980cd..850fa0b8e53 100644 --- a/Build/source/libs/README +++ b/Build/source/libs/README @@ -9,7 +9,7 @@ bypassing or using the original one. See also comments in ../texk/README. -cairo 1.14.12 - checked 07dec17 +cairo 1.16.0 - checked 20oct18 http://cairographics.org/releases/ freetype2 2.9.1 - checked 04may18 diff --git a/Build/source/libs/cairo/ChangeLog b/Build/source/libs/cairo/ChangeLog index fce379febab..b7751e92f12 100644 --- a/Build/source/libs/cairo/ChangeLog +++ b/Build/source/libs/cairo/ChangeLog @@ -1,3 +1,8 @@ +2018-10-20 Akira Kakuto + + Import cairo-1.16.0. + * Makefile.am, version.ac: Adapted. + 2017-12-07 Akira Kakuto Import cairo-1.14.12. diff --git a/Build/source/libs/cairo/Makefile.am b/Build/source/libs/cairo/Makefile.am index dfa3fa02035..0d7134e6267 100644 --- a/Build/source/libs/cairo/Makefile.am +++ b/Build/source/libs/cairo/Makefile.am @@ -98,6 +98,7 @@ libcairo_a_SOURCES = \ @CAIRO_TREE@/src/cairo-path-stroke-traps.c \ @CAIRO_TREE@/src/cairo-path-stroke-tristrip.c \ @CAIRO_TREE@/src/cairo-pattern.c \ + @CAIRO_TREE@/src/cairo-pdf-interchange.c \ @CAIRO_TREE@/src/cairo-pen.c \ @CAIRO_TREE@/src/cairo-polygon.c \ @CAIRO_TREE@/src/cairo-polygon-intersect.c \ @@ -124,6 +125,8 @@ libcairo_a_SOURCES = \ @CAIRO_TREE@/src/cairo-surface-snapshot.c \ @CAIRO_TREE@/src/cairo-surface-subsurface.c \ @CAIRO_TREE@/src/cairo-surface-wrapper.c \ + @CAIRO_TREE@/src/cairo-tag-attributes.c \ + @CAIRO_TREE@/src/cairo-tag-stack.c \ @CAIRO_TREE@/src/cairo-time.c \ @CAIRO_TREE@/src/cairo-tor-scan-converter.c \ @CAIRO_TREE@/src/cairo-tor22-scan-converter.c \ diff --git a/Build/source/libs/cairo/Makefile.in b/Build/source/libs/cairo/Makefile.in index 7bb60847fbc..31347968c86 100644 --- a/Build/source/libs/cairo/Makefile.in +++ b/Build/source/libs/cairo/Makefile.in @@ -234,8 +234,9 @@ am__libcairo_a_SOURCES_DIST = \ @CAIRO_TREE@/src/cairo-path-stroke-polygon.c \ @CAIRO_TREE@/src/cairo-path-stroke-traps.c \ @CAIRO_TREE@/src/cairo-path-stroke-tristrip.c \ - @CAIRO_TREE@/src/cairo-pattern.c @CAIRO_TREE@/src/cairo-pen.c \ - @CAIRO_TREE@/src/cairo-polygon.c \ + @CAIRO_TREE@/src/cairo-pattern.c \ + @CAIRO_TREE@/src/cairo-pdf-interchange.c \ + @CAIRO_TREE@/src/cairo-pen.c @CAIRO_TREE@/src/cairo-polygon.c \ @CAIRO_TREE@/src/cairo-polygon-intersect.c \ @CAIRO_TREE@/src/cairo-polygon-reduce.c \ @CAIRO_TREE@/src/cairo-raster-source-pattern.c \ @@ -258,6 +259,8 @@ am__libcairo_a_SOURCES_DIST = \ @CAIRO_TREE@/src/cairo-surface-snapshot.c \ @CAIRO_TREE@/src/cairo-surface-subsurface.c \ @CAIRO_TREE@/src/cairo-surface-wrapper.c \ + @CAIRO_TREE@/src/cairo-tag-attributes.c \ + @CAIRO_TREE@/src/cairo-tag-stack.c \ @CAIRO_TREE@/src/cairo-time.c \ @CAIRO_TREE@/src/cairo-tor-scan-converter.c \ @CAIRO_TREE@/src/cairo-tor22-scan-converter.c \ @@ -426,6 +429,7 @@ am_libcairo_a_OBJECTS = \ @CAIRO_TREE@/src/cairo-path-stroke-traps.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-path-stroke-tristrip.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-pattern.$(OBJEXT) \ + @CAIRO_TREE@/src/cairo-pdf-interchange.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-pen.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-polygon.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-polygon-intersect.$(OBJEXT) \ @@ -452,6 +456,8 @@ am_libcairo_a_OBJECTS = \ @CAIRO_TREE@/src/cairo-surface-snapshot.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-surface-subsurface.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-surface-wrapper.$(OBJEXT) \ + @CAIRO_TREE@/src/cairo-tag-attributes.$(OBJEXT) \ + @CAIRO_TREE@/src/cairo-tag-stack.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-time.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-tor-scan-converter.$(OBJEXT) \ @CAIRO_TREE@/src/cairo-tor22-scan-converter.$(OBJEXT) \ @@ -570,6 +576,7 @@ am__depfiles_remade = ./$(DEPDIR)/cairotst-cairotst.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-path-stroke.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-path.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-pattern.Po \ + @CAIRO_TREE@/src/$(DEPDIR)/cairo-pdf-interchange.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-pen.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-png.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-polygon-intersect.Po \ @@ -601,6 +608,8 @@ am__depfiles_remade = ./$(DEPDIR)/cairotst-cairotst.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-surface-wrapper.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-surface.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-svg-surface.Po \ + @CAIRO_TREE@/src/$(DEPDIR)/cairo-tag-attributes.Po \ + @CAIRO_TREE@/src/$(DEPDIR)/cairo-tag-stack.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-time.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-tor-scan-converter.Po \ @CAIRO_TREE@/src/$(DEPDIR)/cairo-tor22-scan-converter.Po \ @@ -1132,8 +1141,9 @@ libcairo_a_SOURCES = @CAIRO_TREE@/src/cairo-analysis-surface.c \ @CAIRO_TREE@/src/cairo-path-stroke-polygon.c \ @CAIRO_TREE@/src/cairo-path-stroke-traps.c \ @CAIRO_TREE@/src/cairo-path-stroke-tristrip.c \ - @CAIRO_TREE@/src/cairo-pattern.c @CAIRO_TREE@/src/cairo-pen.c \ - @CAIRO_TREE@/src/cairo-polygon.c \ + @CAIRO_TREE@/src/cairo-pattern.c \ + @CAIRO_TREE@/src/cairo-pdf-interchange.c \ + @CAIRO_TREE@/src/cairo-pen.c @CAIRO_TREE@/src/cairo-polygon.c \ @CAIRO_TREE@/src/cairo-polygon-intersect.c \ @CAIRO_TREE@/src/cairo-polygon-reduce.c \ @CAIRO_TREE@/src/cairo-raster-source-pattern.c \ @@ -1156,6 +1166,8 @@ libcairo_a_SOURCES = @CAIRO_TREE@/src/cairo-analysis-surface.c \ @CAIRO_TREE@/src/cairo-surface-snapshot.c \ @CAIRO_TREE@/src/cairo-surface-subsurface.c \ @CAIRO_TREE@/src/cairo-surface-wrapper.c \ + @CAIRO_TREE@/src/cairo-tag-attributes.c \ + @CAIRO_TREE@/src/cairo-tag-stack.c \ @CAIRO_TREE@/src/cairo-time.c \ @CAIRO_TREE@/src/cairo-tor-scan-converter.c \ @CAIRO_TREE@/src/cairo-tor22-scan-converter.c \ @@ -1460,6 +1472,9 @@ clean-noinstLIBRARIES: @CAIRO_TREE@/src/cairo-pattern.$(OBJEXT): \ @CAIRO_TREE@/src/$(am__dirstamp) \ @CAIRO_TREE@/src/$(DEPDIR)/$(am__dirstamp) +@CAIRO_TREE@/src/cairo-pdf-interchange.$(OBJEXT): \ + @CAIRO_TREE@/src/$(am__dirstamp) \ + @CAIRO_TREE@/src/$(DEPDIR)/$(am__dirstamp) @CAIRO_TREE@/src/cairo-pen.$(OBJEXT): \ @CAIRO_TREE@/src/$(am__dirstamp) \ @CAIRO_TREE@/src/$(DEPDIR)/$(am__dirstamp) @@ -1538,6 +1553,12 @@ clean-noinstLIBRARIES: @CAIRO_TREE@/src/cairo-surface-wrapper.$(OBJEXT): \ @CAIRO_TREE@/src/$(am__dirstamp) \ @CAIRO_TREE@/src/$(DEPDIR)/$(am__dirstamp) +@CAIRO_TREE@/src/cairo-tag-attributes.$(OBJEXT): \ + @CAIRO_TREE@/src/$(am__dirstamp) \ + @CAIRO_TREE@/src/$(DEPDIR)/$(am__dirstamp) +@CAIRO_TREE@/src/cairo-tag-stack.$(OBJEXT): \ + @CAIRO_TREE@/src/$(am__dirstamp) \ + @CAIRO_TREE@/src/$(DEPDIR)/$(am__dirstamp) @CAIRO_TREE@/src/cairo-time.$(OBJEXT): \ @CAIRO_TREE@/src/$(am__dirstamp) \ @CAIRO_TREE@/src/$(DEPDIR)/$(am__dirstamp) @@ -1790,6 +1811,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-path-stroke.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-path.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-pattern.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-pdf-interchange.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-pen.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-png.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-polygon-intersect.Po@am__quote@ # am--include-marker @@ -1821,6 +1843,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-surface-wrapper.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-surface.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-svg-surface.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-tag-attributes.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-tag-stack.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-time.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-tor-scan-converter.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@@CAIRO_TREE@/src/$(DEPDIR)/cairo-tor22-scan-converter.Po@am__quote@ # am--include-marker @@ -2480,6 +2504,7 @@ distclean: distclean-recursive -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-path-stroke.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-path.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-pattern.Po + -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-pdf-interchange.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-pen.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-png.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-polygon-intersect.Po @@ -2511,6 +2536,8 @@ distclean: distclean-recursive -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-surface-wrapper.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-surface.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-svg-surface.Po + -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-tag-attributes.Po + -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-tag-stack.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-time.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-tor-scan-converter.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-tor22-scan-converter.Po @@ -2672,6 +2699,7 @@ maintainer-clean: maintainer-clean-recursive -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-path-stroke.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-path.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-pattern.Po + -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-pdf-interchange.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-pen.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-png.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-polygon-intersect.Po @@ -2703,6 +2731,8 @@ maintainer-clean: maintainer-clean-recursive -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-surface-wrapper.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-surface.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-svg-surface.Po + -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-tag-attributes.Po + -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-tag-stack.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-time.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-tor-scan-converter.Po -rm -f @CAIRO_TREE@/src/$(DEPDIR)/cairo-tor22-scan-converter.Po diff --git a/Build/source/libs/cairo/README b/Build/source/libs/cairo/README index 297acbcd9be..6d35a295b10 100644 --- a/Build/source/libs/cairo/README +++ b/Build/source/libs/cairo/README @@ -1,4 +1,4 @@ - Building cairo-1.14.12 as part of the TL tree + Building cairo-1.16.0 as part of the TL tree ============================================ This directory libs/cairo/ uses a proxy Makefile.am to build the cairo @@ -12,4 +12,4 @@ been translated into equivalent test in libs/cairo/configure.ac. 2012-11-10 Taco Hoekwater 2013-04-15 Peter Breitenlohner -2017-12-07 Akira Kakuto +2018-10-20 Akira Kakuto diff --git a/Build/source/libs/cairo/TLpatches/ChangeLog b/Build/source/libs/cairo/TLpatches/ChangeLog index b8ee20cf6b0..8be6faef5d8 100644 --- a/Build/source/libs/cairo/TLpatches/ChangeLog +++ b/Build/source/libs/cairo/TLpatches/ChangeLog @@ -1,3 +1,7 @@ +2018-10-20 Akira Kakuto + + Import cairo-1.16.0. + 2017-12-07 Akira Kakuto Import cairo-1.14.12. diff --git a/Build/source/libs/cairo/TLpatches/TL-Changes b/Build/source/libs/cairo/TLpatches/TL-Changes index 94ffe89d6ac..9259b0f9de8 100644 --- a/Build/source/libs/cairo/TLpatches/TL-Changes +++ b/Build/source/libs/cairo/TLpatches/TL-Changes @@ -1,5 +1,5 @@ -Changes applied to the cairo-1.14.12/ tree as obtained from: - http://cairographics.org/releases/cairo-1.14.12.tar.xz +Changes applied to the cairo-1.16.0/ tree as obtained from: + http://cairographics.org/releases/cairo-1.16.0.tar.xz Removed: Makefile.in @@ -27,7 +27,6 @@ Removed unused dirs: doc perf src/drm - src/skia src/win32 test util diff --git a/Build/source/libs/cairo/cairo-src/BUGS b/Build/source/libs/cairo/cairo-src/BUGS index ef044046d3e..452d523006f 100644 --- a/Build/source/libs/cairo/cairo-src/BUGS +++ b/Build/source/libs/cairo/cairo-src/BUGS @@ -12,7 +12,7 @@ which you prefer: up on previous bug reports, and search for existing, known bugs. Just use the "cairo" product: - http://bugs.freedesktop.org + https://bugs.freedesktop.org It is necessary to go through a quick account creation process, (with email address verification), in order to be able to report @@ -26,7 +26,7 @@ which you prefer: mailing list only allows posting from subscribers, so use the following page for subscription instructions: - http://cairographics.org/lists + https://cairographics.org/lists Again, we apologize for any inconvenience this subscription step might cause, but we've found it necessary to require this in order @@ -49,10 +49,10 @@ in getting the bug fixed sooner): 1) Check to see if the bug has been reported already. It's pretty easy to run a search or two against the cairo product in the - http://bugs.freedesktop.org bugzilla database. Another place to + https://bugs.freedesktop.org bugzilla database. Another place to look for known bugs is the cairo ROADMAP: - http://cairographics.org/ROADMAP + https://cairographics.org/ROADMAP which shows a planned schedule of releases and which bug fixes are being planned for each release. diff --git a/Build/source/libs/cairo/cairo-src/HACKING b/Build/source/libs/cairo/cairo-src/HACKING index aba2c545bb9..bc97f53248a 100644 --- a/Build/source/libs/cairo/cairo-src/HACKING +++ b/Build/source/libs/cairo/cairo-src/HACKING @@ -24,7 +24,7 @@ Contact Various ways to get in touch with other cairo developers and maintainers have been enumerated at: - http://cairographics.org/contact/ + https://cairographics.org/contact/ Most of that information is also reflected in the following sections. @@ -35,7 +35,7 @@ Mailing Lists There are various mailing lists that are useful when developing cairo code. A complete list is always available at: - http://cairographics.org/lists/ + https://cairographics.org/lists/ It is recommended that cairo developers subscribe to all those lists. The cairo list by itself generates much more traffic than the others @@ -48,7 +48,7 @@ Bug Tracking System We use a standard bugzilla bug tracking system available at: - http://bugs.freedesktop.org/ + https://bugs.freedesktop.org/ See file named BUGS for detailed information on reporting bugs. In short, for straight bug reports, it's best to report them there such that they @@ -71,11 +71,11 @@ Version Control System We use /git/ for version control. See: - http://cairographics.org/download/ + https://cairographics.org/download/ For more information on using git, see: - http://freedesktop.org/wiki/Infrastructure/git/ + https://freedesktop.org/wiki/Infrastructure/git/ Build System @@ -165,7 +165,7 @@ See doc/public/README for more information. For more documentation including frequently asked questions, tutorials, samples, roadmap, todo list, etc visit: - http://cairographics.org/documentation/ + https://cairographics.org/documentation/ Some of those should gradually be moved to doc/. diff --git a/Build/source/libs/cairo/cairo-src/INSTALL b/Build/source/libs/cairo/cairo-src/INSTALL index 9db68dee2ba..f25f8f34d3b 100644 --- a/Build/source/libs/cairo/cairo-src/INSTALL +++ b/Build/source/libs/cairo/cairo-src/INSTALL @@ -140,11 +140,11 @@ itself), then you're in the right place and should read on. However, if you don't need such a bleeding-edge version of cairo, then you might prefer to start by building the latest stable cairo release: - http://cairographics.org/releases + https://cairographics.org/releases or perhaps the latest (unstable) development snapshot: - http://cairographics.org/snapshots + https://cairographics.org/snapshots There you'll find nicely packaged tar files that include a configure script so you can go back the the simpler instructions above. diff --git a/Build/source/libs/cairo/cairo-src/NEWS b/Build/source/libs/cairo/cairo-src/NEWS index c0b5db5b1a6..a50b0a001c3 100644 --- a/Build/source/libs/cairo/cairo-src/NEWS +++ b/Build/source/libs/cairo/cairo-src/NEWS @@ -1,20 +1,290 @@ -Release 1.14.12 (2017-06-13 Bryce Harrington ) +Release 1.16.0 (2018-10-19 Bryce Harrington ) ======================================================================== -Another bugfix release rolling up backported fixes for the past half year. +This new stable release incorporates a number of improvements made in +the four years since 1.14.0. -For a complete log of changes since 1.14.10, please see: +Of particular note is a wealth of work by Adrian Johnson to enhance PDF +functionality, including restoring support for MacOSX 10.4, metadata, +hyperlinks, and more. - http://cairographics.org/releases/ChangeLog.cairo-1.14.12 +Much attention also went into fonts, including new colored emoji glyph +support, variable fonts, and fixes for various font idiosyncrasies. +Other noteworthy changes include GLESv3 support for the cairo_gl +backend, tracking of SVG units in generated SVG documents, and cleanups +for numerous test failures and related issues in the PDF and Postscript +backends. -Features --------- +For a complete log of changes, please see + + https://cairographics.org/releases/ChangeLog.1.16.0 + + +Features and Enhancements +------------------------- +* Add support for OpenGL ES 3.0 to the gl backend. +* The PDF backend has gained support for a range of widely used + features, including thumbnails, page labels, metadata, document + outlines, structured text, hyperlinks, and tags. Tags permit adding + logical info such as headings, tables, figures, etc. that facilitates + indexing, accessibility, text reflow, searching, and extraction of the + tagged items to other software. For details on this new PDF + functionality, see: + https://lists.cairographics.org/archives/cairo/2016-June/027427.html +* Variable font support. Variable fonts are single font files with + various typography characteristics, such as weight or slant, that users + of the font can adjust between two points. Effectively this enables a + single font to behave as multiple fonts. +* Restore MacOSX 10.4 support. Cairo had dropped 10.4 support when + moving to the CoreText API. Now we automatically detect which API to + use via dynamic linking, so can resume supporting this older version + of MacOSX. +* Support colored emoji glyphs, stored as PNG images in OpenType fonts. +* Skia backend is removed +* Use Reusable streams for forms in Level 3 Postscript. +* Add CAIRO_MIME_TYPE_EPS mime type for embedding EPS files. +* Add CCITT_FAX mime type for PDF and PS surfaces +* svg: add a new function to specify the SVG document unit + (Bug #90166) +* Use UTF-8 filenames on Windows + + +API Changes +----------- +Several new APIs were added. No existing APIs were altered. + +New PDF functionality: + + * cairo_pdf_surface_add_outline + * cairo_pdf_surface_set_metadata + * cairo_pdf_surface_set_page_label + * cairo_pdf_surface_set_thumbnail_size + * cairo_tag_begin + * cairo_tag_end + * CAIRO_STATUS_TAG_ERROR + +New error status items for problems relating to PDF tagging: + + * CAIRO_STATUS_WIN32_GDI_ERROR + * CAIRO_STATUS_FREETYPE_ERROR + * CAIRO_STATUS_PNG_ERROR + + New error status items for handling of GDI, libfreetype, and libpng + errors, respectively. + + +Setting up Win32 surfaces for HDC with alpha channels: + + * cairo_win32_surface_create_with_format + + New API for added PDF functionality (see above), and new error + status item for problems relating to PDF tagging. + +Variable fonts: + + * cairo_font_options_get_variations + * cairo_font_options_set_variations + +Tracking units in SVG documents: + + * cairo_svg_surface_set_document_unit + * cairo_svg_surface_get_document_unit + + + +Dependency Changes +------------------ +None + + +Performance Optimizations +------------------------- +None + + +Notable Bug Fixes +----------------- +* Fix thin lines that don't show up when printing in Inkscape due to + overly aggressive culling. + (Bug #77298) +* Fix playback of recording surfaces into PDF surfaces, where objects + with negative coordinates were not getting drawn. To address this, + the coordinate systems for PDF and PS have been changed to match + cairo's coordinate system. This allows recording surfaces to be + emitted in cairo coordinates, and results in the same origin being + used for all operations when using the recording surface XObject. + Test cases for PDF and PS have also been updated accordingly. + (Bug #89232) +* Fix "invalidfont" error on some printers when printing PDFs with + embedded fonts that have glyphs (such as spaces) with + num_contours == 0. (Bug #79897) +* Fix missing glyphs such as thin dashes, which get scaled to 0 in + userspace and thus have their drawing operations culled. (Bug #94615) +* Fix other oddities caused by variously idiosyncratic fonts. +* Fix a data race in freed_pool discovered by Firefox's cairo usage. + The patch adads atomic int load and store functions, with relaxed + memory ordering. (Bug #90318) +* Handle SOURCE and CLEAR operators when painting color glyphs. + (Bug #102661) +* Fix falling back to system font with PDFs using certain embedded + fonts, due to truncated font names. + (Bug #103249) +* Prevent curved strokes in small ctms from being culled from vector + surfaces + (Bug #103071) +* Fix assertion hit with PDFs using Type 4 fonts rendered with user + fonts, due to error when destroying glyph page. + (Bug #103335) +* Prevent invalid ptr access for > 4GB images. + (Bug #98165) +* pdf: Fix internal links pointing to other pages, by pre-calculating + page heights so that link positions can be calculated more accurately. +* Fix error reporting in the xcb backend if fallback fails. Instead of + returning NULL when the X11 server can't do some operation, return a + surface in an error state. +* Clarify documentation regarding device scale inheritance and the units + used in cairo_surface_create_similar_image. + (Bug #99094) +* Call XSync in the xlib backend before setting the error handler to + ignore errors for certain requests, to make sure all pending errors + are handled first. +* Fix regression with text containing space character on Win32. + (Bug: https://gitlab.freedesktop.org/cairo/cairo/issues/339) + +For a more comprehensive listing of fixed bugs, see the release notes for the +individual 1.15.x releases. + + +Release 1.15.14 (2018-09-19 Bryce Harrington ) +============================================================================ +We're nearly ready to finalize the 1.16.0 release, so this snapshot +can be considered a beta for 1.16. + +The most notable change this release is a performance optimization for +windows, discussed below. Other than that, much of the development +focus was on final polish and stability as we prepare for 1.16. + +Some attention went into getting the testsuite passing at least for the +image backend. The Cairo testsuite depends on external software like +Pixman, and changes in the rendering behavior of these dependencies +change test behavior, leading to false positives. + +Results from the Coverity static testing tool were also reviewed. Most +of the issues flagged were false positives, but there were several +legitimate problems found and fixed. + +For a complete log of changes, please see + + https://cairographics.org/releases/ChangeLog.1.15.12 + +Features and Enhancements +------------------------- +* Add more FreeeType font color conversions to support COLR/CPAL +* Update test reference images against current pixman + +API Changes +----------- +None + +Dependency Changes +------------------ None +Performance Optimizations +------------------------- +Vasily Galkin introduced a Win32 performance optimization for +CAIRO_OPERATOR_SOURCE when copying data from a backbuffer to an argb32 +surface corresponding to a Win32 DC. With this, argb32 drawing should +perform as fast as typical dibsection-buffered GDI drawing. See the +Cairo mailing list for April 2018 for data and discussion of the +performance improvements. + + +Bug Fixes +--------- +* Fix crash when rendering Microsoft's Segoe UI Emoji Regular font. +* Fix build breakage with glesv3 enabled due to non-existant glesv3.pc. +* Fix memory leaks found by Coverity +* Fix incorrect null ptr handling found by Coverity +* Fix test compilation when font-config is disabled +* Use _cairo_malloc instead of malloc (Bug #101547) (CVE-2017-9814) +* Fix assertion failure in the freetype backend (Bug #105746) + + +Release 1.15.12 (2018-04-04 Bryce Harrington ) +======================================================================== +The main focus for this release is the addition of Variable Font +support. Variable fonts are single font files with various typography +characteristics, such as weight or slant, that users of the font can +adjust between two points. Effectively this enables a single font to +behave as multiple fonts. + +The Skia backend is disabled in this release, due to severe bitrot, and +will be removed in future releases. Contact the cairo team if you have +a need of this backend. + +For a complete log of changes, please see + + https://cairographics.org/releases/ChangeLog.1.15.12 + +Features and Enhancements +------------------------- +* Variable font support +* Skia backend is disabled + API Changes ----------- +* cairo_font_options_get_variations() and + cairo_font_options_set_variations() are added. + +Dependency Changes +------------------ +None + +Performance Optimizations +------------------------- None +Bug Fixes +--------- +* Fix errors in csi-trace --help and --version options +* Fix a 'memory leak' in the image compositor, with + pixman_glyph_cache_t. +* Fix access of uninitialized memory found by valgrind + (Bug #91271) +* Fix improper initialization of memory in + _cairo_ft_font_face_create_for_pattern() + (Bug #105084) +* Fix multi-monitor virtual desktop with negative coords on Win32 + (Bug #100793) +* Fix issues occuring with older FreeType versions. + + +Release 1.15.10 (2017-12-07 Bryce Harrington ) +======================================================================== +This release adds GLESv3 support to the cairo_gl backend, adds +tracking of SVG units in generated svg documents, and cleans up numerous +test failures and related issues in the PDF and Postscript backends. + +For a complete log of changes, please see + + https://cairographics.org/releases/ChangeLog.1.15.10 + +Features and Enhancements +------------------------- +* Add support for OpenGL ES 3.0 to the gl backend. +* Use Reusable streams for forms in Level 3 Postscript. +* Add CAIRO_MIME_TYPE_EPS mime type for embedding EPS files. +* Add CCITT_FAX mime type for PDF and PS surfaces +* svg: add a new function to specify the SVG document unit + (Bug #90166) +* Use UTF-8 filenames on Windows + +API Changes +----------- +* cairo_svg_surface_set_document_unit() and + cairo_svg_surface_get_document_unit() + Dependency Changes ------------------ None @@ -25,35 +295,114 @@ None Bug Fixes --------- -* Fix assertion hit with PDFs using Type 4 fonts rendered with user - fonts, due to error when destroying glyph page. - (Bug #103335) -* Fix build error with util/font-view -* Fix handling of truetype fonts with excessively long font names - (Bug #103249) -* Fix falling back to system font with PDFs using certain embedded - fonts, due to truncated font names. - (Bug #103249) +* Fix regression in gles version detection +* Fix undefined-behavior with integer math. +* Handle SOURCE and CLEAR operators when painting color glyphs. + (Bug #102661) +* Convert images to rgba or a8 formats when uploading with GLESv2 +* Use _WIN32 instead of windows.h to check for windows build. * Fix sigabrt printing documents with fonts lacking the mandatory .nodef glyph. (Bug #102922) -* Fix undefined-behavior with integer math. -* Fix various warnings and typos +* Prevent curved strokes in small ctms from being culled from vector + surfaces + (Bug #103071) +* Fix painting an unbounded recording surface with the SVG backend. +* Fix falling back to system font with PDFs using certain embedded + fonts, due to truncated font names. + (Bug #103249) +* Fix handling of truetype fonts with excessively long font names + (Bug #103249) +* Fix race conditions with cairo_mask_compositor_t + (Bug #103037) +* Fix build error with util/font-view +* Fix assertion hit with PDFs using Type 4 fonts rendered with user + fonts, due to error when destroying glyph page. + (Bug #103335) +* Set default creation date for PDFs +* Prevent invalid ptr access for > 4GB images. + (Bug #98165) +* Prevent self-copy infinite loop in Postscript surface. +* Fix padded image crash in Postscript surface. +* Fix annotation bugs in PDFs and related memory leaks +* Fix test failures and other assorted issues in ps and pdf code. +* Fix code generation when using GCC legacy atomic operations + (Bug #103559) +* Fix various compilation warnings and errors. +* Fix various distcheck errors with private symbols, doxygen formatting, + etc. + +Release 1.15.8 (2017-08-29 Bryce Harrington ) +======================================================================== +This small snapshot provides new colored emoji glyph support, and a +handful of minor fixes. +For a complete log of changes, please see -Release 1.14.10 (2017-06-13 Bryce Harrington ) -======================================================================== -Bugfix release rolling up backported fixes for the past half year. + https://cairographics.org/releases/ChangeLog.1.15.8 -For a complete log of changes since 1.14.8, please see: +Features and Enhancements +------------------------- +* Support colored emoji glyphs, stored as PNG images in OpenType fonts. - http://cairographics.org/releases/ChangeLog.cairo-1.14.10 +API Changes +----------- +None -Features --------- +Dependency Changes +------------------ +None + +Performance Optimizations +------------------------- None +Bug Fixes +--------- + +* pdf: Fix internal links pointing to other pages, by pre-calculating + page heights so that link positions can be calculated more accurately. + +* image: Fix crash on negative lengths + +* win32: Fix initialization of mutexes for static builds + +* pdf: Don't emit /PageLabel dict when no labels defined + +* font: Fix color font loading on big-endian systems + +* font: Fix color font support infinite-loop with empty glyphs + +* Fix off by one check in cairo-image-info.c + + + +Release 1.15.6 (2017-06-13 Bryce Harrington ) +======================================================================== +This new snapshot incorporates changes over the past half-year since the +1.15.4 snapshot, including all the fixes from the 1.14 release series. + +The PDF code continues to be enhanced, and we're restored MacOSX 10.4 +support. Font-related fixes and improved error handling for X round out +the release. + +For a complete log of changes, please see + + https://cairographics.org/releases/ChangeLog.1.15.6 + + +Features and Enhancements +------------------------- +* Detect if variable fonts have synthesized bold/italic or non-default + variants, and use a fallback font where needed. + +* Restore MacOSX 10.4 support. Cairo had dropped 10.4 support when + moving to the CoreText API. Now we automatically detect which API to + use via dynamic linking, so can resume supporting this older version + of MacOSX. + + API Changes ----------- None @@ -68,10 +417,6 @@ None Bug Fixes --------- -* Clarify documentation regarding device scale inheritance and the units - used in cairo_surface_create_similar_image. - Bug #99094. - * Fix error reporting in the xcb backend if fallback fails. Instead of returning NULL when the X11 server can't do some operation, return a surface in an error state. @@ -80,39 +425,70 @@ Bug Fixes ignore errors for certain requests, to make sure all pending errors are handled first. -* For opentype fonts, always use gid to lookup glyph. - -* If glyph 0 used for rendering, remap to different index. - -* Set font size to em size when retrieving unhinted metrics. +* Fix text-glyph-range for quartz-font. Use 0xFFFF instead of 0 for + invalid index tracking. -* Flush ASCII85Decode file after use with Postscript files. +* Fix handling of Supplementary Multilingual Plane (SMP) Unicode + characters in quartz-font. -* pdf: Don't fail subsetting if unable to convert utf8 to utf16. +* Fix various issues in the drm backend including updating API usage and + general code cleanup. -* For truetype, reverse cmap search should end when 0xffff- 0xffff range - reached. - -* Fix bug in line wrapping with the PDF operators. +* Clarify documentation regarding device scale inheritance and the units + used in cairo_surface_create_similar_image. + Bug #99094. -* Fix an off by one check in cairo-image-info.c. +Release 1.15.4 (2016-12-9 Bryce Harrington ) +======================================================================= +This new snapshot incorporates changes over the past year since the +1.15.2 snapshot, including all the fixes from the 1.14 release series. -Release 1.14.8 (2016-12-07 Bryce Harrington ) -======================================================================== -Bugfix release rolling up backported fixes for the past year. +Of particular note in this snapshot is a wealth of work by Adrian +Johnson to enhance PDF support, as well as numerous bug fixes provided +by him and other contributors. -For a complete log of changes since 1.14.6, please see: +For a complete log of changes since the last release, please see: - http://cairographics.org/releases/ChangeLog.cairo-1.14.8 + https://cairographics.org/releases/ChangeLog.1.15.4 Features -------- -None +* The PDF backend has gained support for a range of widely used + features, including thumbnails, page labels, metadata, document + outlines, structured text, hyperlinks, and tags. Tags permit adding + logical info such as headings, tables, figures, etc. that facilitates + indexing, accessibility, text reflow, searching, and extraction of the + tagged items to other software. For details on this new PDF + functionality, see: + + https://lists.cairographics.org/archives/cairo/2016-June/027427.html + API Changes ----------- -None + + cairo_win32_surface_create_with_format + + Added a cairo API to set up Win32 surfaces for HDC with alpha channels. + + cairo_pdf_surface_add_outline + cairo_pdf_surface_set_metadata + cairo_pdf_surface_set_page_label + cairo_pdf_surface_set_thumbnail_size + cairo_tag_begin + cairo_tag_end + CAIRO_STATUS_TAG_ERROR + + New API for added PDF functionality (see above), and new error + status item for problems relating to PDF tagging. + + CAIRO_STATUS_WIN32_GDI_ERROR + CAIRO_STATUS_FREETYPE_ERROR + CAIRO_STATUS_PNG_ERROR + + New error status items for handling of GDI, libfreetype, and libpng + errors, respectively. Dependency Changes ------------------ @@ -124,22 +500,131 @@ None Bug Fixes --------- +* Bug fixes from 1.15.2 (see the 1.15.2 NEWS for details) + +* Fix playback of recording surfaces into PDF surfaces, where objects + with negative coordinates were not getting drawn. To address this, + the coordinate systems for PDF and PS have been changed to match + cairo's coordinate system. This allows recording surfaces to be + emitted in cairo coordinates, and results in the same origin being + used for all operations when using the recording surface XObject. + Test cases for PDF and PS have also been updated accordingly. + (Bug #89232) + * Fix "invalidfont" error on some printers when printing PDFs with embedded fonts that have glyphs (such as spaces) with num_contours == 0. (Bug #79897) + +* Fix missing glyphs such as thin dashes, which get scaled to 0 in + userspace and thus have their drawing operations culled. (Bug #94615) + +* Fix other oddities caused by variously idiosyncratic fonts. + * Fix deadlock when destruction of a scaled font indirectly triggers destruction of a second scaled font, causing the global cache to be locked twice. (Bug #93891) + * Fix X errors reported to applications when shmdt() is called before the Attach request is processed, due to missing xcb and xlib calls. + * Fix random failure in record-paint-alpha-clip-mast test case, caused by an incorrect assumption that a deferred clear can be skipped. (Bug #84330) + * Fix crash when dealing with an XShmGetImage() failure, caused by a double free in _get_image_surface(). (Bug #91967) -* Fix build issue when using non-GNU strings utility. (Bug #88639) + +* Fix invalid execution of ASCII85 data by the PS interpreter that the + image operator didn't use, by flushing the extraneous data after + drawing the image. (Bug #84811) + +* Fix decoding of Adobe Photoshop's inverted CMYK JPEG files in PDF + export. + +* Fix unbounded surface assertion in win32-print code. + +* Fix a data race in freed_pool discovered by Firefox's cairo usage. + The patch adads atomic int load and store functions, with relaxed + memory ordering. (Bug #90318) + * Cleanup debugging text sent to stdout instead of log. (Bug #95227) +* Fix build issue when using non-GNU strings utility. (Bug #88639) + +* Fix build of cairo modules as regular modules, not as versioned shared + libaries. (Bug #29319) + +* Fix build on win32 using gcc 5.4. + +* Fix build of script backend to require zlib. + +* Update test suite reference images using Debian Jessie 64-bit and + poppler current as of June, 2016. + +* Various improvements to documentation and tests, compiler warning + fixes, and an assortment of code refactoring and cleanup. + + +Release 1.15.2 (2015-12-10 Bryce Harrington ) +======================================================================== +This release is largely a rollup to include a variety of fixes that +didn't make the cut for the stable 1.14.2 and 1.14.4 releases, as well +as all the fixes from those releases. Notably this includes a highly +requested new API for Win32 surfaces. + +For a complete log of changes since the last release, please see: + + https://cairographics.org/releases/ChangeLog.1.15.2 + +Features +-------- +None + +API Changes +----------- + + cairo_win32_surface_create_with_format + + Added a cairo API to set up Win32 surfaces for HDC with alpha channels. + +Dependency Changes +------------------ +None + +Performance Optimizations +------------------------- +None + +Bug Fixes +--------- +* All the bug fixes from 1.14.2, 1.14.4, and 1.14.6 + +* Fix xcb/xlib compilation and calls. Make image boxes behave when SHM + is not available. + +* Fix various issues with printing and transparent images on Win32. + +* Fix thin lines that don't show up when printing in Inkscape due to + overly aggressive culling. + (Bug #77298) + +* Fix broken printing via pdf when glyph 0 is used for rendering, + resulting in missing spaces and letters. + (Bug #89082) + +* Fix crash for certain glyphs in opentype fonts. + (Bug #91902) + +* Fix incorrect rendering of SVG paths with more than one subpath. If + more than one trap is passed in then it's guaranteed that the returned + traps will have their left edge to the left of their right edge, but + if only one trap is passed in then the function always returns without + doing anything. + (Bug #90984) + +* Improve rendering with Quartz to better match pixman's blending and + filtering behavior. + Release 1.14.6 (2015-12-09 Bryce Harrington ) ======================================================================== @@ -147,7 +632,7 @@ Simple bugfix release to fix one Windows issue. For a complete log of changes since 1.14.4, please see: - http://cairographics.org/releases/ChangeLog.cairo-1.14.6 + https://cairographics.org/releases/ChangeLog.1.14.6 Features -------- @@ -182,9 +667,8 @@ cleanup of warnings and memory leaks, correction of misspellings, updates to documentation, etc. For a complete log of changes since 1.14.2, please see: - - http://cairographics.org/releases/ChangeLog.cairo-1.14.4 - + + https://cairographics.org/releases/ChangeLog.cairo-1.14.4 Features -------- @@ -260,7 +744,7 @@ Bug Fixes with XCB. -Release 1.14.2 (2014-03-09 Bryce Harrington ) +Release 1.14.2 (2015-03-09 Bryce Harrington ) ==================================================================== This release provides collected bug fixes, along with one feature enhancement for the xcb backend, and a small performance improvement for @@ -335,6 +819,7 @@ Bug Fixes (fdo bugs #89338, #89340, #89356, #89354) * Fix various documentation warnings and errors + Release 1.14.0 (2014-10-13 Bryce Harrington ) ==================================================================== Hard to believe it's been over a year since our last release, but it's @@ -836,7 +1321,7 @@ Bug fixes and then back again to user coordinates (cairo_copy_path, cairo_append_path) https://bugs.freedesktop.org/show_bug.cgi?id=54732 - + Fix extents computations for a degenerate path consisting only of a move-to https://bugs.freedesktop.org/show_bug.cgi?id=54549 @@ -844,7 +1329,7 @@ Bug fixes Prevent crashing on a degenerate project edge after polygon intersection https://bugs.freedesktop.org/show_bug.cgi?id=54822 - + Release 1.12.2 (2012-04-29 Chris Wilson ) @@ -864,7 +1349,7 @@ Bug fixes Allow applications to create 0x0 xlib surfaces, such as used by LibreOffice. https://bugs.freedesktop.org/show_bug.cgi?id=49118 - + Trim composite extents for SOURCE/CLEAR operators to the mask. Use fallback fonts in PDF for unhandled computed glyph widths @@ -1178,7 +1663,7 @@ drawing commands made by an application. This can be used to inspecting applications to understand issues and as a means for profiling real-world usage of cairo. -The traces generated by cairo-trace have been collected in +The traces generated by cairo-trace have been collected in git://git.cairographics.org/git/cairo-traces @@ -1394,7 +1879,7 @@ API additions The Cairo region API was actually added a couple of snapshots ago, but we forgot to mention it at the time. A simple API for the handling of rectangular pixel-aligned regions by Soeren Sandmann. - + Backend-specific improvements ----------------------------- @@ -1599,10 +2084,10 @@ New experimental backends: QT OpenVG - The initial work was done by Øyvind KolÃ¥s, and made ready for - inclusion by Pierre Tardy. + inclusion by Pierre Tardy. OpenGL - An advanced OpenGL compositor. The aim is to write a integrate - directed rendering using OpenGL at a high-level into Cairo. In + directed rendering using OpenGL at a high-level into Cairo. In contrast to the previous attempt using Glitz which tried to implement the RENDER protocol on top of OpenGL, using the high-level interface should permit greater flexibility and @@ -1801,14 +2286,14 @@ A few FreeType font handling bugs were fixed: Don't call FT_Done_Face() on faces we did not create zombie ft_font_face / ft_unscaled_font mutual referencing problems - http://bugs.freedesktop.org/show_bug.cgi?id=21706 + https://bugs.freedesktop.org/show_bug.cgi?id=21706 Ensure win32 font backend sets the return value to -1 (indicating the absent glyph) if the font index lookup for the unicode character fails. And similarly fix a bug where a fatal error was raised for an invalid glyph. cairo_scaled_font_glyph_extents breaks with invalid glyph id - http://bugs.freedesktop.org/show_bug.cgi?id=20255 + https://bugs.freedesktop.org/show_bug.cgi?id=20255 Various improvements to the documentation, reported by Truc Troung: @@ -1838,7 +2323,7 @@ Build fixes Fix build of DirectFB backend with debugging enabled: Bug in _cairo_directfb_surface_release_source_image function - http://bugs.freedesktop.org/show_bug.cgi?id=18322 + https://bugs.freedesktop.org/show_bug.cgi?id=18322 Fix build on OS/2. @@ -1856,12 +2341,12 @@ Invalid referencing of patterns in the Quartz backend: Failed assertion `CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count)' when using cairo quartz backend - http://bugs.freedesktop.org/show_bug.cgi?id=18632 + https://bugs.freedesktop.org/show_bug.cgi?id=18632 Invalid references to glyphs after early culling, causing segmentation faults in the PDF backend: - http://lists.cairographics.org/archives/cairo/2008-December/015976.html + https://lists.cairographics.org/archives/cairo/2008-December/015976.html Check for XRender in the XCB backend, or else we may attempt an invalid memory access: @@ -1904,7 +2389,7 @@ Fix display of user fonts as exercised by proposed support for type3 fonts in poppler (unsigned promotion fixes): Use cairo user-font for Type 3 fonts - http://lists.freedesktop.org/archives/poppler/2008-October/004181.html + https://lists.freedesktop.org/archives/poppler/2008-October/004181.html Avoid miscomputing size of fallback images required when rendering with CLEAR, IN, or SOURCE operator to vector surfaces, (PS, PDF, SVG, @@ -1913,7 +2398,7 @@ etc.). Be more tolerant of broken fonts when subsetting type1 fonts: Error handling in cairo_type1_font_subset_get_glyph_names_and_widths - http://lists.cairographics.org/archives/cairo/2008-October/015569.html + https://lists.cairographics.org/archives/cairo/2008-October/015569.html Fix cairo_fill_extents, cairo_stroke_extents, cairo_path_extents, to correctly allow NULL parameters as documented. @@ -1983,10 +2468,10 @@ extents of transformed, filtered surfaces (Owen Taylor, Carl Worth, and Chris Wilson): Bad clipping with EXTEND_NONE - http://bugs.freedesktop.org/show_bug.cgi?id=15349 + https://bugs.freedesktop.org/show_bug.cgi?id=15349 Improve filtering handling in cairo-pattern.c - http://bugs.freedesktop.org/show_bug.cgi?id=15367 + https://bugs.freedesktop.org/show_bug.cgi?id=15367 Many thanks to Chris Wilson for digging out and cleaning up these fixes. @@ -2214,7 +2699,7 @@ xlib: Faster bookkeeping (Karl Tomlinson) PS: Fix gradients with non-constant alpha (Chris Wilson) Fix deadlock in user-font code (Richard Hughes and Behdad Esfahbod) - http://bugs.freedesktop.org/show_bug.cgi?id=16819 + https://bugs.freedesktop.org/show_bug.cgi?id=16819 Countless other bugs have been fixed and optimizations made, many of them thanks to Chris Wilson. Thanks Chris and others! @@ -2296,7 +2781,7 @@ xlib: Faster bookkeeping (Karl Tomlinson) PS: Fix gradients with non-constant alpha (Chris Wilson) Fix deadlock in user-font code (Richard Hughes and Behdad Esfahbod) - http://bugs.freedesktop.org/show_bug.cgi?id=16819 + https://bugs.freedesktop.org/show_bug.cgi?id=16819 Several other minor fixes. @@ -2557,10 +3042,10 @@ This fix has been tested to resolve the bugs posted here, (for both Xerox and Dell printers): Printing some PDFs from evince is crashing our Xerox printer - http://bugs.freedesktop.org/show_bug.cgi?id=15348 + https://bugs.freedesktop.org/show_bug.cgi?id=15348 Cairo-generated postscript blocks Dell 5100cn - http://bugs.freedesktop.org/show_bug.cgi?id=15445 + https://bugs.freedesktop.org/show_bug.cgi?id=15445 Add missing locking in cairo-xlib --------------------------------- @@ -2588,7 +3073,7 @@ New dependency on external pixman library (Thanks, Søren!) As of cairo 1.6, cairo now depends on the pixman library, for which the latest release can be obtained alongside cairo: - http://cairographics.org/releases/pixman-0.10.0.tar.gz + https://cairographics.org/releases/pixman-0.10.0.tar.gz This library provides all software rendering for cairo, (the implementation of the image backend as well as any image fallbacks @@ -2626,7 +3111,7 @@ to, (and we could use help from users that have access to misbehaving printers). This bug is being tracked here: Printing some PDFs from evince is crashing our Xerox printer - http://bugs.freedesktop.org/show_bug.cgi?id=15348 + https://bugs.freedesktop.org/show_bug.cgi?id=15348 New support for arbitrary X server visuals (Thanks, Keith and Behdad!) ---------------------------------------------------------------------- @@ -2694,7 +3179,7 @@ Rendering with CAIRO_ANTIALIAS_NONE has been fixed to be more predictable, (previously image rendering and geometry rendering would be slightly misaligned with respect to each other). -The reference manual at http://cairographics.org/manual now documents +The reference manual at https://cairographics.org/manual now documents 100% of the functions and types in cairo's public API. API additions @@ -2931,7 +3416,7 @@ general Cairo now depends on pixman 0.10.0 which was recently released. The latest pixman release can always be found alongside cairo releases at: - http://cairographics.org/releases + https://cairographics.org/releases Increase the precision of color stops for gradients. This fixes a regression in gradient rendering that had been present since the @@ -3041,7 +3526,7 @@ Rename ATSUI font backend to Quartz font backend. This affects the following usage: --enable-atsui -> --enable-quartz-font - CAIRO_HAS_ATSUI_FONT -> CAIRO_HAS_QUARTZ_FONT + CAIRO_HAS_ATSUI_FONT -> CAIRO_HAS_QUARTZ_FONT CAIRO_FONT_TYPE_ATSUI -> CAIRO_FONT_TYPE_QUARTZ cairo_atsui_font_face_create_for_atsu_font_id -> @@ -3093,7 +3578,7 @@ cairo-svg --------- Fix stroke of path with a non-solid-color source pattern: - http://bugs.freedesktop.org/show_bug.cgi?id=14556 + https://bugs.freedesktop.org/show_bug.cgi?id=14556 cairo-quartz ------------ @@ -3104,7 +3589,7 @@ cairo_show_text()/cairo_show_glyphs(). Correctly handle gradients with non-identity transformations: - Fixes http://bugs.freedesktop.org/show_bug.cgi?id=14248 + Fixes https://bugs.freedesktop.org/show_bug.cgi?id=14248 Add native implementation of REPEAT and REFLECT extend modes for gradients. @@ -3231,7 +3716,7 @@ Add new API for efficiently using image data as a source: For full documentation, see: - http://cairographics.org/manual/cairo-Quartz-Surfaces.html#cairo-quartz-image-surface-create + https://cairographics.org/manual/cairo-Quartz-Surfaces.html#cairo-quartz-image-surface-create Several fixes for cairo_mask(). @@ -3606,14 +4091,14 @@ So users will need to acquire and build pixman before being able to build cairo. The current release is 0.9.6 and can be obtained from here: - http://cairographics.org/releases/pixman-0.9.6.tar.gz + https://cairographics.org/releases/pixman-0.9.6.tar.gz which can be verified with: - http://cairographics.org/releases/pixman-0.9.6.tar.gz.sha1 + https://cairographics.org/releases/pixman-0.9.6.tar.gz.sha1 66f01a682c64403a3d7a855ba5aa609ed93bcb9e pixman-0.9.6.tar.gz - http://cairographics.org/releases/pixman-0.9.6.tar.gz.sha1.asc + https://cairographics.org/releases/pixman-0.9.6.tar.gz.sha1.asc (signed by Carl Worth) Major PDF/PostScript improvements @@ -3854,8 +4339,8 @@ complain that some cleanup work is already done, but there you have it.) This fixes the bug causing OpenOffice.org to crash as described here: - XError on right click menus in OOo. - https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=243811 + XError on right click menus in OOo. + https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=243811 Use IncludeInferiors when using xlib surface as a source (Ryan Lortie) ---------------------------------------------------------------------- @@ -3919,7 +4404,7 @@ bugs had perhaps never been hit by any users. But at least one was hit by the gnome-about program which resulted in dozens of duplicated bug reports against that program: - http://bugzilla.gnome.org/show_bug.cgi?id=431990 + https://bugzilla.gnome.org/show_bug.cgi?id=431990 We were very pleasantly surprised to see this bug get fixed as a side-effect of Chris's work. Well done, Chris! @@ -4035,16 +4520,16 @@ notes on using it: To build, do: - make malloc-stats.so + make malloc-stats.so inside util/, and to use, run: - LD_PRELOAD=malloc-stats.so some-program + LD_PRELOAD=malloc-stats.so some-program For binaries managed by libtool, eg, cairo-perf, do: - ../libtool --mode=execute /bin/true ./cairo-perf - LD_PRELOAD="../util/malloc-stats.so" .libs/lt-cairo-perf + ../libtool --mode=execute /bin/true ./cairo-perf + LD_PRELOAD="../util/malloc-stats.so" .libs/lt-cairo-perf Finally, the cairo-perf-diff-files utility was enhanced to allow for generating performance reports from several runs of the same backend @@ -4116,7 +4601,7 @@ PDF: Johnson) • Fix glyph positioning bug when glyphs are not horizontal - http://lists.freedesktop.org/archives/cairo/2007-April/010337.html + https://lists.freedesktop.org/archives/cairo/2007-April/010337.html win32: • Fix crash when rendering with bitmap fonts (Carl Worth) @@ -4167,7 +4652,7 @@ Critical fixes • Fix a crash due to a LOCK vs. UNLOCK typo (M. Drochner fixing Carl Worth's embarrassing typo). - http://bugs.freedesktop.org/show_bug.cgi?id=10235 + https://bugs.freedesktop.org/show_bug.cgi?id=10235 • Fix potential buffer overflow, which on some systems with a checking variant of snprintf would lead to a crash (Adrian Johnson, Stanislav @@ -4212,7 +4697,7 @@ Other bug fixes PDF output in some viewers. (Adrian Johnson, Adam Goode, and MenTaLguY). - http://lists.freedesktop.org/archives/cairo/2006-November/008551.html + https://lists.freedesktop.org/archives/cairo/2006-November/008551.html • win32: Return correct metrics when hinting is off, and fix font descent computation (Behdad Esfahbod). @@ -4929,7 +5414,7 @@ several improvements. The bug fixes in this snapshot include: mentioned here: CAIRO_BO_GUARD_BITS and coordinate space? - http://lists.freedesktop.org/archives/cairo/2006-December/008743.html + https://lists.freedesktop.org/archives/cairo/2006-December/008743.html * Fix several regressions in new tessellator (M Joonas Pihlaja) @@ -4989,7 +5474,7 @@ performance improvements are as follows: His own writeup of the work he did is quite thorough, but more than can be quoted here. Please see his post for the interesting details: - http://lists.freedesktop.org/archives/cairo/2006-November/008483.html + https://lists.freedesktop.org/archives/cairo/2006-November/008483.html (Though note that this snapshot also includes some additional, significant improvements that were only sketched out in that @@ -5373,54 +5858,54 @@ here for such a short time period. Rendering fixes --------------- Fix image surfaces to not be clipped when used as a source (Vladimir Vukicevic) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=72e25648c4c4bc82ddd938aa4e05887a293f0d8b +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=72e25648c4c4bc82ddd938aa4e05887a293f0d8b Fix a couple of corner cases in dashing degenerate paths (Jeff Muizelaar) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=fbb1758ba8384650157b2bbbc93d161b0c2a05f0 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=fbb1758ba8384650157b2bbbc93d161b0c2a05f0 Fix support for type1 fonts on win32 (Adrian Johnson) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=da1019c9138695cb838a54f8b871bbfd0e8996d7 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=da1019c9138695cb838a54f8b871bbfd0e8996d7 Fix assertion failure when rotating bitmap fonts (Carl Worth) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=0bfa6d4f33b8ddb5dc55bbe419c15df4af856ff9 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=0bfa6d4f33b8ddb5dc55bbe419c15df4af856ff9 Fix assertion failure when calling cairo_text_path with bitmap fonts (Carl Worth) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=9878a033531e6b96b5f27e69e10e90dee7440cd9 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=9878a033531e6b96b5f27e69e10e90dee7440cd9 Fix mis-handling of cairo_close_path in some situations (Tim Rowley, Carl Worth) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=53f74e59faf1af78f2f0741ccf1f23aa5dad4efc +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=53f74e59faf1af78f2f0741ccf1f23aa5dad4efc Respect font_matrix translation in _cairo_gstate_glyph_path (Behdad Esfahbod) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=f183b835b111d23e838889178aa8106ec84663b3 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=f183b835b111d23e838889178aa8106ec84663b3 Fix vertical metrics adjustment to work with non-identity shapes (Behdad Esfahbod) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=b7bc263842a798d657a95e539e1693372448837f +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=b7bc263842a798d657a95e539e1693372448837f [PS] Set correct ImageMatrix in _cairo_ps_surface_emit_bitmap_glyph_data (Behdad Esfahbod) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=d47388ad759b0a1a0869655a87d9b5eb6ae2445d +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=d47388ad759b0a1a0869655a87d9b5eb6ae2445d Build system fixes ------------------ Fix xlib detection to prefer pkg-config to avoid false libXt dependency (Behdad Esfahbod) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=0e78e7144353703cbd28aae6a67cd9ca261f1d68 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=0e78e7144353703cbd28aae6a67cd9ca261f1d68 Fix typos causing win32 build problem with PS,PDF, and SVG backends (Behdad Esfahbod) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=aea83b908d020e26732753830bb3056e6702a774 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=aea83b908d020e26732753830bb3056e6702a774 Fix configure cache to not use stale results (Behdad Esfahbod) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=6d0e3260444a2d5b6fb0cb223ac79f1c0e7b3a6e +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=6d0e3260444a2d5b6fb0cb223ac79f1c0e7b3a6e Fix to not pass unsupported warning options to the compiler (Jens Granseuer) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=97524a8fdb899de1ae4a3e920fb7bda6d76c5571 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=97524a8fdb899de1ae4a3e920fb7bda6d76c5571 Fix to allow env. variables such as png_REQUIRES to override configure detection (Jens Granseuer) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=abd16e47d6331bd3811c908e524b4dcb6bd23bf0 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=abd16e47d6331bd3811c908e524b4dcb6bd23bf0 Fix test suite to not use an old system cairo when converting svg2png (Behdad Esfahbod) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=6122cc85c8f71b1ba2df3ab86907768edebe1781 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=6122cc85c8f71b1ba2df3ab86907768edebe1781 Fix test suite to not require signal.h to be present (Behdad Esfahbod) -http://gitweb.freedesktop.org/?p=cairo;a=commit;h=6f8cf53b1e1ccdbe1ab6a275656b19c6e5120e40 +https://gitweb.freedesktop.org/?p=cairo;a=commit;h=6f8cf53b1e1ccdbe1ab6a275656b19c6e5120e40 Code cleanups ------------- @@ -5446,7 +5931,7 @@ affected X servers that do not provide the Render extension and that provide a visual with BGR rather than RGB channel order. report: https://bugs.freedesktop.org/show_bug.cgi?id=7294 -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=9ae66174e774b57f16ad791452ed44efc2770a59 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=9ae66174e774b57f16ad791452ed44efc2770a59 Fix the "disappearing text" bug ------------------------------- @@ -5460,7 +5945,7 @@ was also exacerbated by a KDE migration bug that caused antialiasing to be disabled more than desired. report: https://bugs.freedesktop.org/show_bug.cgi?id=7494 -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=456cdb3058f3b416109a9600167cd8842300ae14 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=456cdb3058f3b416109a9600167cd8842300ae14 see also: Xorg: https://bugs.freedesktop.org/show_bug.cgi?id=7681 KDE: http://qa.mandriva.com/show_bug.cgi?id=23990 @@ -5476,7 +5961,7 @@ than 72.0 would lead to incorrect results, (larger values would lead to increasingly shrunken output). report: https://bugs.freedesktop.org/show_bug.cgi?id=7533 -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=1feb4291cf7813494355459bb547eec604c54ffb +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=1feb4291cf7813494355459bb547eec604c54ffb Fix inadvertent semantic change of font matrix translation (Behdad Esfahbod) ---------------------------------------------------------------------------- @@ -5490,7 +5975,7 @@ practice, and it was not intentional to introduce a semantic change. With 1.2.2 we return to the 1.0 semantics, with a much better implementation that provides correct glyph metrics. -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=84840e6bba6e72aa88fad7a0ee929e8955ba9051 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=84840e6bba6e72aa88fad7a0ee929e8955ba9051 Fix create_similar to preserve fallback resolution and font options (Behdad Esfahbod) ------------------------------------------------------------------------------------- @@ -5502,8 +5987,8 @@ destination surface would not be preserved to the intermediate fallbacks, for example. report: https://bugs.freedesktop.org/show_bug.cgi?id=4106 -fixes: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=9fcb3c32c1f16fe6ab913e27eb54d18b7d9a06b0 - http://gitweb.freedesktop.org/?p=cairo;a=commit;h=bdb4e1edadb78a2118ff70b28163f8bd4317f1ec +fixes: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=9fcb3c32c1f16fe6ab913e27eb54d18b7d9a06b0 + https://gitweb.freedesktop.org/?p=cairo;a=commit;h=bdb4e1edadb78a2118ff70b28163f8bd4317f1ec xlib: Fix text performance regression from 1.0 to 1.2.0 (Vladimir Vukicevic) ---------------------------------------------------------------------------- @@ -5515,7 +6000,7 @@ to the X server, (such as a remote X server over an ssh connection). The slowdown was identified and fixed in 1.2.2. report: https://bugs.freedesktop.org/show_bug.cgi?id=7514 -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=b7191885c88068dad57d68ced69a752d1162b12c +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=b7191885c88068dad57d68ced69a752d1162b12c PDF: Eliminate dependency on FreeType library dependency (Adrian Johnson) ------------------------------------------------------------------------- @@ -5527,16 +6012,16 @@ freetype library is not required to use the pdf backend on the win32 platform. report: https://bugs.freedesktop.org/show_bug.cgi?id=7538 -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=a0989f427be87c60415963dd6822b3c5c3781691 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=a0989f427be87c60415963dd6822b3c5c3781691 PDF: Fix broken output on amd64 (Adrian Johnson) ------------------------------------------------ -report: http://bugzilla.gnome.org/show_bug.cgi?id=349826 -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=f4b12e497b7ac282b2f6831b8fb68deebc412e60 +report: https://bugzilla.gnome.org/show_bug.cgi?id=349826 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=f4b12e497b7ac282b2f6831b8fb68deebc412e60 PS: Fix broken output for truetype fonts > 64k (Adrian Johnson) --------------------------------------------------------------- -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=067d97eb1793a6b0d0dddfbd0b54117844511a94 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=067d97eb1793a6b0d0dddfbd0b54117844511a94 PDF: Fix so that dashing doesn't get stuck on (Kent Worsnop) ------------------------------------------------------------ @@ -5544,26 +6029,26 @@ Kent notices that with the PDF backend in cairo 1.2.0 as soon as a stroke was performed with dashing, all subsequent strokes would also be dashed. There was no way to turn dashing off again. -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=778c4730a86296bf0a71080cf7008d7291792256 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=778c4730a86296bf0a71080cf7008d7291792256 Fix memory leaks in failure paths in gradient creation (Alfred Peng) -------------------------------------------------------------------- -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=db06681b487873788b51a6766894fc619eb8d8f2 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=db06681b487873788b51a6766894fc619eb8d8f2 Fix memory leak in _cairo_surface_show_glyphs (Chris Wilson) ------------------------------------------------------------ report: https://bugs.freedesktop.org/show_bug.cgi?id=7766 -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=e2fddcccb43d06486d3680a19cfdd5a54963fcbd +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=e2fddcccb43d06486d3680a19cfdd5a54963fcbd Solaris: Add definition of cairo_private for some Sun compilers (Alfred Peng) ----------------------------------------------------------------------------- report: https://bugzilla.mozilla.org/show_bug.cgi?id=341874 -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=04757a3aa8deeff3265719ebe01b021638990ec6 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=04757a3aa8deeff3265719ebe01b021638990ec6 Solaris: Change version number of Sun's Xorg server with buggy repeat (Brian Cameron) ------------------------------------------------------------------------------------- report: https://bugs.freedesktop.org/show_bug.cgi?id=7483 -fix: http://gitweb.freedesktop.org/?p=cairo;a=commit;h=e0ad1aa995bcec4246c0b8ab0d5a5a79871ce235 +fix: https://gitweb.freedesktop.org/?p=cairo;a=commit;h=e0ad1aa995bcec4246c0b8ab0d5a5a79871ce235 Various memory leak fixes ------------------------- @@ -5612,7 +6097,7 @@ And at least the following bugs have been fixed: * PS/PDF: Fix broken placement for vertical glyphs * PS: Fix to not draw BUTT-capped zero-length dash segments * Do device offset before float->fixed conversion - http://bugzilla.gnome.org/show_bug.cgi?id=332266 + https://bugzilla.gnome.org/show_bug.cgi?id=332266 * PS: Fix source surfaces with transformations * PS: Fix to not draw BUTT-capped degnerate sub-paths * PS: Don't walk off end of array when printing "~>" @@ -5779,7 +6264,7 @@ This is the third in a series of snapshots working toward the imminent 1.2 release of cairo. For a list of items still needing work on the cairo 1.2 roadmap, please see: - http://cairographics.org/ROADMAP + https://cairographics.org/ROADMAP As can be seen in that list, there are no longer any API additions left on the roadmap. Instead, there is a feature (PDF type 3 fonts) a @@ -5874,7 +6359,7 @@ This is the second in a series of snapshots working toward the upcoming 1.2 release of cairo. For a list of items still needing work on the cairo 1.2 roadmap, please see: - http://cairographics.org/ROADMAP + https://cairographics.org/ROADMAP The items included in this snapshot (since the 1.1.2 snapshot) are described below. @@ -5887,9 +6372,9 @@ support this use case, we have added 4 new function calls that are specific to the PostScript backend: cairo_ps_surface_set_size - cairo_ps_surface_dsc_comment - cairo_ps_surface_dsc_begin_setup - cairo_ps_surface_dsc_begin_page_setup + cairo_ps_surface_dsc_comment + cairo_ps_surface_dsc_begin_setup + cairo_ps_surface_dsc_begin_page_setup These functions allow variation of the page size/orientation from one page to the next in the PostScript output. They also allow the toolkit @@ -7041,7 +7526,7 @@ Owen Taylor has converted cairo's documentation system to gtk-doc and has begun some long-needed work on the documentation, which can now be viewed online here: - http://cairographics.org/manual/ + https://cairographics.org/manual/ New backend: win32 ------------------ @@ -7073,7 +7558,7 @@ This is the first snapshot to include a functional win32 backend, And see also the documentation at: -http://cairographics.org/manual/cairo-Microsoft-Windows-Backend.html +https://cairographics.org/manual/cairo-Microsoft-Windows-Backend.html Disabled backend: quartz ------------------------ @@ -7102,14 +7587,14 @@ resolution. Further changes are described below. Added cairo_font_extents and cairo_font_glyph_extents. See documentation for details: - http://cairographics.org/manual/cairo-cairo-t.html#cairo-font-extents + https://cairographics.org/manual/cairo-cairo-t.html#cairo-font-extents cairo-ft.h ---------- The cairo_ft_font API changed considerably. Please see the documentation for details: - http://cairographics.org/manual/cairo-FreeType-Fonts.html + https://cairographics.org/manual/cairo-FreeType-Fonts.html Performance ----------- @@ -7175,23 +7660,23 @@ Major API changes cc `pkg-config --cflags --libs cairo` -o foo foo.c IMPORTANT: Users with old versions of cairo installed will need to - manually remove cairo.h and cairo-features.h from the - system include directories in order to prevent the old - headers from being used in preference to the new ones. + manually remove cairo.h and cairo-features.h from the + system include directories in order to prevent the old + headers from being used in preference to the new ones. 2) The backend-specific portions of the old monolithic cairo.h have been split out into individual public header files. The new files are: cairo-atsui.h - cairo-ft.h - cairo-glitz.h - cairo-pdf.h - cairo-png.h - cairo-ps.h + cairo-ft.h + cairo-glitz.h + cairo-pdf.h + cairo-png.h + cairo-ps.h cairo-quartz.h - cairo-xcb.h - cairo-xlib.h + cairo-xcb.h + cairo-xlib.h Applications will need to be modified to explicitly include the new header files where appropriate. @@ -7260,7 +7745,7 @@ is a port of Keith Packard's fdclock program originally written for the xlib backend. A screenshot of this program running on Mac OS X is available here: - http://cairographics.org/~cworth/images/fdclock-quartz.png + https://cairographics.org/~cworth/images/fdclock-quartz.png ATSUI font backend ------------------ @@ -7555,10 +8040,10 @@ Better text support This snapshot provides much better text support by implementing the following four functions: - cairo_text_extents - cairo_glyph_extents - cairo_text_path - cairo_glyph_path + cairo_text_extents + cairo_glyph_extents + cairo_text_path + cairo_glyph_path The text/glyph_extents functions can be used to determine the bounding box (and advance) for text as if drawn by show_text/glyphs. diff --git a/Build/source/libs/cairo/cairo-src/README b/Build/source/libs/cairo/cairo-src/README index 0be9947d548..0bcf140121a 100644 --- a/Build/source/libs/cairo/cairo-src/README +++ b/Build/source/libs/cairo/cairo-src/README @@ -1,5 +1,5 @@ Cairo - Multi-platform 2D graphics library -http://cairographics.org +https://cairographics.org What is cairo ============= @@ -35,25 +35,25 @@ Where to get more information about cairo ========================================= The primary source of information about cairo is: - http://cairographics.org/ + https://cairographics.org/ The latest versions of cairo can always be found at: - http://cairographics.org/download + https://cairographics.org/download Documentation on using cairo and frequently-asked questions: - http://cairographics.org/documentation - http://cairographics.org/FAQ + https://cairographics.org/documentation + https://cairographics.org/FAQ Mailing lists for contacting cairo users and developers: - http://cairographics.org/lists + https://cairographics.org/lists Roadmap and unscheduled things to do, (please feel free to help out): - http://cairographics.org/roadmap - http://cairographics.org/todo + https://cairographics.org/roadmap + https://cairographics.org/todo Dependencies ============ @@ -91,7 +91,7 @@ Supported, "standard" surface backends ------------------------------------ image backend (required) ------------------------ - pixman >= 0.30.0 http://cairographics.org/releases + pixman >= 0.30.0 https://cairographics.org/releases png support (can be left out if desired, but many ----------- applications expect it to be present) @@ -113,15 +113,15 @@ Supported, "platform" surface backends ----------------------------------- xlib backend ------------ - X11 http://freedesktop.org/Software/xlibs + X11 https://freedesktop.org/Software/xlibs xlib-xrender backend -------------------- - Xrender >= 0.6 http://freedesktop.org/Software/xlibs + Xrender >= 0.6 https://freedesktop.org/Software/xlibs quartz backend -------------- - MacOS X >= 10.5 with Xcode >= 3.0 + MacOS X >= 10.4 with Xcode >= 2.5 win32 backend ------------- @@ -129,7 +129,7 @@ Supported, "platform" surface backends xcb backend ----------- - XCB http://xcb.freedesktop.org + XCB https://xcb.freedesktop.org Font backends (required to have at least one) --------------------------------------------- @@ -181,12 +181,6 @@ Experimental surface backends packages and developer dependencies are available at Netlabs: ftp://ftp.netlabs.org/pub/cairo - skia backend - ------------ - Requires the skia library as of June 2014. Since skia is not - API stable, building against newer (or older) versions of skia - will probably fail. - Compiling ========= diff --git a/Build/source/libs/cairo/cairo-src/RELEASING b/Build/source/libs/cairo/cairo-src/RELEASING index 424902e9b68..8ac926e9bdd 100644 --- a/Build/source/libs/cairo/cairo-src/RELEASING +++ b/Build/source/libs/cairo/cairo-src/RELEASING @@ -1,5 +1,18 @@ Here are the steps to follow to create a new cairo release: +0) Decide type of release and checkout the appropriate branch. + + The Cairo project makes three types of releases: Development + snapshot releases, stable minor releases, and stable micro (aka + "point") releases. Micro releases should be only bugfixes and + no API additions. If there are API additions consider making a + Minor release. Snapshot releases can be done of the current + development tree between Minor releases, as desired. + + For stable releases (both minor and micro), the work should be + done on the given release branch. E.g. for 1.14.12, check out + the 1.14 branch via "git checkout origin/1.14 -b 1.14". + 1) Ensure that there are no local, uncommitted/unpushed mods. You're probably in a good state if both "git diff @@ -45,12 +58,6 @@ Here are the steps to follow to create a new cairo release: 3) Decide what the new version number for the release will be. - There are three types of releases: Minor, Micro, and - Snapshot. Micro releases should be only bugfixes and no API - additions. If there are API additions consider making a Minor - release. Snapshot releases can be done of the current - development tree between Minor releases, as desired. - Cairo uses even numbers for official releases, and odd numbers for development snapshots. Thus, for a Minor release it would be: @@ -76,8 +83,6 @@ Here are the steps to follow to create a new cairo release: LAST_RELEASE="X.Y.Z" # e.g. 1.15.2 THIS_RELEASE="X.Y.Z+2" # e.g. 1.15.4 - - 4) Fill out an entry in the NEWS file Sift through the logs since the last release. This is most @@ -99,7 +104,7 @@ Here are the steps to follow to create a new cairo release: Include a link to the incremental ChangeLog for this release, which we'll be uploading in a later step: - http://cairographics.org/releases/ChangeLog.cairo-${THIS_RELEASE} + https://cairographics.org/releases/ChangeLog.cairo-${THIS_RELEASE} 4) Increment cairo_version_{minor|micro} in cairo-version.h: @@ -117,12 +122,21 @@ Here are the steps to follow to create a new cairo release: Otherwise, (i.e. there are only bug fixes), increment cairo_version_micro to the next larger (even) number. -5) Commit the changes to NEWS and cairo-version.h +5) For Minor releases, add an index entry to doc/public/cairo-docs.xml + + Towards the end of the file, add a new section for the stable + release. It'll look something like: + + + Index of new symbols in X.Y + + +6) Commit the changes to NEWS and cairo-version.h It's especially important to mention the new version number in your commit log. -6) Run "make release-publish" which will perform the following steps +7) Run "make release-publish" which will perform the following steps for you: * Generate ChangeLog files out of git repository @@ -133,10 +147,10 @@ Here are the steps to follow to create a new cairo release: * Generate the final tar file * Generate an sha1sum file * Sign the sha1sum using your GPG setup (asks for your GPG password) - * scp the three files to appear on http://cairographics.org/releases + * scp the three files to appear on https://cairographics.org/releases * Generate a versioned manual and upload it to appear as both: - http://cairographics.org/manual-${THIS_RELEASE} - http://cairographics.org/manual + https://cairographics.org/manual-${THIS_RELEASE} + https://cairographics.org/manual * Place local copies of the three files in the releases directory * Create a LATEST-package-version file (after deleting any old one) * Tag the entire source tree with a ${THIS_RELEASE} tag, and sign @@ -159,26 +173,33 @@ Here are the steps to follow to create a new cairo release: previous versions, remove manual-${THIS_RELEASE} and release/cairo-${THIS_RELEASE}. -7) Update trunk (or the stable branch) version number. +8) Push the new tag out to the central tree with a command like: + + git push origin master ${THIS_RELEASE} + +9) Update master (or the stable branch) version number. - For Micro releases (X.Y.Z), increment cairo_version_micro to the - next larger (odd) number in cairo-version.h, commit, and push. + For Micro releases (X.Y.Z+2), increment cairo_version_micro to + the next larger (odd) number in cairo-version.h, commit, and + push. + + DEVEL_VERSION="X.Y.Z+1" # e.g. 1.15.10 -> 1.15.11 For Minor releases (X.Y.0), increment cairo_version_minor to the next larger (odd) number, and set cairo_version_micro to 1. Then commit and push. -8) Push the new tag out to the central tree with a command like: + DEVEL_VERSION="X.Y.Z+1" # e.g. 1.16.0 -> 1.17.1 - git push origin master ${THIS_RELEASE} + git commit cairo-version.h -m "Bump version for ${DEVEL_VERSION}" -9) Edit the cairo bugzilla product and add the new version numbers. +10) Edit the cairo bugzilla product and add the new version numbers. Note that you need to add two versions. One for the release/snapshot (with an even micro version), another with the post-release version (with an odd micro version). -10) Send out an announcement message. +11) Send out an announcement message. Send a message to cairo-announce@cairographics.org and CC cairo@cairographics.org, gnome-announce-list@gnome.org and @@ -189,5 +210,8 @@ Here are the steps to follow to create a new cairo release: git shortlog ${LAST_RELEASE}... -11) Add the announcement to the NEWS page and the front page. +12) Add the announcement to the website as a new entry in the news/ + dir. It will automatically get indexed onto the homepage when the + site refreshes. + diff --git a/Build/source/libs/cairo/cairo-src/build/Makefile.am.gtk-doc b/Build/source/libs/cairo/cairo-src/build/Makefile.am.gtk-doc index c3d642b097b..56aa4957d32 100644 --- a/Build/source/libs/cairo/cairo-src/build/Makefile.am.gtk-doc +++ b/Build/source/libs/cairo/cairo-src/build/Makefile.am.gtk-doc @@ -8,7 +8,7 @@ # - Some other changed introduced in 7f114b781f5c530d57530e5f76402e41cdabac6b # # Before changing it, check to see if a newer gtk-doc.make has fixed the issue you are facing. -# From time to time, it would be nice to udpate this to the latest copy of gtk-doc.make, but +# From time to time, it would be nice to update this to the latest copy of gtk-doc.make, but # please do review all the differences and port our modifications forward. # @@ -42,8 +42,8 @@ EXTRA_DIST += \ $(DOC_MODULE)-sections.txt \ $(DOC_MODULE)-overrides.txt -DOC_STAMPS=scan-build.stamp tmpl-build.stamp sgml-build.stamp html-build.stamp \ - $(srcdir)/tmpl.stamp $(srcdir)/sgml.stamp $(srcdir)/html.stamp +DOC_STAMPS=scan-build.stamp sgml-build.stamp html-build.stamp \ + $(srcdir)/sgml.stamp $(srcdir)/html.stamp SCANOBJ_FILES = \ $(DOC_MODULE).args \ @@ -88,26 +88,11 @@ scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB) $(EXTRA_HFILES) $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp @true -#### templates #### - -tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt - @echo 'gtk-doc: Rebuilding template files' - @-chmod -R u+w $(srcdir) - cd $(srcdir) && gtkdoc-mktmpl --module=$(DOC_MODULE) $(MKTMPL_OPTIONS) - touch tmpl-build.stamp - -tmpl.stamp: tmpl-build.stamp - @true - -tmpl/*.sgml: - @true - - #### xml #### # gtkdoc-mkdb is broken and requires a --root-dir=$(srcdir) option # The _srcdir diversion is fragile but works for make check; make distcheck -sgml-build.stamp: tmpl.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(srcdir)/tmpl/*.sgml $(expand_content_files) +sgml-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(expand_content_files) @echo 'gtk-doc: Building XML' @-chmod -R u+w $(srcdir) _srcdir="`pwd`/$(DOC_SOURCE_DIR)"; \ @@ -127,7 +112,7 @@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) cd $(srcdir)/html && gtkdoc-mkhtml $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) html ) @echo 'gtk-doc: Fixing cross-references' - cd $(srcdir) && gtkdoc-fixxref --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + cd $(srcdir) && gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) touch html-build.stamp ############## @@ -176,10 +161,8 @@ dist-check-gtkdoc: endif dist-hook: dist-check-gtkdoc dist-hook-local - mkdir $(distdir)/tmpl mkdir $(distdir)/xml mkdir $(distdir)/html - -cp $(srcdir)/tmpl/*.sgml $(distdir)/tmpl -cp $(srcdir)/xml/*.xml $(distdir)/xml cp $(srcdir)/html/* $(distdir)/html -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/ diff --git a/Build/source/libs/cairo/cairo-src/build/Makefile.am.releasing b/Build/source/libs/cairo/cairo-src/build/Makefile.am.releasing index b17faabce2f..329d49c8ca8 100644 --- a/Build/source/libs/cairo/cairo-src/build/Makefile.am.releasing +++ b/Build/source/libs/cairo/cairo-src/build/Makefile.am.releasing @@ -31,7 +31,7 @@ RELEASE_OR_SNAPSHOT = $$(if test "x$(CAIRO_VERSION_MINOR)" = "x$$(echo "$(CAIRO_ RELEASE_UPLOAD_HOST = cairographics.org RELEASE_UPLOAD_BASE = /srv/cairo.freedesktop.org/www RELEASE_UPLOAD_DIR = $(RELEASE_UPLOAD_BASE)/$(RELEASE_OR_SNAPSHOT)s -RELEASE_URL_BASE = http://cairographics.org/$(RELEASE_OR_SNAPSHOT)s +RELEASE_URL_BASE = https://cairographics.org/$(RELEASE_OR_SNAPSHOT)s RELEASE_ANNOUNCE_LIST = cairo-announce@cairographics.org (and CC gnome-announce-list@gnome.org) MANUAL_VERSIONED = manual-$(VERSION) diff --git a/Build/source/libs/cairo/cairo-src/build/Makefile.win32.features b/Build/source/libs/cairo/cairo-src/build/Makefile.win32.features index 8cb155dc084..b15c4488f88 100644 --- a/Build/source/libs/cairo/cairo-src/build/Makefile.win32.features +++ b/Build/source/libs/cairo/cairo-src/build/Makefile.win32.features @@ -11,7 +11,6 @@ CAIRO_HAS_QUARTZ_FONT=0 CAIRO_HAS_QUARTZ_IMAGE_SURFACE=0 CAIRO_HAS_WIN32_SURFACE=1 CAIRO_HAS_WIN32_FONT=1 -CAIRO_HAS_SKIA_SURFACE=0 CAIRO_HAS_OS2_SURFACE=0 CAIRO_HAS_BEOS_SURFACE=0 CAIRO_HAS_DRM_SURFACE=0 @@ -19,6 +18,7 @@ CAIRO_HAS_GALLIUM_SURFACE=0 CAIRO_HAS_PNG_FUNCTIONS=1 CAIRO_HAS_GL_SURFACE=0 CAIRO_HAS_GLESV2_SURFACE=0 +CAIRO_HAS_GLESV3_SURFACE=0 CAIRO_HAS_COGL_SURFACE=0 CAIRO_HAS_DIRECTFB_SURFACE=0 CAIRO_HAS_VG_SURFACE=0 diff --git a/Build/source/libs/cairo/cairo-src/build/Makefile.win32.features-h b/Build/source/libs/cairo/cairo-src/build/Makefile.win32.features-h index 13904cfa9f0..5759b48a3b9 100644 --- a/Build/source/libs/cairo/cairo-src/build/Makefile.win32.features-h +++ b/Build/source/libs/cairo/cairo-src/build/Makefile.win32.features-h @@ -38,9 +38,6 @@ endif ifeq ($(CAIRO_HAS_WIN32_FONT),1) @echo "#define CAIRO_HAS_WIN32_FONT 1" >> $(top_srcdir)/src/cairo-features.h endif -ifeq ($(CAIRO_HAS_SKIA_SURFACE),1) - @echo "#define CAIRO_HAS_SKIA_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h -endif ifeq ($(CAIRO_HAS_OS2_SURFACE),1) @echo "#define CAIRO_HAS_OS2_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h endif @@ -62,6 +59,9 @@ endif ifeq ($(CAIRO_HAS_GLESV2_SURFACE),1) @echo "#define CAIRO_HAS_GLESV2_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h endif +ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1) + @echo "#define CAIRO_HAS_GLESV3_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h +endif ifeq ($(CAIRO_HAS_COGL_SURFACE),1) @echo "#define CAIRO_HAS_COGL_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h endif diff --git a/Build/source/libs/cairo/cairo-src/build/aclocal.cairo.m4 b/Build/source/libs/cairo/cairo-src/build/aclocal.cairo.m4 index 44ba5fdf6f5..64c1a2e2fad 100644 --- a/Build/source/libs/cairo/cairo-src/build/aclocal.cairo.m4 +++ b/Build/source/libs/cairo/cairo-src/build/aclocal.cairo.m4 @@ -165,7 +165,7 @@ AC_DEFUN([CAIRO_CHECK_NATIVE_ATOMIC_PRIMITIVES], int atomic_add(int i) { return __sync_fetch_and_add (&i, 1); } int atomic_cmpxchg(int i, int j, int k) { return __sync_val_compare_and_swap (&i, j, k); } ], [], - cairo_cv_atomic_primitives="Intel" + cairo_cv_atomic_primitives="gcc-legacy" ) AC_TRY_LINK([ @@ -190,9 +190,9 @@ int atomic_cmpxchg(int i, int j, int k) { return __atomic_compare_exchange_n(&i, [Enable if your compiler supports the GCC __atomic_* atomic primitives]) fi - if test "x$cairo_cv_atomic_primitives" = xIntel; then - AC_DEFINE(HAVE_INTEL_ATOMIC_PRIMITIVES, 1, - [Enable if your compiler supports the Intel __sync_* atomic primitives]) + if test "x$cairo_cv_atomic_primitives" = xgcc-legacy; then + AC_DEFINE(HAVE_GCC_LEGACY_ATOMICS, 1, + [Enable if your compiler supports the legacy GCC __sync_* atomic primitives]) fi if test "x$cairo_cv_atomic_primitives" = "xlibatomic-ops"; then @@ -215,7 +215,7 @@ AC_DEFUN([CAIRO_CHECK_ATOMIC_OP_NEEDS_MEMORY_BARRIER], case $host_cpu in i?86) cairo_cv_atomic_op_needs_memory_barrier="no" ;; x86_64) cairo_cv_atomic_op_needs_memory_barrier="no" ;; - arm*) cairo_cv_atomic_op_needs_memory_barrier="no" ;; + arm*) cairo_cv_atomic_op_needs_memory_barrier="yes" ;; *) cairo_cv_atomic_op_needs_memory_barrier="yes" ;; esac ]) diff --git a/Build/source/libs/cairo/cairo-src/build/aclocal.float.m4 b/Build/source/libs/cairo/cairo-src/build/aclocal.float.m4 index ca14ea37707..85adf6d5f45 100644 --- a/Build/source/libs/cairo/cairo-src/build/aclocal.float.m4 +++ b/Build/source/libs/cairo/cairo-src/build/aclocal.float.m4 @@ -12,7 +12,7 @@ AC_DEFUN([AX_C_FLOAT_WORDS_BIGENDIAN], [AC_CACHE_CHECK(whether float word ordering is bigendian, ax_cv_c_float_words_bigendian, [ -# The endianess is detected by first compiling C code that contains a special +# The endianness is detected by first compiling C code that contains a special # double float value, then grepping the resulting object file for certain # strings of ascii values. The double is specially crafted to have a # binary representation that corresponds with a simple string. In this diff --git a/Build/source/libs/cairo/cairo-src/build/aclocal.pkg.m4 b/Build/source/libs/cairo/cairo-src/build/aclocal.pkg.m4 index cf90a967880..8b9fda90930 100644 --- a/Build/source/libs/cairo/cairo-src/build/aclocal.pkg.m4 +++ b/Build/source/libs/cairo/cairo-src/build/aclocal.pkg.m4 @@ -146,7 +146,7 @@ path to pkg-config. _PKG_TEXT -To get pkg-config, see .])], +To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS diff --git a/Build/source/libs/cairo/cairo-src/build/configure.ac.features b/Build/source/libs/cairo/cairo-src/build/configure.ac.features index 77f20358889..e0a46069c82 100644 --- a/Build/source/libs/cairo/cairo-src/build/configure.ac.features +++ b/Build/source/libs/cairo/cairo-src/build/configure.ac.features @@ -369,7 +369,7 @@ AC_DEFUN([CAIRO_REPORT], echo " Mime: yes (always builtin)" echo " Tee: $use_tee" echo " XML: $use_xml" - echo " Skia: $use_skia" + #echo " Skia: $use_skia" echo " Xlib: $use_xlib" echo " Xlib Xrender: $use_xlib_xrender" echo " Qt: $use_qt" @@ -384,6 +384,7 @@ AC_DEFUN([CAIRO_REPORT], echo " SVG: $use_svg" echo " OpenGL: $use_gl" echo " OpenGL ES 2.0: $use_glesv2" + echo " OpenGL ES 3.0: $use_glesv3" echo " BeOS: $use_beos" echo " DirectFB: $use_directfb" echo " OpenVG: $use_vg" diff --git a/Build/source/libs/cairo/cairo-src/build/configure.ac.system b/Build/source/libs/cairo/cairo-src/build/configure.ac.system index 915b42b4636..def75cdc1fc 100644 --- a/Build/source/libs/cairo/cairo-src/build/configure.ac.system +++ b/Build/source/libs/cairo/cairo-src/build/configure.ac.system @@ -108,7 +108,7 @@ AC_CHECK_HEADER(fenv.h, dnl check for misc headers and functions AC_CHECK_HEADERS([libgen.h byteswap.h signal.h setjmp.h fenv.h sys/wait.h]) -AC_CHECK_FUNCS([ctime_r drand48 flockfile funlockfile getline link strndup]) +AC_CHECK_FUNCS([ctime_r localtime_r gmtime_r drand48 flockfile funlockfile getline link strndup]) dnl Check if the runtime platform is a native Win32 host. AC_COMPILE_IFELSE([[ diff --git a/Build/source/libs/cairo/cairo-src/build/configure.ac.tools b/Build/source/libs/cairo/cairo-src/build/configure.ac.tools index a24dbcecb91..1fd2d3df825 100644 --- a/Build/source/libs/cairo/cairo-src/build/configure.ac.tools +++ b/Build/source/libs/cairo/cairo-src/build/configure.ac.tools @@ -12,7 +12,7 @@ dnl =========================================================================== PKG_PROG_PKG_CONFIG() if test "x$PKG_CONFIG" = x; then - AC_MSG_ERROR([pkg-config >= $PKGCONFIG_REQUIRED required but not found (http://pkgconfig.freedesktop.org/)]) + AC_MSG_ERROR([pkg-config >= $PKGCONFIG_REQUIRED required but not found (https://pkgconfig.freedesktop.org/)]) fi dnl Check for recent pkg-config which supports Requires.private diff --git a/Build/source/libs/cairo/cairo-src/build/gtk-doc.m4 b/Build/source/libs/cairo/cairo-src/build/gtk-doc.m4 index 36755432b50..2d12f01f4b9 100644 --- a/Build/source/libs/cairo/cairo-src/build/gtk-doc.m4 +++ b/Build/source/libs/cairo/cairo-src/build/gtk-doc.m4 @@ -1,4 +1,29 @@ -dnl -*- mode: autoconf -*- +# -*- mode: autoconf -*- +# +# gtk-doc.m4 - configure macro to check for gtk-doc +# Copyright (C) 2003 James Henstridge +# 2007-2017 Stefan Sauer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# As a special exception, the above copyright owner gives unlimited +# permission to copy, distribute and modify the configure scripts that +# are the output of Autoconf when processing the Macro. You need not +# follow the terms of the GNU General Public License when using or +# distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. # serial 2 diff --git a/Build/source/libs/cairo/cairo-src/cairo-version.h b/Build/source/libs/cairo/cairo-src/cairo-version.h index 1f17dd6c6ba..512cfa27907 100644 --- a/Build/source/libs/cairo/cairo-src/cairo-version.h +++ b/Build/source/libs/cairo/cairo-src/cairo-version.h @@ -2,7 +2,7 @@ #define CAIRO_VERSION_H #define CAIRO_VERSION_MAJOR 1 -#define CAIRO_VERSION_MINOR 14 -#define CAIRO_VERSION_MICRO 12 +#define CAIRO_VERSION_MINOR 16 +#define CAIRO_VERSION_MICRO 0 #endif diff --git a/Build/source/libs/cairo/cairo-src/config.h.in b/Build/source/libs/cairo/cairo-src/config.h.in index 5bb49725685..812ef575abb 100644 --- a/Build/source/libs/cairo/cairo-src/config.h.in +++ b/Build/source/libs/cairo/cairo-src/config.h.in @@ -52,6 +52,9 @@ significant word first */ #undef FLOAT_WORDS_BIGENDIAN +/* Define to (0) if freetype2 does not support color fonts */ +#undef FT_HAS_COLOR + /* Enable pixman glyph cache */ #undef HAS_PIXMAN_GLYPHS @@ -110,6 +113,12 @@ /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK +/* Define to 1 if you have the `FT_Done_MM_Var' function. */ +#undef HAVE_FT_DONE_MM_VAR + +/* Define to 1 if you have the `FT_Get_Var_Design_Coordinates' function. */ +#undef HAVE_FT_GET_VAR_DESIGN_COORDINATES + /* Define to 1 if you have the `FT_Get_X11_Font_Format' function. */ #undef HAVE_FT_GET_X11_FONT_FORMAT @@ -128,14 +137,18 @@ /* Define to 1 if you have the `funlockfile' function. */ #undef HAVE_FUNLOCKFILE +/* Enable if your compiler supports the legacy GCC __sync_* atomic primitives + */ +#undef HAVE_GCC_LEGACY_ATOMICS + /* Whether you have gcov */ #undef HAVE_GCOV /* Define to 1 if you have the `getline' function. */ #undef HAVE_GETLINE -/* Enable if your compiler supports the Intel __sync_* atomic primitives */ -#undef HAVE_INTEL_ATOMIC_PRIMITIVES +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -155,6 +168,9 @@ /* Define to 1 if you have the `link' function. */ #undef HAVE_LINK +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + /* Define to 1 if you have the Valgrind lockdep tool */ #undef HAVE_LOCKDEP @@ -174,6 +190,9 @@ /* Define to 1 if you have the `mmap' function. */ #undef HAVE_MMAP +/* Define to 1 if you have the `newlocale' function. */ +#undef HAVE_NEWLOCALE + /* Enable if you have MacOS X atomic operations */ #undef HAVE_OS_ATOMIC_OPS @@ -213,6 +232,9 @@ /* Define to 1 if you have the `strndup' function. */ #undef HAVE_STRNDUP +/* Define to 1 if you have the `strtod_l' function. */ +#undef HAVE_STRTOD_L + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_INT_TYPES_H @@ -243,6 +265,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H +/* Define to 1 if typeof works with your compiler. */ +#undef HAVE_TYPEOF + /* Define to 1 if the system has the type `uint128_t'. */ #undef HAVE_UINT128_T @@ -267,6 +292,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_X11_EXTENSIONS_XSHM_H +/* Define to 1 if you have the header file. */ +#undef HAVE_XLOCALE_H + /* Define to 1 if you have the `XRenderCreateConicalGradient' function. */ #undef HAVE_XRENDERCREATECONICALGRADIENT @@ -410,3 +438,6 @@ #ifndef __cplusplus #undef inline #endif + +/* Define to __typeof__ if your compiler spells it that way. */ +#undef typeof diff --git a/Build/source/libs/cairo/cairo-src/configure.ac b/Build/source/libs/cairo/cairo-src/configure.ac index 2ce19599e30..5e33c96ea8b 100644 --- a/Build/source/libs/cairo/cairo-src/configure.ac +++ b/Build/source/libs/cairo/cairo-src/configure.ac @@ -2,9 +2,9 @@ AC_PREREQ([2.63]) CAIRO_PARSE_VERSION AC_INIT([cairo], [cairo_version_major.cairo_version_minor.cairo_version_micro], - [http://bugs.freedesktop.org/enter_bug.cgi?product=cairo], + [https://bugs.freedesktop.org/enter_bug.cgi?product=cairo], [cairo], - [http://cairographics.org/]) + [https://cairographics.org/]) AC_CONFIG_AUX_DIR(build) AC_CONFIG_MACRO_DIR(build) AC_USE_SYSTEM_EXTENSIONS @@ -12,6 +12,7 @@ AC_CONFIG_SRCDIR(src/cairo.h) AC_CONFIG_HEADERS(config.h) AC_CHECK_HEADERS([unistd.h sys/ioctl.h]) +AC_C_TYPEOF AM_INIT_AUTOMAKE([1.11 foreign -Wall no-define no-dist-gzip dist-xz]) AM_SILENT_RULES([yes]) @@ -75,6 +76,9 @@ if test "x$have_dlsym" = "xyes"; then fi AM_CONDITIONAL(CAIRO_HAS_DLSYM, test "x$have_dlsym" = "xyes") +AC_CHECK_HEADERS(xlocale.h) +AC_CHECK_FUNCS(newlocale strtod_l) + dnl =========================================================================== CAIRO_ENABLE_SURFACE_BACKEND(xlib, Xlib, auto, [ @@ -139,7 +143,7 @@ CAIRO_ENABLE_SURFACE_BACKEND(xlib_xrender, Xlib Xrender, auto, [ CPPFLAGS="$CPPFLAGS $xlib_CFLAGS $xlib_NONPKGCONFIG_CFLAGS" AC_CHECK_HEADER(X11/extensions/Xrender.h, [xlib_xrender_NONPKGCONFIG_LIBS="-lXrender"], - [use_xlib_xrender="no (requires $xlib_xrender_REQUIRES http://freedesktop.org/Software/xlibs)"], + [use_xlib_xrender="no (requires $xlib_xrender_REQUIRES https://freedesktop.org/Software/xlibs)"], [#include ]) CPPFLAGS=$old_CPPFLAGS ]) @@ -160,14 +164,14 @@ dnl =========================================================================== CAIRO_ENABLE_SURFACE_BACKEND(xcb, XCB, auto, [ xcb_REQUIRES="xcb >= 1.6 xcb-render >= 1.6" PKG_CHECK_MODULES(xcb, $xcb_REQUIRES, , - [use_xcb="no (requires $xcb_REQUIRES http://xcb.freedesktop.org)"]) + [use_xcb="no (requires $xcb_REQUIRES https://xcb.freedesktop.org)"]) ]) CAIRO_ENABLE_FUNCTIONS(xlib_xcb, Xlib/XCB, no, [ if test "x$use_xcb" = "xyes" -a "x$use_xlib" = "xyes"; then xlib_xcb_REQUIRES="x11-xcb" PKG_CHECK_MODULES(xlib_xcb, $xlib_xcb_REQUIRES, , - [use_xlib_xcb="no (requires $xlib_xcb_REQUIRES http://xcb.freedesktop.org)"]) + [use_xlib_xcb="no (requires $xlib_xcb_REQUIRES https://xcb.freedesktop.org)"]) else use_xlib_xcb="no (requires both --enable-xlib and --enable-xcb)" fi @@ -177,7 +181,7 @@ CAIRO_ENABLE_FUNCTIONS(xcb_shm, XCB/SHM, auto, [ if test "x$use_xcb" = "xyes"; then xcb_shm_REQUIRES="xcb-shm" PKG_CHECK_MODULES(xcb_shm, $xcb_shm_REQUIRES, , - [use_xcb_shm="no (requires $xcb_shm http://xcb.freedesktop.org)"]) + [use_xcb_shm="no (requires $xcb_shm https://xcb.freedesktop.org)"]) else use_xcb_shm="no (requires --enable-xcb)" fi @@ -245,27 +249,6 @@ AM_CONDITIONAL(CAIRO_CAN_TEST_WIN32_PRINTING_SURFACE, test "x$test_win32_printin dnl =========================================================================== -CAIRO_ENABLE_SURFACE_BACKEND(skia, Skia, no, [ - AC_ARG_WITH([skia], - [AS_HELP_STRING([--with-skia=/path/to/skia], - [directory to find compiled skia sources])], - [skia_DIR="$withval"], - [skia_DIR="`pwd`/../skia"]) - AC_ARG_WITH([skia-build-type], - [AS_HELP_STRING([--with-skia-build-type=(Release|Debug)] - [build of skia to link with, default is Release])], - [skia_BUILD_TYPE="$withval"], - [skia_BUILD_TYPE="Release"]) - skia_NONPKGCONFIG_CFLAGS="-I$skia_DIR/include/config -I$skia_DIR/include/core -I$skia_DIR/include/effects" - if test "x$skia_BUILD_TYPE" = "xRelease"; then - skia_NONPKGCONFIG_CFLAGS="-DSK_RELEASE -DSK_CAN_USE_FLOAT $skia_NONPKGCONFIG_CFLAGS" - fi - skia_NONPKGCONFIG_LIBS="-L$skia_DIR/out/$skia_BUILD_TYPE/lib.target/ -lskia -lstdc++" - AC_SUBST(skia_DIR) -]) - -dnl =========================================================================== - CAIRO_ENABLE_SURFACE_BACKEND(os2, OS/2, no, [ case "$host" in *-*-os2*) @@ -296,7 +279,7 @@ CAIRO_ENABLE_SURFACE_BACKEND(beos, BeOS/Zeta, no, [ dnl =========================================================================== CAIRO_ENABLE_SURFACE_BACKEND(drm, DRM, no, [ - drm_REQUIRES="libudev >= 136" + drm_REQUIRES="libudev >= 136, libdrm >= 2.4" PKG_CHECK_MODULES(drm, $drm_REQUIRES, , [use_drm="no (requires $drm_REQUIRES, udev is available from git://git.kernel.org/pub/scm/linux/hotplug/udev.git)"]) ]) @@ -385,6 +368,32 @@ CAIRO_ENABLE_SURFACE_BACKEND(glesv2, OpenGLESv2, no, [ need_egl_functions=yes ]) +dnl =========================================================================== +CAIRO_ENABLE_SURFACE_BACKEND(glesv3, OpenGLESv3, no, [ + dnl glesv3 is provided via libGLESv2.so, so require glesv2.pc (there is no libGLESv3, nor glesv3.pc) + glesv3_REQUIRES="glesv2" + PKG_CHECK_MODULES(glesv3, $glesv3_REQUIRES,, [ + use_glesv3="no (glesv2.pc not found, required for glesv3)" + ]) + + dnl Since there is no glesv3.pc, need to search for header files + AC_CHECK_HEADER(GLES3/gl3.h,, [use_glesv3="no (OpenGL ES 3.0 headers not found)"]) + if test "x$use_glesv3" = "xyes"; then + glesv3_NONPKGCONFIG_CFLAGS= + glesv3_NONPKGCONFIG_LIBS="-lGLESv2" + fi + + if test "x$have_dl" = "xyes" -a "x$have_dlsym" = "xyes"; then + glesv3_LIBS="$glesv3_LIBS -ldl" + fi + + if test "x$use_glesv3" = "xyes" -a "x$use_gl" = "xyes"; then + AC_MSG_ERROR([use either --enable-gl=yes or --enable-glesv3=yes. Not both at the same time.]) + fi + + need_egl_functions=yes +]) + dnl =========================================================================== CAIRO_ENABLE_SURFACE_BACKEND(cogl, Cogl, no, [ cogl_REQUIRES="cogl-2.0-experimental" @@ -470,6 +479,9 @@ dnl =========================================================================== any2ppm_cs=no CAIRO_ENABLE_SURFACE_BACKEND(script, script, yes, [ any2ppm_cs=yes + # The script backend requires zlib. + use_script=$have_libz + script_NONPKGCONFIG_LIBS=-lz ]) dnl =========================================================================== @@ -544,7 +556,18 @@ if test "x$use_ft" = "xyes"; then LIBS="$LIBS $ft_LIBS" CFLAGS="$CFLAGS $ft_CFLAGS" - AC_CHECK_FUNCS(FT_Get_X11_Font_Format FT_GlyphSlot_Embolden FT_GlyphSlot_Oblique FT_Load_Sfnt_Table FT_Library_SetLcdFilter) + AC_CHECK_FUNCS(FT_Get_X11_Font_Format FT_GlyphSlot_Embolden FT_GlyphSlot_Oblique FT_Load_Sfnt_Table FT_Library_SetLcdFilter FT_Get_Var_Design_Coordinates FT_Done_MM_Var) + + AC_MSG_CHECKING(for FT_HAS_COLOR) + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include +#include FT_FREETYPE_H +],[ +FT_Long has_color = FT_HAS_COLOR( ((FT_Face)NULL) ); +])],[AC_MSG_RESULT([yes])],[ + AC_DEFINE([FT_HAS_COLOR(x)], [(0)], [Define to (0) if freetype2 does not support color fonts]) + AC_MSG_RESULT([no, disable color font (freetype2 >= 2.5.1 is required)]) +]) LIBS="$_save_libs" CFLAGS="$_save_cflags" @@ -664,7 +687,7 @@ dnl =========================================================================== CAIRO_ENABLE_SURFACE_BACKEND(image, image, always, [ pixman_REQUIRES="pixman-1 >= 0.30.0" PKG_CHECK_MODULES(pixman, $pixman_REQUIRES, , - [use_image="no (requires $pixman_REQUIRES http://cairographics.org/releases/)"]) + [use_image="no (requires $pixman_REQUIRES https://cairographics.org/releases/)"]) image_REQUIRES=$pixman_REQUIRES image_CFLAGS=$pixman_CFLAGS image_LIBS=$pixman_LIBS @@ -712,7 +735,7 @@ dnl Build gobject integration library CAIRO_ENABLE_FUNCTIONS(gobject, gobject, auto, [ gobject_REQUIRES="gobject-2.0 glib-2.0 >= 2.14" PKG_CHECK_MODULES(GOBJECT, $gobject_REQUIRES, , - [use_gobject="no (requires $gobject_REQUIRES http://download.gnome.org/pub/GNOME/sources/glib/)"]) + [use_gobject="no (requires $gobject_REQUIRES https://download.gnome.org/pub/GNOME/sources/glib/)"]) gobject_NONPKGCONFIG_EXTRA_LIBS="-L\${libdir} -lcairo-gobject" ]) dnl I'm too lazy to fix the caching properly @@ -839,7 +862,6 @@ dnl =========================================================================== dnl Extra stuff we need to do when building C++ code need_cxx="no" -AS_IF([test "x$use_skia" = "xyes"], [need_cxx="yes"]) AS_IF([test "x$use_qt" = "xyes"], [need_cxx="yes"]) AS_IF([test "x$use_beos" = "xyes"], [need_cxx="yes"]) diff --git a/Build/source/libs/cairo/cairo-src/src/Makefile.am.features b/Build/source/libs/cairo/cairo-src/src/Makefile.am.features index c58ac23da4e..47c95db1f91 100644 --- a/Build/source/libs/cairo/cairo-src/src/Makefile.am.features +++ b/Build/source/libs/cairo/cairo-src/src/Makefile.am.features @@ -193,22 +193,6 @@ if CAIRO_HAS_WIN32_FONT enabled_cairo_pkgconf += cairo-win32-font.pc endif -unsupported_cairo_headers += $(cairo_skia_headers) -all_cairo_headers += $(cairo_skia_headers) -all_cairo_private += $(cairo_skia_private) -all_cairo_cxx_sources += $(cairo_skia_cxx_sources) -all_cairo_sources += $(cairo_skia_sources) -if CAIRO_HAS_SKIA_SURFACE -enabled_cairo_headers += $(cairo_skia_headers) -enabled_cairo_private += $(cairo_skia_private) -enabled_cairo_cxx_sources += $(cairo_skia_cxx_sources) -enabled_cairo_sources += $(cairo_skia_sources) -endif -all_cairo_pkgconf += cairo-skia.pc -if CAIRO_HAS_SKIA_SURFACE -enabled_cairo_pkgconf += cairo-skia.pc -endif - unsupported_cairo_headers += $(cairo_os2_headers) all_cairo_headers += $(cairo_os2_headers) all_cairo_private += $(cairo_os2_private) @@ -321,6 +305,22 @@ if CAIRO_HAS_GLESV2_SURFACE enabled_cairo_pkgconf += cairo-glesv2.pc endif +unsupported_cairo_headers += $(cairo_glesv3_headers) +all_cairo_headers += $(cairo_glesv3_headers) +all_cairo_private += $(cairo_glesv3_private) +all_cairo_cxx_sources += $(cairo_glesv3_cxx_sources) +all_cairo_sources += $(cairo_glesv3_sources) +if CAIRO_HAS_GLESV3_SURFACE +enabled_cairo_headers += $(cairo_glesv3_headers) +enabled_cairo_private += $(cairo_glesv3_private) +enabled_cairo_cxx_sources += $(cairo_glesv3_cxx_sources) +enabled_cairo_sources += $(cairo_glesv3_sources) +endif +all_cairo_pkgconf += cairo-glesv3.pc +if CAIRO_HAS_GLESV3_SURFACE +enabled_cairo_pkgconf += cairo-glesv3.pc +endif + unsupported_cairo_headers += $(cairo_cogl_headers) all_cairo_headers += $(cairo_cogl_headers) all_cairo_private += $(cairo_cogl_private) diff --git a/Build/source/libs/cairo/cairo-src/src/Makefile.sources b/Build/source/libs/cairo/cairo-src/src/Makefile.sources index fac24d79d8a..096a3bcfaad 100644 --- a/Build/source/libs/cairo/cairo-src/src/Makefile.sources +++ b/Build/source/libs/cairo/cairo-src/src/Makefile.sources @@ -64,10 +64,10 @@ cairo_private = \ cairo-clip-private.h \ cairo-combsort-inline.h \ cairo-compiler-private.h \ + cairo-composite-rectangles-private.h \ cairo-compositor-private.h \ cairo-contour-inline.h \ cairo-contour-private.h \ - cairo-composite-rectangles-private.h \ cairo-damage-private.h \ cairo-default-context-private.h \ cairo-device-private.h \ @@ -75,10 +75,10 @@ cairo_private = \ cairo-error-private.h \ cairo-fixed-private.h \ cairo-fixed-type-private.h \ + cairo-fontconfig-private.h \ + cairo-freed-pool-private.h \ cairo-freelist-private.h \ cairo-freelist-type-private.h \ - cairo-freed-pool-private.h \ - cairo-fontconfig-private.h \ cairo-gstate-private.h \ cairo-hash-private.h \ cairo-image-info-private.h \ @@ -110,26 +110,26 @@ cairo_private = \ cairo-rtree-private.h \ cairo-scaled-font-private.h \ cairo-slope-private.h \ - cairo-spans-private.h \ cairo-spans-compositor-private.h \ + cairo-spans-private.h \ cairo-stroke-dash-private.h \ - cairo-surface-inline.h \ - cairo-surface-private.h \ cairo-surface-backend-private.h \ cairo-surface-clipper-private.h \ cairo-surface-fallback-private.h \ + cairo-surface-inline.h \ cairo-surface-observer-inline.h \ cairo-surface-observer-private.h \ cairo-surface-offset-private.h \ - cairo-surface-subsurface-inline.h \ - cairo-surface-subsurface-private.h \ + cairo-surface-private.h \ cairo-surface-snapshot-inline.h \ cairo-surface-snapshot-private.h \ + cairo-surface-subsurface-inline.h \ + cairo-surface-subsurface-private.h \ cairo-surface-wrapper-private.h \ cairo-time-private.h \ - cairo-types-private.h \ cairo-traps-private.h \ cairo-tristrip-private.h \ + cairo-types-private.h \ cairo-user-font-private.h \ cairo-wideint-private.h \ cairo-wideint-type-private.h \ @@ -141,19 +141,19 @@ cairo_sources = \ cairo-atomic.c \ cairo-base64-stream.c \ cairo-base85-stream.c \ - cairo-bentley-ottmann.c \ cairo-bentley-ottmann-rectangular.c \ cairo-bentley-ottmann-rectilinear.c \ + cairo-bentley-ottmann.c \ cairo-botor-scan-converter.c \ - cairo-boxes.c \ cairo-boxes-intersect.c \ - cairo.c \ + cairo-boxes.c \ cairo-cache.c \ - cairo-clip.c \ cairo-clip-boxes.c \ cairo-clip-polygon.c \ cairo-clip-region.c \ cairo-clip-surface.c \ + cairo-clip-tor-scan-converter.c \ + cairo-clip.c \ cairo-color.c \ cairo-composite-rectangles.c \ cairo-compositor.c \ @@ -165,12 +165,12 @@ cairo_sources = \ cairo-error.c \ cairo-fallback-compositor.c \ cairo-fixed.c \ - cairo-font-face.c \ - cairo-font-face-twin.c \ cairo-font-face-twin-data.c \ + cairo-font-face-twin.c \ + cairo-font-face.c \ cairo-font-options.c \ - cairo-freelist.c \ cairo-freed-pool.c \ + cairo-freelist.c \ cairo-gstate.c \ cairo-hash.c \ cairo-hull.c \ @@ -180,10 +180,10 @@ cairo_sources = \ cairo-image-surface.c \ cairo-line.c \ cairo-lzw.c \ - cairo-matrix.c \ cairo-mask-compositor.c \ - cairo-mesh-pattern-rasterizer.c \ + cairo-matrix.c \ cairo-mempool.c \ + cairo-mesh-pattern-rasterizer.c \ cairo-misc.c \ cairo-mono-scan-converter.c \ cairo-mutex.c \ @@ -192,20 +192,20 @@ cairo_sources = \ cairo-output-stream.c \ cairo-paginated-surface.c \ cairo-path-bounds.c \ - cairo-path.c \ cairo-path-fill.c \ cairo-path-fixed.c \ cairo-path-in-fill.c \ - cairo-path-stroke.c \ cairo-path-stroke-boxes.c \ cairo-path-stroke-polygon.c \ cairo-path-stroke-traps.c \ cairo-path-stroke-tristrip.c \ + cairo-path-stroke.c \ + cairo-path.c \ cairo-pattern.c \ cairo-pen.c \ - cairo-polygon.c \ cairo-polygon-intersect.c \ cairo-polygon-reduce.c \ + cairo-polygon.c \ cairo-raster-source-pattern.c \ cairo-recording-surface.c \ cairo-rectangle.c \ @@ -215,12 +215,11 @@ cairo_sources = \ cairo-scaled-font.c \ cairo-shape-mask-compositor.c \ cairo-slope.c \ - cairo-spans.c \ cairo-spans-compositor.c \ + cairo-spans.c \ cairo-spline.c \ cairo-stroke-dash.c \ cairo-stroke-style.c \ - cairo-surface.c \ cairo-surface-clipper.c \ cairo-surface-fallback.c \ cairo-surface-observer.c \ @@ -228,18 +227,19 @@ cairo_sources = \ cairo-surface-snapshot.c \ cairo-surface-subsurface.c \ cairo-surface-wrapper.c \ + cairo-surface.c \ cairo-time.c \ cairo-tor-scan-converter.c \ cairo-tor22-scan-converter.c \ - cairo-clip-tor-scan-converter.c \ cairo-toy-font-face.c \ + cairo-traps-compositor.c \ cairo-traps.c \ cairo-tristrip.c \ - cairo-traps-compositor.c \ cairo-unicode.c \ cairo-user-font.c \ cairo-version.c \ cairo-wideint.c \ + cairo.c \ $(NULL) _cairo_font_subset_private = \ @@ -264,8 +264,16 @@ cairo_egl_sources = cairo_glx_sources = cairo_wgl_sources = -_cairo_pdf_operators_private = cairo-pdf-operators-private.h cairo-pdf-shading-private.h -_cairo_pdf_operators_sources = cairo-pdf-operators.c cairo-pdf-shading.c +_cairo_pdf_operators_private = \ + cairo-pdf-operators-private.h \ + cairo-pdf-shading-private.h \ + cairo-tag-attributes-private.h \ + $(NULL) +_cairo_pdf_operators_sources = \ + cairo-pdf-operators.c \ + cairo-pdf-shading.c \ + cairo-tag-attributes.c \ + $(NULL) cairo_private += $(_cairo_pdf_operators_private) cairo_sources += $(_cairo_pdf_operators_sources) @@ -279,8 +287,8 @@ _cairo_deflate_stream_sources = cairo-deflate-stream.c cairo_sources += $(_cairo_deflate_stream_sources) cairo_pdf_headers = cairo-pdf.h -cairo_pdf_private = cairo-pdf-surface-private.h -cairo_pdf_sources = cairo-pdf-surface.c +cairo_pdf_private = cairo-pdf-surface-private.h cairo-tag-stack-private.h +cairo_pdf_sources = cairo-pdf-surface.c cairo-pdf-interchange.c cairo-tag-stack.c cairo_svg_headers = cairo-svg.h cairo_svg_private = cairo-svg-surface-private.h @@ -367,13 +375,6 @@ cairo_win32_font_sources = \ win32/cairo-win32-font.c \ $(NULL) -cairo_skia_headers = cairo-skia.h -cairo_skia_private = skia/cairo-skia-private.h -cairo_skia_cxx_sources = \ - skia/cairo-skia-context.cpp \ - skia/cairo-skia-surface.cpp \ - $(NULL) - cairo_os2_headers = cairo-os2.h cairo_os2_private = cairo-os2-private.h cairo_os2_sources = cairo-os2-surface.c @@ -395,18 +396,22 @@ cairo_gl_sources = cairo-gl-composite.c \ cairo-gl-glyphs.c \ cairo-gl-gradient.c \ cairo-gl-info.c \ + cairo-gl-msaa-compositor.c \ cairo-gl-operand.c \ cairo-gl-shaders.c \ - cairo-gl-msaa-compositor.c \ - cairo-gl-spans-compositor.c \ - cairo-gl-traps-compositor.c \ cairo-gl-source.c \ - cairo-gl-surface.c + cairo-gl-spans-compositor.c \ + cairo-gl-surface.c \ + cairo-gl-traps-compositor.c cairo_glesv2_headers = $(cairo_gl_headers) cairo_glesv2_private = $(cairo_gl_private) cairo_glesv2_sources = $(cairo_gl_sources) +cairo_glesv3_headers = $(cairo_gl_headers) +cairo_glesv3_private = $(cairo_gl_private) +cairo_glesv3_sources = $(cairo_gl_sources) + cairo_egl_sources += cairo-egl-context.c cairo_glx_sources += cairo-glx-context.c cairo_wgl_sources += cairo-wgl-context.c @@ -416,7 +421,6 @@ cairo_directfb_sources = cairo-directfb-surface.c cairo_drm_headers = cairo-drm.h cairo_drm_private = drm/cairo-drm-private.h \ - drm/cairo-drm-ioctl-private.h \ drm/cairo-drm-intel-private.h \ drm/cairo-drm-intel-brw-defines.h \ drm/cairo-drm-intel-brw-structs.h \ diff --git a/Build/source/libs/cairo/cairo-src/src/Makefile.win32.features b/Build/source/libs/cairo/cairo-src/src/Makefile.win32.features index 2274f4ad6cf..377d6dd12a8 100644 --- a/Build/source/libs/cairo/cairo-src/src/Makefile.win32.features +++ b/Build/source/libs/cairo/cairo-src/src/Makefile.win32.features @@ -197,22 +197,6 @@ ifeq ($(CAIRO_HAS_WIN32_FONT),1) enabled_cairo_pkgconf += cairo-win32-font.pc endif -unsupported_cairo_headers += $(cairo_skia_headers) -all_cairo_headers += $(cairo_skia_headers) -all_cairo_private += $(cairo_skia_private) -all_cairo_cxx_sources += $(cairo_skia_cxx_sources) -all_cairo_sources += $(cairo_skia_sources) -ifeq ($(CAIRO_HAS_SKIA_SURFACE),1) -enabled_cairo_headers += $(cairo_skia_headers) -enabled_cairo_private += $(cairo_skia_private) -enabled_cairo_cxx_sources += $(cairo_skia_cxx_sources) -enabled_cairo_sources += $(cairo_skia_sources) -endif -all_cairo_pkgconf += cairo-skia.pc -ifeq ($(CAIRO_HAS_SKIA_SURFACE),1) -enabled_cairo_pkgconf += cairo-skia.pc -endif - unsupported_cairo_headers += $(cairo_os2_headers) all_cairo_headers += $(cairo_os2_headers) all_cairo_private += $(cairo_os2_private) @@ -325,6 +309,22 @@ ifeq ($(CAIRO_HAS_GLESV2_SURFACE),1) enabled_cairo_pkgconf += cairo-glesv2.pc endif +unsupported_cairo_headers += $(cairo_glesv3_headers) +all_cairo_headers += $(cairo_glesv3_headers) +all_cairo_private += $(cairo_glesv3_private) +all_cairo_cxx_sources += $(cairo_glesv3_cxx_sources) +all_cairo_sources += $(cairo_glesv3_sources) +ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1) +enabled_cairo_headers += $(cairo_glesv3_headers) +enabled_cairo_private += $(cairo_glesv3_private) +enabled_cairo_cxx_sources += $(cairo_glesv3_cxx_sources) +enabled_cairo_sources += $(cairo_glesv3_sources) +endif +all_cairo_pkgconf += cairo-glesv3.pc +ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1) +enabled_cairo_pkgconf += cairo-glesv3.pc +endif + unsupported_cairo_headers += $(cairo_cogl_headers) all_cairo_headers += $(cairo_cogl_headers) all_cairo_private += $(cairo_cogl_private) diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-analysis-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-analysis-surface.c index 8516094c200..c4f9a6d3551 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-analysis-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-analysis-surface.c @@ -118,11 +118,11 @@ attach_proxy (cairo_surface_t *source, { struct proxy *proxy; - proxy = malloc (sizeof (*proxy)); + proxy = _cairo_malloc (sizeof (*proxy)); if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - _cairo_surface_init (&proxy->base, &proxy_backend, NULL, target->content); + _cairo_surface_init (&proxy->base, &proxy_backend, NULL, target->content, target->is_vector); proxy->target = target; _cairo_surface_attach_snapshot (source, &proxy->base, NULL); @@ -137,53 +137,6 @@ detach_proxy (cairo_surface_t *proxy) cairo_surface_destroy (proxy); } -static cairo_int_status_t -_analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, - const cairo_pattern_t *pattern) -{ - const cairo_surface_pattern_t *surface_pattern; - cairo_analysis_surface_t *tmp; - cairo_surface_t *source, *proxy; - cairo_matrix_t p2d; - cairo_status_t status, analysis_status; - - assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); - surface_pattern = (const cairo_surface_pattern_t *) pattern; - assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING); - source = surface_pattern->surface; - - proxy = _cairo_surface_has_snapshot (source, &proxy_backend); - if (proxy != NULL) { - /* nothing untoward found so far */ - return CAIRO_STATUS_SUCCESS; - } - - tmp = (cairo_analysis_surface_t *) - _cairo_analysis_surface_create (surface->target); - if (unlikely (tmp->base.status)) - return tmp->base.status; - proxy = attach_proxy (source, &tmp->base); - - p2d = pattern->matrix; - status = cairo_matrix_invert (&p2d); - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_multiply (&tmp->ctm, &p2d, &surface->ctm); - tmp->has_ctm = ! _cairo_matrix_is_identity (&tmp->ctm); - - source = _cairo_surface_get_source (source, NULL); - status = _cairo_recording_surface_replay_and_create_regions (source, - &tmp->base); - analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS; - detach_proxy (proxy); - cairo_surface_destroy (&tmp->base); - - if (unlikely (status)) - return status; - - return analysis_status; -} - static cairo_int_status_t _add_operation (cairo_analysis_surface_t *surface, cairo_rectangle_int_t *rect, @@ -301,6 +254,104 @@ _add_operation (cairo_analysis_surface_t *surface, return status; } +static cairo_int_status_t +_analyze_recording_surface_pattern (cairo_analysis_surface_t *surface, + const cairo_pattern_t *pattern, + cairo_rectangle_int_t *extents) +{ + const cairo_surface_pattern_t *surface_pattern; + cairo_analysis_surface_t *tmp; + cairo_surface_t *source, *proxy; + cairo_matrix_t p2d; + cairo_int_status_t status; + cairo_int_status_t analysis_status = CAIRO_INT_STATUS_SUCCESS; + cairo_bool_t surface_is_unbounded; + cairo_bool_t unused; + + assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); + surface_pattern = (const cairo_surface_pattern_t *) pattern; + assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING); + source = surface_pattern->surface; + + proxy = _cairo_surface_has_snapshot (source, &proxy_backend); + if (proxy != NULL) { + /* nothing untoward found so far */ + return CAIRO_STATUS_SUCCESS; + } + + tmp = (cairo_analysis_surface_t *) + _cairo_analysis_surface_create (surface->target); + if (unlikely (tmp->base.status)) { + status =tmp->base.status; + goto cleanup1; + } + proxy = attach_proxy (source, &tmp->base); + + p2d = pattern->matrix; + status = cairo_matrix_invert (&p2d); + assert (status == CAIRO_INT_STATUS_SUCCESS); + _cairo_analysis_surface_set_ctm (&tmp->base, &p2d); + + + source = _cairo_surface_get_source (source, NULL); + surface_is_unbounded = (pattern->extend == CAIRO_EXTEND_REPEAT + || pattern->extend == CAIRO_EXTEND_REFLECT); + status = _cairo_recording_surface_replay_and_create_regions (source, + &pattern->matrix, + &tmp->base, + surface_is_unbounded); + if (unlikely (status)) + goto cleanup2; + + /* black background or mime data fills entire extents */ + if (!(source->content & CAIRO_CONTENT_ALPHA) || _cairo_surface_has_mime_image (source)) { + cairo_rectangle_int_t rect; + + if (_cairo_surface_get_extents (source, &rect)) { + cairo_box_t bbox; + + _cairo_box_from_rectangle (&bbox, &rect); + _cairo_matrix_transform_bounding_box_fixed (&p2d, &bbox, NULL); + _cairo_box_round_to_rectangle (&bbox, &rect); + status = _add_operation (tmp, &rect, CAIRO_INT_STATUS_SUCCESS); + if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) + status = CAIRO_INT_STATUS_SUCCESS; + if (unlikely (status)) + goto cleanup2; + } + } + + if (tmp->has_supported) { + surface->has_supported = TRUE; + unused = cairo_region_union (&surface->supported_region, &tmp->supported_region); + } + + if (tmp->has_unsupported) { + surface->has_unsupported = TRUE; + unused = cairo_region_union (&surface->fallback_region, &tmp->fallback_region); + } + + analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS; + if (pattern->extend != CAIRO_EXTEND_NONE) { + _cairo_unbounded_rectangle_init (extents); + } else { + status = cairo_matrix_invert (&tmp->ctm); + _cairo_matrix_transform_bounding_box_fixed (&tmp->ctm, + &tmp->page_bbox, NULL); + _cairo_box_round_to_rectangle (&tmp->page_bbox, extents); + } + + cleanup2: + detach_proxy (proxy); + cleanup1: + cairo_surface_destroy (&tmp->base); + + if (unlikely (status)) + return status; + else + return analysis_status; +} + static cairo_status_t _cairo_analysis_surface_finish (void *abstract_surface) { @@ -344,7 +395,7 @@ _cairo_analysis_surface_operation_extents (cairo_analysis_surface_t *surface, if (_cairo_operator_bounded_by_source (op)) { cairo_rectangle_int_t source_extents; - _cairo_pattern_get_extents (source, &source_extents); + _cairo_pattern_get_extents (source, &source_extents, surface->target->is_vector); _cairo_rectangle_intersect (extents, &source_extents); } @@ -355,7 +406,7 @@ static cairo_int_status_t _cairo_analysis_surface_paint (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, - const cairo_clip_t *clip) + const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; @@ -371,12 +422,14 @@ _cairo_analysis_surface_paint (void *abstract_surface, return backend_status; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } return _add_operation (surface, &extents, backend_status); } @@ -386,7 +439,7 @@ _cairo_analysis_surface_mask (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, - const cairo_clip_t *clip) + const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; @@ -402,18 +455,24 @@ _cairo_analysis_surface_mask (void *abstract_surface, return backend_status; } + _cairo_analysis_surface_operation_extents (surface, + op, source, clip, + &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS; cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS; + cairo_rectangle_int_t rec_extents; if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_t *src_surface = ((cairo_surface_pattern_t *)source)->surface; src_surface = _cairo_surface_get_source (src_surface, NULL); if (_cairo_surface_is_recording (src_surface)) { backend_source_status = - _analyze_recording_surface_pattern (surface, source); + _analyze_recording_surface_pattern (surface, source, &rec_extents); if (_cairo_int_status_is_error (backend_source_status)) return backend_source_status; + + _cairo_rectangle_intersect (&extents, &rec_extents); } } @@ -422,9 +481,11 @@ _cairo_analysis_surface_mask (void *abstract_surface, mask_surface = _cairo_surface_get_source (mask_surface, NULL); if (_cairo_surface_is_recording (mask_surface)) { backend_mask_status = - _analyze_recording_surface_pattern (surface, mask); + _analyze_recording_surface_pattern (surface, mask, &rec_extents); if (_cairo_int_status_is_error (backend_mask_status)) return backend_mask_status; + + _cairo_rectangle_intersect (&extents, &rec_extents); } } @@ -433,14 +494,10 @@ _cairo_analysis_surface_mask (void *abstract_surface, backend_mask_status); } - _cairo_analysis_surface_operation_extents (surface, - op, source, clip, - &extents); - if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t mask_extents; - _cairo_pattern_get_extents (mask, &mask_extents); + _cairo_pattern_get_extents (mask, &mask_extents, surface->target->is_vector); _cairo_rectangle_intersect (&extents, &mask_extents); } @@ -448,16 +505,16 @@ _cairo_analysis_surface_mask (void *abstract_surface, } static cairo_int_status_t -_cairo_analysis_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) +_cairo_analysis_surface_stroke (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_path_fixed_t *path, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; @@ -476,12 +533,14 @@ _cairo_analysis_surface_stroke (void *abstract_surface, return backend_status; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t mask_extents; @@ -508,7 +567,7 @@ _cairo_analysis_surface_fill (void *abstract_surface, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, - const cairo_clip_t *clip) + const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; @@ -526,12 +585,14 @@ _cairo_analysis_surface_fill (void *abstract_surface, return backend_status; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t mask_extents; @@ -588,12 +649,14 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface, backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } if (_cairo_operator_bounded_by_mask (op)) { status = _cairo_scaled_font_glyph_device_extents (scaled_font, @@ -664,12 +727,14 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, return backend_status; } - if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) - backend_status = _analyze_recording_surface_pattern (surface, source); - _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); + if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { + cairo_rectangle_int_t rec_extents; + backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); + _cairo_rectangle_intersect (&extents, &rec_extents); + } if (_cairo_operator_bounded_by_mask (op)) { status = _cairo_scaled_font_glyph_device_extents (scaled_font, @@ -686,6 +751,39 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, return _add_operation (surface, &extents, backend_status); } +static cairo_int_status_t +_cairo_analysis_surface_tag (void *abstract_surface, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip) +{ + cairo_analysis_surface_t *surface = abstract_surface; + cairo_int_status_t backend_status; + + backend_status = CAIRO_INT_STATUS_SUCCESS; + if (surface->target->backend->tag != NULL) { + backend_status = + surface->target->backend->tag (surface->target, + begin, + tag_name, + attributes, + source, + stroke_style, + ctm, + ctm_inverse, + clip); + if (_cairo_int_status_is_error (backend_status)) + return backend_status; + } + + return backend_status; +} + static const cairo_surface_backend_t cairo_analysis_surface_backend = { CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS, @@ -718,7 +816,9 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = { NULL, /* fill_stroke */ _cairo_analysis_surface_show_glyphs, _cairo_analysis_surface_has_show_text_glyphs, - _cairo_analysis_surface_show_text_glyphs + _cairo_analysis_surface_show_text_glyphs, + NULL, /* get_supported_mime_types */ + _cairo_analysis_surface_tag }; cairo_surface_t * @@ -731,7 +831,7 @@ _cairo_analysis_surface_create (cairo_surface_t *target) if (unlikely (status)) return _cairo_surface_create_in_error (status); - surface = malloc (sizeof (cairo_analysis_surface_t)); + surface = _cairo_malloc (sizeof (cairo_analysis_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -740,7 +840,8 @@ _cairo_analysis_surface_create (cairo_surface_t *target) _cairo_surface_init (&surface->base, &cairo_analysis_surface_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + target->is_vector); cairo_matrix_init_identity (&surface->ctm); surface->has_ctm = FALSE; @@ -920,7 +1021,7 @@ _cairo_null_surface_create (cairo_content_t content) { cairo_surface_t *surface; - surface = malloc (sizeof (cairo_surface_t)); + surface = _cairo_malloc (sizeof (cairo_surface_t)); if (unlikely (surface == NULL)) { return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } @@ -928,7 +1029,8 @@ _cairo_null_surface_create (cairo_content_t content) _cairo_surface_init (surface, &cairo_null_surface_backend, NULL, /* device */ - content); + content, + TRUE); /* is_vector */ return surface; } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-atomic-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-atomic-private.h index 11b2887a147..46761856fac 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-atomic-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-atomic-private.h @@ -45,6 +45,8 @@ #include "config.h" #endif +#include + /* The autoconf on OpenBSD 4.5 produces the malformed constant name * SIZEOF_VOID__ rather than SIZEOF_VOID_P. Work around that here. */ #if !defined(SIZEOF_VOID_P) && defined(SIZEOF_VOID__) @@ -75,6 +77,18 @@ _cairo_atomic_int_get (cairo_atomic_int_t *x) return __atomic_load_n(x, __ATOMIC_SEQ_CST); } +static cairo_always_inline cairo_atomic_int_t +_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x) +{ + return __atomic_load_n(x, __ATOMIC_RELAXED); +} + +static cairo_always_inline void +_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val) +{ + __atomic_store_n(x, val, __ATOMIC_RELAXED); +} + static cairo_always_inline void * _cairo_atomic_ptr_get (void **x) { @@ -143,13 +157,12 @@ _cairo_atomic_ptr_cmpxchg_return_old_impl(void **x, void *oldv, void *newv) #endif -#if HAVE_INTEL_ATOMIC_PRIMITIVES +#if HAVE_GCC_LEGACY_ATOMICS #define HAS_ATOMIC_OPS 1 typedef int cairo_atomic_int_t; -#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER static cairo_always_inline cairo_atomic_int_t _cairo_atomic_int_get (cairo_atomic_int_t *x) { @@ -157,16 +170,24 @@ _cairo_atomic_int_get (cairo_atomic_int_t *x) return *x; } +static cairo_always_inline cairo_atomic_int_t +_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x) +{ + return *x; +} + +static cairo_always_inline void +_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val) +{ + *x = val; +} + static cairo_always_inline void * _cairo_atomic_ptr_get (void **x) { __sync_synchronize (); return *x; } -#else -# define _cairo_atomic_int_get(x) (*x) -# define _cairo_atomic_ptr_get(x) (*x) -#endif # define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1)) # define _cairo_atomic_int_dec(x) ((void) __sync_fetch_and_add(x, -1)) @@ -200,6 +221,8 @@ typedef long long cairo_atomic_intptr_t; typedef AO_t cairo_atomic_int_t; # define _cairo_atomic_int_get(x) (AO_load_full (x)) +# define _cairo_atomic_int_get_relaxed(x) (AO_load_full (x)) +# define _cairo_atomic_int_set_relaxed(x, val) (AO_store_full ((x), (val))) # define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x)) # define _cairo_atomic_int_dec(x) ((void) AO_fetch_and_sub1_full(x)) @@ -230,6 +253,8 @@ typedef unsigned long long cairo_atomic_intptr_t; typedef int32_t cairo_atomic_int_t; # define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x)) +# define _cairo_atomic_int_get_relaxed(x) *(x) +# define _cairo_atomic_int_set_relaxed(x, val) *(x) = (val) # define _cairo_atomic_int_inc(x) ((void) OSAtomicIncrement32Barrier (x)) # define _cairo_atomic_int_dec(x) ((void) OSAtomicDecrement32Barrier (x)) @@ -288,9 +313,15 @@ _cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv); #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER cairo_private cairo_atomic_int_t _cairo_atomic_int_get (cairo_atomic_int_t *x); +cairo_private cairo_atomic_int_t +_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x); +void +_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val); # define _cairo_atomic_ptr_get(x) (void *) _cairo_atomic_int_get((cairo_atomic_int_t *) x) #else # define _cairo_atomic_int_get(x) (*x) +# define _cairo_atomic_int_get_relaxed(x) (*x) +# define _cairo_atomic_int_set_relaxed(x, val) (*x) = (val) # define _cairo_atomic_ptr_get(x) (*x) #endif @@ -357,6 +388,37 @@ _cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv) (void) ret__; \ } while (0) +typedef cairo_atomic_int_t cairo_atomic_once_t; + +#define CAIRO_ATOMIC_ONCE_UNINITIALIZED (0) +#define CAIRO_ATOMIC_ONCE_INITIALIZING (1) +#define CAIRO_ATOMIC_ONCE_INITIALIZED (2) +#define CAIRO_ATOMIC_ONCE_INIT CAIRO_ATOMIC_ONCE_UNINITIALIZED + +static cairo_always_inline cairo_bool_t +_cairo_atomic_init_once_enter(cairo_atomic_once_t *once) +{ + if (likely(_cairo_atomic_int_get(once) == CAIRO_ATOMIC_ONCE_INITIALIZED)) + return 0; + + if (_cairo_atomic_int_cmpxchg(once, + CAIRO_ATOMIC_ONCE_UNINITIALIZED, + CAIRO_ATOMIC_ONCE_INITIALIZING)) + return 1; + + while (_cairo_atomic_int_get(once) != CAIRO_ATOMIC_ONCE_INITIALIZED) {} + return 0; +} + +static cairo_always_inline void +_cairo_atomic_init_once_leave(cairo_atomic_once_t *once) +{ + if (unlikely(!_cairo_atomic_int_cmpxchg(once, + CAIRO_ATOMIC_ONCE_INITIALIZING, + CAIRO_ATOMIC_ONCE_INITIALIZED))) + assert (0 && "incorrect use of _cairo_atomic_init_once API (once != CAIRO_ATOMIC_ONCE_INITIALIZING)"); +} + CAIRO_END_DECLS #endif diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-atomic.c b/Build/source/libs/cairo/cairo-src/src/cairo-atomic.c index 909cfea4925..2af50cd3878 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-atomic.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-atomic.c @@ -101,6 +101,20 @@ _cairo_atomic_int_get (cairo_atomic_intptr_t *x) return ret; } + +cairo_atomic_intptr_t +_cairo_atomic_int_get_relaxed (cairo_atomic_intptr_t *x) +{ + return _cairo_atomic_int_get (x); +} + +void +_cairo_atomic_int_set_relaxed (cairo_atomic_intptr_t *x, cairo_atomic_intptr_t val) +{ + CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); + *x = val; + CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); +} #endif #endif diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-backend-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-backend-private.h index b05eca59ab3..67607c12f3a 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-backend-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-backend-private.h @@ -172,6 +172,9 @@ struct _cairo_backend { cairo_status_t (*copy_page) (void *cr); cairo_status_t (*show_page) (void *cr); + + cairo_status_t (*tag_begin) (void *cr, const char *tag_name, const char *attributes); + cairo_status_t (*tag_end) (void *cr, const char *tag_name); }; static inline void diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-base64-stream.c b/Build/source/libs/cairo/cairo-src/src/cairo-base64-stream.c index 636431372b5..6352545f785 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-base64-stream.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-base64-stream.c @@ -125,7 +125,7 @@ _cairo_base64_stream_create (cairo_output_stream_t *output) if (output->status) return _cairo_output_stream_create_in_error (output->status); - stream = malloc (sizeof (cairo_base64_stream_t)); + stream = _cairo_malloc (sizeof (cairo_base64_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-base85-stream.c b/Build/source/libs/cairo/cairo-src/src/cairo-base85-stream.c index f81affb49ea..3202f1e5fb4 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-base85-stream.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-base85-stream.c @@ -114,7 +114,7 @@ _cairo_base85_stream_create (cairo_output_stream_t *output) if (output->status) return _cairo_output_stream_create_in_error (output->status); - stream = malloc (sizeof (cairo_base85_stream_t)); + stream = _cairo_malloc (sizeof (cairo_base85_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-bentley-ottmann-rectangular.c b/Build/source/libs/cairo/cairo-src/src/cairo-bentley-ottmann-rectangular.c index cb2e30c8a96..65f95d79705 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-bentley-ottmann-rectangular.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-bentley-ottmann-rectangular.c @@ -593,12 +593,6 @@ sweep_line_insert (sweep_line_t *sweep, rectangle_t *rectangle) pqueue_push (sweep, rectangle); } -static int -sweep_line_setjmp (sweep_line_t *sweep_line) -{ - return setjmp (sweep_line->unwind); -} - static cairo_status_t _cairo_bentley_ottmann_tessellate_rectangular (rectangle_t **rectangles, int num_rectangles, @@ -609,15 +603,17 @@ _cairo_bentley_ottmann_tessellate_rectangular (rectangle_t **rectangles, sweep_line_t sweep_line; rectangle_t *rectangle; cairo_status_t status; - cairo_bool_t update = FALSE; + cairo_bool_t update; sweep_line_init (&sweep_line, rectangles, num_rectangles, fill_rule, do_traps, container); - if ((status = sweep_line_setjmp (&sweep_line))) + if ((status = setjmp (sweep_line.unwind))) return status; + update = FALSE; + rectangle = rectangle_pop_start (&sweep_line); do { if (rectangle->top != sweep_line.current_y) { @@ -678,10 +674,19 @@ _cairo_bentley_ottmann_tessellate_rectangular_traps (cairo_traps_t *traps, cairo_status_t status; int i; - if (unlikely (traps->num_traps <= 1)) + assert (traps->is_rectangular); + + if (unlikely (traps->num_traps <= 1)) { + if (traps->num_traps == 1) { + cairo_trapezoid_t *trap = traps->traps; + if (trap->left.p1.x > trap->right.p1.x) { + cairo_line_t tmp = trap->left; + trap->left = trap->right; + trap->right = tmp; + } + } return CAIRO_STATUS_SUCCESS; - - assert (traps->is_rectangular); + } dump_traps (traps, "bo-rects-traps-in.txt"); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-bentley-ottmann.c b/Build/source/libs/cairo/cairo-src/src/cairo-bentley-ottmann.c index 91e41f9c3cb..2011e73bd2d 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-bentley-ottmann.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-bentley-ottmann.c @@ -1484,10 +1484,13 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps, ymin = _cairo_fixed_integer_floor (polygon->limit.p1.y); ymax = _cairo_fixed_integer_ceil (polygon->limit.p2.y) - ymin; - if (ymax > 64) + if (ymax > 64) { event_y = _cairo_malloc_ab(sizeof (cairo_bo_event_t*), ymax); - else + if (unlikely (event_y == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } else { event_y = stack_event_y; + } memset (event_y, 0, ymax * sizeof(cairo_bo_event_t *)); } @@ -1498,8 +1501,11 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps, sizeof (cairo_bo_start_event_t) + sizeof (cairo_bo_event_t *), sizeof (cairo_bo_event_t *)); - if (unlikely (events == NULL)) + if (unlikely (events == NULL)) { + if (event_y != stack_event_y) + free (event_y); return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } event_ptrs = (cairo_bo_event_t **) (events + num_events); } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-botor-scan-converter.c b/Build/source/libs/cairo/cairo-src/src/cairo-botor-scan-converter.c index 515305bf24e..438f96bb86f 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-botor-scan-converter.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-botor-scan-converter.c @@ -456,7 +456,7 @@ edges_compare_x_for_y (const cairo_edge_t *a, HAVE_BX = 0x2, HAVE_BOTH = HAVE_AX | HAVE_BX } have_ax_bx = HAVE_BOTH; - int32_t ax, bx; + int32_t ax = 0, bx = 0; /* XXX given we have x and dx? */ @@ -2128,6 +2128,44 @@ botor_add_edge (cairo_botor_scan_converter_t *self, return CAIRO_STATUS_SUCCESS; } +#if 0 +static cairo_status_t +_cairo_botor_scan_converter_add_edge (void *converter, + const cairo_point_t *p1, + const cairo_point_t *p2, + int top, int bottom, + int dir) +{ + cairo_botor_scan_converter_t *self = converter; + cairo_edge_t edge; + + edge.line.p1 = *p1; + edge.line.p2 = *p2; + edge.top = top; + edge.bottom = bottom; + edge.dir = dir; + + return botor_add_edge (self, &edge); +} +#endif + +cairo_status_t +_cairo_botor_scan_converter_add_polygon (cairo_botor_scan_converter_t *converter, + const cairo_polygon_t *polygon) +{ + cairo_botor_scan_converter_t *self = converter; + cairo_status_t status; + int i; + + for (i = 0; i < polygon->num_edges; i++) { + status = botor_add_edge (self, &polygon->edges[i]); + if (unlikely (status)) + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + static void _cairo_botor_scan_converter_destroy (void *converter) { diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-box-inline.h b/Build/source/libs/cairo/cairo-src/src/cairo-box-inline.h index d6b994127e3..59e5a0d5f19 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-box-inline.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-box-inline.h @@ -57,6 +57,16 @@ _cairo_box_from_integers (cairo_box_t *box, int x, int y, int w, int h) box->p2.y = _cairo_fixed_from_int (y + h); } +static inline void +_cairo_box_from_rectangle_int (cairo_box_t *box, + const cairo_rectangle_int_t *rect) +{ + box->p1.x = _cairo_fixed_from_int (rect->x); + box->p1.y = _cairo_fixed_from_int (rect->y); + box->p2.x = _cairo_fixed_from_int (rect->x + rect->width); + box->p2.y = _cairo_fixed_from_int (rect->y + rect->height); +} + /* assumes box->p1 is top-left, p2 bottom-right */ static inline void _cairo_box_add_point (cairo_box_t *box, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-boxes-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-boxes-private.h index d1f9dfcd1e5..fd622aec316 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-boxes-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-boxes-private.h @@ -92,8 +92,7 @@ _cairo_boxes_extents (const cairo_boxes_t *boxes, cairo_private cairo_box_t * _cairo_boxes_to_array (const cairo_boxes_t *boxes, - int *num_boxes, - cairo_bool_t force_allocation); + int *num_boxes); cairo_private cairo_status_t _cairo_boxes_intersect (const cairo_boxes_t *a, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-boxes.c b/Build/source/libs/cairo/cairo-src/src/cairo-boxes.c index 63b68ddfb90..3c5d2a75029 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-boxes.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-boxes.c @@ -102,6 +102,17 @@ _cairo_boxes_init_for_array (cairo_boxes_t *boxes, boxes->is_pixel_aligned = n == num_boxes; } +/** _cairo_boxes_limit: + * + * Computes the minimum bounding box of the given list of boxes and assign + * it to the given boxes set. It also assigns that list as the list of + * limiting boxes in the box set. + * + * @param boxes the box set to be filled (return buffer) + * @param limits array of the limiting boxes to compute the bounding + * box from + * @param num_limits length of the limits array + */ void _cairo_boxes_limit (cairo_boxes_t *boxes, const cairo_box_t *limits, @@ -265,6 +276,14 @@ _cairo_boxes_add (cairo_boxes_t *boxes, return boxes->status; } +/** _cairo_boxes_extents: + * + * Computes the minimum bounding box of the given box set and stores + * it in the given box. + * + * @param boxes The box set whose minimum bounding is computed. + * @param box Return buffer for the computed result. + */ void _cairo_boxes_extents (const cairo_boxes_t *boxes, cairo_box_t *box) @@ -317,18 +336,25 @@ _cairo_boxes_clear (cairo_boxes_t *boxes) boxes->is_pixel_aligned = TRUE; } +/** _cairo_boxes_to_array: + * + * Linearize a box set of possibly multiple chunks into one big chunk + * and returns an array of boxes + * + * @param boxes The box set to be converted. + * @param num_boxes Return buffer for the number of boxes (array count). + * @return Pointer to the newly allocated array of boxes + * (the number o elements is given in num_boxes). + */ cairo_box_t * _cairo_boxes_to_array (const cairo_boxes_t *boxes, - int *num_boxes, - cairo_bool_t force_allocation) + int *num_boxes) { const struct _cairo_boxes_chunk *chunk; cairo_box_t *box; int i, j; *num_boxes = boxes->num_boxes; - if (boxes->chunks.next == NULL && ! force_allocation) - return boxes->chunks.base; box = _cairo_malloc_ab (boxes->num_boxes, sizeof (cairo_box_t)); if (box == NULL) { diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-cff-subset.c b/Build/source/libs/cairo/cairo-src/src/cairo-cff-subset.c index c93a8bd8696..37727eddb45 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-cff-subset.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-cff-subset.c @@ -295,20 +295,11 @@ decode_nibble (int n, char *buf) static unsigned char * decode_real (unsigned char *p, double *real) { - const char *decimal_point; - int decimal_point_len; - int n; char buffer[100]; - char buffer2[200]; - char *q; char *buf = buffer; char *buf_end = buffer + sizeof (buffer); - - decimal_point = cairo_get_locale_decimal_point (); - decimal_point_len = strlen (decimal_point); - - assert (decimal_point_len != 0); - assert (sizeof(buffer) + decimal_point_len < sizeof(buffer2)); + char *end; + int n; p++; while (buf + 2 < buf_end) { @@ -324,19 +315,7 @@ decode_real (unsigned char *p, double *real) }; *buf = 0; - buf = buffer; - if (strchr (buffer, '.')) { - q = strchr (buffer, '.'); - strncpy (buffer2, buffer, q - buffer); - buf = buffer2 + (q - buffer); - strncpy (buf, decimal_point, decimal_point_len); - buf += decimal_point_len; - strcpy (buf, q + 1); - buf = buffer2; - } - - if (sscanf(buf, "%lf", real) != 1) - *real = 0.0; + *real = _cairo_strtod (buffer, &end); return p; } @@ -568,7 +547,7 @@ cff_index_append_copy (cairo_array_t *index, element.length = length; element.is_copy = TRUE; - element.data = malloc (element.length); + element.data = _cairo_malloc (element.length); if (unlikely (element.data == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -631,12 +610,12 @@ cff_dict_create_operator (int operator, { cff_dict_operator_t *op; - op = malloc (sizeof (cff_dict_operator_t)); + op = _cairo_malloc (sizeof (cff_dict_operator_t)); if (unlikely (op == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); _cairo_dict_init_key (op, operator); - op->operand = malloc (size); + op->operand = _cairo_malloc (size); if (unlikely (op->operand == NULL)) { free (op); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -737,7 +716,7 @@ cff_dict_set_operands (cairo_hash_table_t *dict, op = _cairo_hash_table_lookup (dict, &key.base); if (op != NULL) { free (op->operand); - op->operand = malloc (size); + op->operand = _cairo_malloc (size); if (unlikely (op->operand == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -891,7 +870,7 @@ cairo_cff_font_read_name (cairo_cff_font_t *font) len -= 7; } } - font->ps_name = malloc (len + 1); + font->ps_name = _cairo_malloc (len + 1); if (unlikely (font->ps_name == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1879,7 +1858,7 @@ cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font) cairo_status_t status; font->num_fontdicts = 1; - font->fd_dict = malloc (sizeof (cairo_hash_table_t *)); + font->fd_dict = _cairo_malloc (sizeof (cairo_hash_table_t *)); if (unlikely (font->fd_dict == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1890,11 +1869,11 @@ cairo_cff_font_create_cid_fontdict (cairo_cff_font_t *font) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - font->fd_subset_map = malloc (sizeof (int)); + font->fd_subset_map = _cairo_malloc (sizeof (int)); if (unlikely (font->fd_subset_map == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - font->private_dict_offset = malloc (sizeof (int)); + font->private_dict_offset = _cairo_malloc (sizeof (int)); if (unlikely (font->private_dict_offset == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1989,7 +1968,7 @@ cairo_cff_font_subset_font (cairo_cff_font_t *font) if (unlikely (status)) return status; } else { - font->private_dict_offset = malloc (sizeof (int)); + font->private_dict_offset = _cairo_malloc (sizeof (int)); if (unlikely (font->private_dict_offset == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -2581,7 +2560,7 @@ cairo_cff_font_generate (cairo_cff_font_t *font, /* If the PS name is not found, create a CairoFont-x-y name. */ if (font->ps_name == NULL) { - font->ps_name = malloc (30); + font->ps_name = _cairo_malloc (30); if (unlikely (font->ps_name == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2731,7 +2710,7 @@ _cairo_cff_font_load_opentype_cff (cairo_cff_font_t *font) font->is_opentype = TRUE; font->data_length = data_length; - font->data = malloc (data_length); + font->data = _cairo_malloc (data_length); if (unlikely (font->data == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2766,7 +2745,7 @@ _cairo_cff_font_load_cff (cairo_cff_font_t *font) font->font_name = NULL; font->is_opentype = FALSE; font->data_length = data_length; - font->data = malloc (data_length); + font->data = _cairo_malloc (data_length); if (unlikely (font->data == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2788,13 +2767,20 @@ _cairo_cff_font_create (cairo_scaled_font_subset_t *scaled_font_subset, { const cairo_scaled_font_backend_t *backend; cairo_int_status_t status; + cairo_bool_t is_synthetic; cairo_cff_font_t *font; backend = scaled_font_subset->scaled_font->backend; - /* We need to use a fallback font generated from the synthesized outlines. */ - if (backend->is_synthetic && backend->is_synthetic (scaled_font_subset->scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; + /* We need to use a fallback font if this font differs from the CFF outlines. */ + if (backend->is_synthetic) { + status = backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic); + if (unlikely (status)) + return status; + + if (is_synthetic) + return CAIRO_INT_STATUS_UNSUPPORTED; + } font = calloc (1, sizeof (cairo_cff_font_t)); if (unlikely (font == NULL)) @@ -2995,7 +2981,7 @@ _cairo_cff_subset_init (cairo_cff_subset_t *cff_subset, cff_subset->ascent = (double)font->ascent/font->units_per_em; cff_subset->descent = (double)font->descent/font->units_per_em; - cff_subset->data = malloc (length); + cff_subset->data = _cairo_malloc (length); if (unlikely (cff_subset->data == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail4; @@ -3054,7 +3040,7 @@ _cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font) (status = backend->load_truetype_table (scaled_font, TT_TAG_CFF, 0, NULL, &data_length)) == CAIRO_INT_STATUS_SUCCESS) { - data = malloc (data_length); + data = _cairo_malloc (data_length); if (unlikely (data == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); return FALSE; @@ -3071,7 +3057,7 @@ _cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font) (status = backend->load_type1_data (scaled_font, 0, NULL, &data_length)) == CAIRO_INT_STATUS_SUCCESS) { - data = malloc (data_length); + data = _cairo_malloc (data_length); if (unlikely (data == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); return FALSE; @@ -3144,7 +3130,7 @@ _cairo_cff_font_fallback_create (cairo_scaled_font_subset_t *scaled_font_subset cairo_status_t status; cairo_cff_font_t *font; - font = malloc (sizeof (cairo_cff_font_t)); + font = _cairo_malloc (sizeof (cairo_cff_font_t)); if (unlikely (font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -3330,7 +3316,7 @@ cairo_cff_font_fallback_generate (cairo_cff_font_t *font, if (unlikely (status)) return status; } else { - font->private_dict_offset = malloc (sizeof (int)); + font->private_dict_offset = _cairo_malloc (sizeof (int)); if (unlikely (font->private_dict_offset == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -3407,7 +3393,7 @@ _cairo_cff_fallback_init (cairo_cff_subset_t *cff_subset, cff_subset->ascent = (double)type2_subset.y_max/1000; cff_subset->descent = (double)type2_subset.y_min/1000; - cff_subset->data = malloc (length); + cff_subset->data = _cairo_malloc (length); if (unlikely (cff_subset->data == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail4; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-clip-boxes.c b/Build/source/libs/cairo/cairo-src/src/cairo-clip-boxes.c index 7bcbeb1918a..aaddeb7f7be 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-clip-boxes.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-clip-boxes.c @@ -119,11 +119,7 @@ _cairo_clip_contains_rectangle (const cairo_clip_t *clip, { cairo_box_t box; - box.p1.x = _cairo_fixed_from_int (rect->x); - box.p1.y = _cairo_fixed_from_int (rect->y); - box.p2.x = _cairo_fixed_from_int (rect->x + rect->width); - box.p2.y = _cairo_fixed_from_int (rect->y + rect->height); - + _cairo_box_from_rectangle_int (&box, rect); return _cairo_clip_contains_rectangle_box (clip, rect, &box); } @@ -268,6 +264,34 @@ _cairo_clip_intersect_box (cairo_clip_t *clip, return _cairo_clip_intersect_rectangle_box (clip, &r, box); } +/* Copy a box set to a clip + * + * @param boxes The box set to copy from. + * @param clip The clip to copy to (return buffer). + * @returns Zero if the allocation failed (the clip will be set to + * all-clipped), otherwise non-zero. + */ +static cairo_bool_t +_cairo_boxes_copy_to_clip (const cairo_boxes_t *boxes, cairo_clip_t *clip) +{ + /* XXX cow-boxes? */ + if (boxes->num_boxes == 1) { + clip->boxes = &clip->embedded_box; + clip->boxes[0] = boxes->chunks.base[0]; + clip->num_boxes = 1; + return TRUE; + } + + clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes); + if (unlikely (clip->boxes == NULL)) + { + _cairo_clip_set_all_clipped (clip); + return FALSE; + } + + return TRUE; +} + cairo_clip_t * _cairo_clip_intersect_boxes (cairo_clip_t *clip, const cairo_boxes_t *boxes) @@ -305,13 +329,10 @@ _cairo_clip_intersect_boxes (cairo_clip_t *clip, if (boxes->num_boxes == 0) { clip = _cairo_clip_set_all_clipped (clip); goto out; - } else if (boxes->num_boxes == 1) { - clip->boxes = &clip->embedded_box; - clip->boxes[0] = boxes->chunks.base[0]; - clip->num_boxes = 1; - } else { - clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE); } + + _cairo_boxes_copy_to_clip (boxes, clip); + _cairo_boxes_extents (boxes, &limits); _cairo_box_round_to_rectangle (&limits, &extents); @@ -347,10 +368,7 @@ _cairo_clip_intersect_rectangle (cairo_clip_t *clip, if (r->width == 0 || r->height == 0) return _cairo_clip_set_all_clipped (clip); - box.p1.x = _cairo_fixed_from_int (r->x); - box.p1.y = _cairo_fixed_from_int (r->y); - box.p2.x = _cairo_fixed_from_int (r->x + r->width); - box.p2.y = _cairo_fixed_from_int (r->y + r->height); + _cairo_box_from_rectangle_int (&box, r); return _cairo_clip_intersect_rectangle_box (clip, r, &box); } @@ -581,16 +599,8 @@ _cairo_clip_from_boxes (const cairo_boxes_t *boxes) if (clip == NULL) return _cairo_clip_set_all_clipped (clip); - /* XXX cow-boxes? */ - if(boxes->num_boxes == 1) { - clip->boxes = &clip->embedded_box; - clip->boxes[0] = boxes->chunks.base[0]; - clip->num_boxes = 1; - } else { - clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE); - if (clip->boxes == NULL) - return _cairo_clip_set_all_clipped (clip); - } + if (unlikely (! _cairo_boxes_copy_to_clip (boxes, clip))) + return clip; _cairo_boxes_extents (boxes, &extents); _cairo_box_round_to_rectangle (&extents, &clip->extents); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-clip-tor-scan-converter.c b/Build/source/libs/cairo/cairo-src/src/cairo-clip-tor-scan-converter.c index e32a5a9d9c7..2ac1d32b138 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-clip-tor-scan-converter.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-clip-tor-scan-converter.c @@ -29,7 +29,7 @@ * The source is from commit 734c53237a867a773640bd5b64816249fa1730f8 * of * - * http://gitweb.freedesktop.org/?p=users/joonas/glitter-paths + * https://gitweb.freedesktop.org/?p=users/joonas/glitter-paths */ /* Glitter-paths is a stand alone polygon rasteriser derived from * David Turner's reimplementation of Tor Anderssons's 15x17 @@ -465,7 +465,7 @@ _pool_chunk_create(struct pool *pool, size_t size) { struct _pool_chunk *p; - p = malloc(size + sizeof(struct _pool_chunk)); + p = _cairo_malloc (size + sizeof(struct _pool_chunk)); if (unlikely (NULL == p)) longjmp (*pool->jmp, _cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-clip.c b/Build/source/libs/cairo/cairo-src/src/cairo-clip.c index 0df9b06bf60..d499bf0adec 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-clip.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-clip.c @@ -62,7 +62,7 @@ _cairo_clip_path_create (cairo_clip_t *clip) clip_path = _freed_pool_get (&clip_path_pool); if (unlikely (clip_path == NULL)) { - clip_path = malloc (sizeof (cairo_clip_path_t)); + clip_path = _cairo_malloc (sizeof (cairo_clip_path_t)); if (unlikely (clip_path == NULL)) return NULL; } @@ -108,7 +108,7 @@ _cairo_clip_create (void) clip = _freed_pool_get (&clip_pool); if (unlikely (clip == NULL)) { - clip = malloc (sizeof (cairo_clip_t)); + clip = _cairo_malloc (sizeof (cairo_clip_t)); if (unlikely (clip == NULL)) return NULL; } @@ -735,7 +735,7 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status) if (status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; - list = malloc (sizeof (*list)); + list = _cairo_malloc (sizeof (*list)); if (unlikely (list == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; @@ -795,7 +795,7 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) } DONE: - list = malloc (sizeof (cairo_rectangle_list_t)); + list = _cairo_malloc (sizeof (cairo_rectangle_list_t)); if (unlikely (list == NULL)) { free (rectangles); return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-cogl-context.c b/Build/source/libs/cairo/cairo-src/src/cairo-cogl-context.c index 0116b0a5a93..c3227805766 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-cogl-context.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-cogl-context.c @@ -755,7 +755,7 @@ _cairo_cogl_context_create (void *target) cr = _freed_pool_get (&context_pool); if (unlikely (cr == NULL)) { - cr = malloc (sizeof (cairo_cogl_context_t)); + cr = _cairo_malloc (sizeof (cairo_cogl_context_t)); if (unlikely (cr == NULL)) return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-cogl-gradient.c b/Build/source/libs/cairo/cairo-src/src/cairo-cogl-gradient.c index f8c80041629..0923e3b6d95 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-cogl-gradient.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-cogl-gradient.c @@ -397,7 +397,7 @@ _cairo_cogl_get_linear_gradient (cairo_cogl_device_t *device, } if (!gradient) { - gradient = malloc (sizeof (cairo_cogl_linear_gradient_t) + + gradient = _cairo_malloc (sizeof (cairo_cogl_linear_gradient_t) + sizeof (cairo_gradient_stop_t) * (n_stops - 1)); if (!gradient) return CAIRO_INT_STATUS_NO_MEMORY; @@ -413,7 +413,7 @@ _cairo_cogl_get_linear_gradient (cairo_cogl_device_t *device, } else _cairo_cogl_linear_gradient_reference (gradient); - entry = malloc (sizeof (cairo_cogl_linear_texture_entry_t)); + entry = _cairo_malloc (sizeof (cairo_cogl_linear_texture_entry_t)); if (!entry) { status = CAIRO_INT_STATUS_NO_MEMORY; goto BAIL; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-cogl-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-cogl-surface.c index c57fd7f433c..2f7ed58d333 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-cogl-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-cogl-surface.c @@ -517,7 +517,7 @@ _cairo_cogl_surface_allocate_buffer_space (cairo_cogl_surface_t *surface, void **pointer) { /* XXX: In the Cogl journal we found it more efficient to have a pool of - * buffers that we re-cycle but for now we simply thow away our stack + * buffers that we re-cycle but for now we simply throw away our stack * buffer each time we flush. */ if (unlikely (surface->buffer_stack && (surface->buffer_stack_size - surface->buffer_stack_offset) < size)) { @@ -1994,7 +1994,7 @@ _cairo_cogl_get_path_stroke_meta (cairo_cogl_surface_t *surface, CAIRO_REFERENCE_COUNT_INIT (&meta->ref_count, 1); meta->cache_entry.hash = hash; meta->counter = 0; - meta_path = malloc (sizeof (cairo_path_fixed_t)); + meta_path = _cairo_malloc (sizeof (cairo_path_fixed_t)); if (!meta_path) goto BAIL; /* FIXME: we should add a ref-counted wrapper for our user_paths @@ -2248,7 +2248,7 @@ _cairo_cogl_get_path_fill_meta (cairo_cogl_surface_t *surface) meta->cache_entry.hash = hash; meta->counter = 0; CAIRO_REFERENCE_COUNT_INIT (&meta->ref_count, 1); - meta_path = malloc (sizeof (cairo_path_fixed_t)); + meta_path = _cairo_malloc (sizeof (cairo_path_fixed_t)); if (!meta_path) goto BAIL; /* FIXME: we should add a ref-counted wrapper for our user_paths @@ -2504,7 +2504,7 @@ _cairo_cogl_surface_create_full (cairo_cogl_device_t *dev, if (unlikely (status)) return _cairo_surface_create_in_error (status); - surface = malloc (sizeof (cairo_cogl_surface_t)); + surface = _cairo_malloc (sizeof (cairo_cogl_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -2544,7 +2544,8 @@ _cairo_cogl_surface_create_full (cairo_cogl_device_t *dev, _cairo_surface_init (&surface->base, &_cairo_cogl_surface_backend, &dev->base, - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + FALSE); /* is_vector */ return &surface->base; } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-compiler-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-compiler-private.h index 216e71b4ec3..d982c101d04 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-compiler-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-compiler-private.h @@ -69,7 +69,7 @@ * call sites. The macro works by renaming `f' to an internal name * in the symbol table and hiding that. As far as cairo internal * calls are concerned they're calling a library internal function - * and thus don't need to bounce via the PLT. + * and thus don't need to bounce via the procedure linkage table (PLT). * * slim_hidden_def(f) * diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-composite-rectangles.c b/Build/source/libs/cairo/cairo-src/src/cairo-composite-rectangles.c index 6c3e97d4a97..f102eddbce9 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-composite-rectangles.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-composite-rectangles.c @@ -97,7 +97,8 @@ _cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents, _cairo_composite_reduce_pattern (source, &extents->source_pattern); _cairo_pattern_get_extents (&extents->source_pattern.base, - &extents->source); + &extents->source, + surface->is_vector); if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) { if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source)) return FALSE; @@ -146,10 +147,8 @@ static cairo_int_status_t _cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents, const cairo_clip_t *clip) { - cairo_bool_t ret; - - ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask); - if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) + if ((!_cairo_rectangle_intersect (&extents->bounded, &extents->mask)) && + (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)) return CAIRO_INT_STATUS_NOTHING_TO_DO; if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE)) { @@ -318,7 +317,7 @@ _cairo_composite_rectangles_intersect_mask_extents (cairo_composite_rectangles_t cairo_int_status_t _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents, - cairo_surface_t*surface, + cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, @@ -332,7 +331,7 @@ _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents extents->original_mask_pattern = mask; _cairo_composite_reduce_pattern (mask, &extents->mask_pattern); - _cairo_pattern_get_extents (&extents->mask_pattern.base, &extents->mask); + _cairo_pattern_get_extents (&extents->mask_pattern.base, &extents->mask, surface->is_vector); return _cairo_composite_rectangles_intersect (extents, clip); } @@ -353,7 +352,7 @@ _cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *exten return CAIRO_INT_STATUS_NOTHING_TO_DO; } - _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &extents->mask); + _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, surface->is_vector, &extents->mask); return _cairo_composite_rectangles_intersect (extents, clip); } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-damage.c b/Build/source/libs/cairo/cairo-src/src/cairo-damage.c index 63191fee95d..97d9fe9095b 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-damage.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-damage.c @@ -51,7 +51,7 @@ _cairo_damage_create (void) { cairo_damage_t *damage; - damage = malloc (sizeof (*damage)); + damage = _cairo_malloc (sizeof (*damage)); if (unlikely (damage == NULL)) { _cairo_error_throw(CAIRO_STATUS_NO_MEMORY); return (cairo_damage_t *) &__cairo_damage__nil; @@ -122,7 +122,7 @@ _cairo_damage_add_boxes(cairo_damage_t *damage, if (size < count) size = (count + 64) & ~63; - chunk = malloc (sizeof (*chunk) + sizeof (cairo_box_t) * size); + chunk = _cairo_malloc (sizeof (*chunk) + sizeof (cairo_box_t) * size); if (unlikely (chunk == NULL)) { _cairo_damage_destroy (damage); return (cairo_damage_t *) &__cairo_damage__nil; @@ -210,7 +210,7 @@ _cairo_damage_reduce (cairo_damage_t *damage) boxes = damage->tail->base; if (damage->dirty > damage->tail->size) { - boxes = free_boxes = malloc (damage->dirty * sizeof (cairo_box_t)); + boxes = free_boxes = _cairo_malloc (damage->dirty * sizeof (cairo_box_t)); if (unlikely (boxes == NULL)) { _cairo_damage_destroy (damage); return (cairo_damage_t *) &__cairo_damage__nil; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-debug.c b/Build/source/libs/cairo/cairo-src/src/cairo-debug.c index e7ffe48d28c..6005060d4a0 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-debug.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-debug.c @@ -86,6 +86,8 @@ cairo_debug_reset_static_data (void) _cairo_image_reset_static_data (); + _cairo_image_compositor_reset_static_data (); + #if CAIRO_HAS_DRM_SURFACE _cairo_drm_device_reset_static_data (); #endif @@ -237,7 +239,7 @@ _print_close (void *closure) } void -_cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path) +_cairo_debug_print_path (FILE *stream, const cairo_path_fixed_t *path) { cairo_status_t status; cairo_box_t box; @@ -302,3 +304,20 @@ _cairo_debug_print_polygon (FILE *stream, cairo_polygon_t *polygon) } } + +void +_cairo_debug_print_matrix (FILE *file, const cairo_matrix_t *matrix) +{ + fprintf (file, "[%g %g %g %g %g %g]\n", + matrix->xx, matrix->yx, + matrix->xy, matrix->yy, + matrix->x0, matrix->y0); +} + +void +_cairo_debug_print_rect (FILE *file, const cairo_rectangle_int_t *rect) +{ + fprintf (file, "x: %d y: %d width: %d height: %d\n", + rect->x, rect->y, + rect->width, rect->height); +} diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-default-context.c b/Build/source/libs/cairo/cairo-src/src/cairo-default-context.c index 1e5067bf1b8..985215ff739 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-default-context.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-default-context.c @@ -1155,6 +1155,24 @@ _cairo_default_context_copy_page (void *abstract_cr) return _cairo_gstate_copy_page (cr->gstate); } +static cairo_status_t +_cairo_default_context_tag_begin (void *abstract_cr, + const char *tag_name, const char *attributes) +{ + cairo_default_context_t *cr = abstract_cr; + + return _cairo_gstate_tag_begin (cr->gstate, tag_name, attributes); +} + +static cairo_status_t +_cairo_default_context_tag_end (void *abstract_cr, + const char *tag_name) +{ + cairo_default_context_t *cr = abstract_cr; + + return _cairo_gstate_tag_end (cr->gstate, tag_name); +} + static cairo_status_t _cairo_default_context_show_page (void *abstract_cr) { @@ -1437,6 +1455,9 @@ static const cairo_backend_t _cairo_default_context_backend = { _cairo_default_context_copy_page, _cairo_default_context_show_page, + + _cairo_default_context_tag_begin, + _cairo_default_context_tag_end, }; cairo_status_t @@ -1460,7 +1481,7 @@ _cairo_default_context_create (void *target) cr = _freed_pool_get (&context_pool); if (unlikely (cr == NULL)) { - cr = malloc (sizeof (cairo_default_context_t)); + cr = _cairo_malloc (sizeof (cairo_default_context_t)); if (unlikely (cr == NULL)) return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-deflate-stream.c b/Build/source/libs/cairo/cairo-src/src/cairo-deflate-stream.c index ae23bda9472..b51a6399cd0 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-deflate-stream.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-deflate-stream.c @@ -124,7 +124,7 @@ _cairo_deflate_stream_create (cairo_output_stream_t *output) if (output->status) return _cairo_output_stream_create_in_error (output->status); - stream = malloc (sizeof (cairo_deflate_stream_t)); + stream = _cairo_malloc (sizeof (cairo_deflate_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-device.c b/Build/source/libs/cairo/cairo-src/src/cairo-device.c index 585a9c1c41f..965c84c6519 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-device.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-device.c @@ -159,6 +159,10 @@ _cairo_device_create_in_error (cairo_status_t status) case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: case CAIRO_STATUS_DEVICE_FINISHED: case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: + case CAIRO_STATUS_PNG_ERROR: + case CAIRO_STATUS_FREETYPE_ERROR: + case CAIRO_STATUS_WIN32_GDI_ERROR: + case CAIRO_STATUS_TAG_ERROR: default: _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_device_t *) &_nil_device; @@ -190,8 +194,8 @@ _cairo_device_init (cairo_device_t *device, * @device from being destroyed until a matching call to * cairo_device_destroy() is made. * - * The number of references to a #cairo_device_t can be get using - * cairo_device_get_reference_count(). + * Use cairo_device_get_reference_count() to get the number of references + * to a #cairo_device_t. * * Return value: the referenced #cairo_device_t. * diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-directfb-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-directfb-surface.c index 5ac64ba98ee..0deedf0d549 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-directfb-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-directfb-surface.c @@ -522,7 +522,8 @@ cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface) _cairo_surface_init (&surface->image.base, &_cairo_dfb_surface_backend, NULL, /* device */ - _directfb_format_to_content (format)); + _directfb_format_to_content (format), + FALSE); /* is_vector */ surface->image.pixman_format = pixman_format; surface->image.format = _cairo_format_from_pixman_format (pixman_format); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-error-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-error-private.h index 178078ad614..1ab57ddf846 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-error-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-error-private.h @@ -94,6 +94,10 @@ enum _cairo_int_status { CAIRO_INT_STATUS_INVALID_MESH_CONSTRUCTION, CAIRO_INT_STATUS_DEVICE_FINISHED, CAIRO_INT_STATUS_JBIG2_GLOBAL_MISSING, + CAIRO_INT_STATUS_PNG_ERROR, + CAIRO_INT_STATUS_FREETYPE_ERROR, + CAIRO_INT_STATUS_WIN32_GDI_ERROR, + CAIRO_INT_STATUS_TAG_ERROR, CAIRO_INT_STATUS_LAST_STATUS, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-font-face-twin.c b/Build/source/libs/cairo/cairo-src/src/cairo-font-face-twin.c index 2ad26302849..a0855c9f601 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-font-face-twin.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-font-face-twin.c @@ -288,7 +288,7 @@ twin_font_face_create_properties (cairo_font_face_t *twin_face) { twin_face_properties_t *props; - props = malloc (sizeof (twin_face_properties_t)); + props = _cairo_malloc (sizeof (twin_face_properties_t)); if (unlikely (props == NULL)) return NULL; @@ -412,7 +412,7 @@ twin_scaled_font_compute_properties (cairo_scaled_font_t *scaled_font, cairo_status_t status; twin_scaled_properties_t *props; - props = malloc (sizeof (twin_scaled_properties_t)); + props = _cairo_malloc (sizeof (twin_scaled_properties_t)); if (unlikely (props == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-font-face.c b/Build/source/libs/cairo/cairo-src/src/cairo-font-face.c index 795951b1420..e10a6eac2f2 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-font-face.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-font-face.c @@ -111,8 +111,8 @@ _cairo_font_face_init (cairo_font_face_t *font_face, * @font_face from being destroyed until a matching call to * cairo_font_face_destroy() is made. * - * The number of references to a #cairo_font_face_t can be get using - * cairo_font_face_get_reference_count(). + * Use cairo_font_face_get_reference_count() to get the number of + * references to a #cairo_font_face_t. * * Return value: the referenced #cairo_font_face_t. * diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-font-options.c b/Build/source/libs/cairo/cairo-src/src/cairo-font-options.c index ad28745e6b9..9aef1407386 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-font-options.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-font-options.c @@ -55,7 +55,8 @@ static const cairo_font_options_t _cairo_font_options_nil = { CAIRO_LCD_FILTER_DEFAULT, CAIRO_HINT_STYLE_DEFAULT, CAIRO_HINT_METRICS_DEFAULT, - CAIRO_ROUND_GLYPH_POS_DEFAULT + CAIRO_ROUND_GLYPH_POS_DEFAULT, + NULL }; /** @@ -73,6 +74,7 @@ _cairo_font_options_init_default (cairo_font_options_t *options) options->hint_style = CAIRO_HINT_STYLE_DEFAULT; options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT; options->round_glyph_positions = CAIRO_ROUND_GLYPH_POS_DEFAULT; + options->variations = NULL; } void @@ -85,6 +87,7 @@ _cairo_font_options_init_copy (cairo_font_options_t *options, options->hint_style = other->hint_style; options->hint_metrics = other->hint_metrics; options->round_glyph_positions = other->round_glyph_positions; + options->variations = other->variations ? strdup (other->variations) : NULL; } /** @@ -106,7 +109,7 @@ cairo_font_options_create (void) { cairo_font_options_t *options; - options = malloc (sizeof (cairo_font_options_t)); + options = _cairo_malloc (sizeof (cairo_font_options_t)); if (!options) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_font_options_t *) &_cairo_font_options_nil; @@ -140,7 +143,7 @@ cairo_font_options_copy (const cairo_font_options_t *original) if (cairo_font_options_status ((cairo_font_options_t *) original)) return (cairo_font_options_t *) &_cairo_font_options_nil; - options = malloc (sizeof (cairo_font_options_t)); + options = _cairo_malloc (sizeof (cairo_font_options_t)); if (!options) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_font_options_t *) &_cairo_font_options_nil; @@ -151,6 +154,12 @@ cairo_font_options_copy (const cairo_font_options_t *original) return options; } +void +_cairo_font_options_fini (cairo_font_options_t *options) +{ + free (options->variations); +} + /** * cairo_font_options_destroy: * @options: a #cairo_font_options_t @@ -166,6 +175,7 @@ cairo_font_options_destroy (cairo_font_options_t *options) if (cairo_font_options_status (options)) return; + _cairo_font_options_fini (options); free (options); } @@ -226,6 +236,24 @@ cairo_font_options_merge (cairo_font_options_t *options, options->hint_metrics = other->hint_metrics; if (other->round_glyph_positions != CAIRO_ROUND_GLYPH_POS_DEFAULT) options->round_glyph_positions = other->round_glyph_positions; + + if (other->variations) { + if (options->variations) { + char *p; + + /* 'merge' variations by concatenating - later entries win */ + p = malloc (strlen (other->variations) + strlen (options->variations) + 2); + p[0] = 0; + strcat (p, options->variations); + strcat (p, ","); + strcat (p, other->variations); + free (options->variations); + options->variations = p; + } + else { + options->variations = strdup (other->variations); + } + } } slim_hidden_def (cairo_font_options_merge); @@ -259,7 +287,10 @@ cairo_font_options_equal (const cairo_font_options_t *options, options->lcd_filter == other->lcd_filter && options->hint_style == other->hint_style && options->hint_metrics == other->hint_metrics && - options->round_glyph_positions == other->round_glyph_positions); + options->round_glyph_positions == other->round_glyph_positions && + ((options->variations == NULL && other->variations == NULL) || + (options->variations != NULL && other->variations != NULL && + strcmp (options->variations, other->variations) == 0))); } slim_hidden_def (cairo_font_options_equal); @@ -280,14 +311,19 @@ slim_hidden_def (cairo_font_options_equal); unsigned long cairo_font_options_hash (const cairo_font_options_t *options) { + unsigned long hash = 0; + if (cairo_font_options_status ((cairo_font_options_t *) options)) options = &_cairo_font_options_nil; /* force default values */ + if (options->variations) + hash = _cairo_string_hash (options->variations, strlen (options->variations)); + return ((options->antialias) | (options->subpixel_order << 4) | (options->lcd_filter << 8) | (options->hint_style << 12) | - (options->hint_metrics << 16)); + (options->hint_metrics << 16)) ^ hash; } slim_hidden_def (cairo_font_options_hash); @@ -533,3 +569,54 @@ cairo_font_options_get_hint_metrics (const cairo_font_options_t *options) return options->hint_metrics; } + +/** + * cairo_font_options_set_variations: + * @options: a #cairo_font_options_t + * @variations: the new font variations, or %NULL + * + * Sets the OpenType font variations for the font options object. + * Font variations are specified as a string with a format that + * is similar to the CSS font-variation-settings. The string contains + * a comma-separated list of axis assignments, which each assignment + * consists of a 4-character axis name and a value, separated by + * whitespace and optional equals sign. + * + * Examples: + * + * wght=200,wdth=140.5 + * + * wght 200 , wdth 140.5 + * + * Since: 1.16 + **/ +void +cairo_font_options_set_variations (cairo_font_options_t *options, + const char *variations) +{ + char *tmp = variations ? strdup (variations) : NULL; + free (options->variations); + options->variations = tmp; +} + +/** + * cairo_font_options_get_variations: + * @options: a #cairo_font_options_t + * + * Gets the OpenType font variations for the font options object. + * See cairo_font_options_set_variations() for details about the + * string format. + * + * Return value: the font variations for the font options object. The + * returned string belongs to the @options and must not be modified. + * It is valid until either the font options object is destroyed or + * the font variations in this object is modified with + * cairo_font_options_set_variations(). + * + * Since: 1.16 + **/ +const char * +cairo_font_options_get_variations (cairo_font_options_t *options) +{ + return options->variations; +} diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-freed-pool-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-freed-pool-private.h index 0ec6de3d1f1..8a7af523db3 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-freed-pool-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-freed-pool-private.h @@ -51,7 +51,7 @@ CAIRO_BEGIN_DECLS #define MAX_FREED_POOL_SIZE 16 typedef struct { void *pool[MAX_FREED_POOL_SIZE]; - int top; + cairo_atomic_int_t top; } freed_pool_t; static cairo_always_inline void * @@ -81,13 +81,13 @@ _freed_pool_get (freed_pool_t *pool) void *ptr; int i; - i = pool->top - 1; + i = _cairo_atomic_int_get_relaxed (&pool->top) - 1; if (i < 0) i = 0; ptr = _atomic_fetch (&pool->pool[i]); if (likely (ptr != NULL)) { - pool->top = i; + _cairo_atomic_int_set_relaxed (&pool->top, i); return ptr; } @@ -103,11 +103,11 @@ _freed_pool_put (freed_pool_t *pool, void *ptr) { int i; - i = pool->top; + i = _cairo_atomic_int_get_relaxed (&pool->top); if (likely (i < ARRAY_LENGTH (pool->pool) && _atomic_store (&pool->pool[i], ptr))) { - pool->top = i + 1; + _cairo_atomic_int_set_relaxed (&pool->top, i + 1); return; } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-freed-pool.c b/Build/source/libs/cairo/cairo-src/src/cairo-freed-pool.c index cfdc8e96b05..5b1c4c0bb2c 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-freed-pool.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-freed-pool.c @@ -50,13 +50,13 @@ _freed_pool_get_search (freed_pool_t *pool) for (i = ARRAY_LENGTH (pool->pool); i--;) { ptr = _atomic_fetch (&pool->pool[i]); if (ptr != NULL) { - pool->top = i; + _cairo_atomic_int_set_relaxed (&pool->top, i); return ptr; } } /* empty */ - pool->top = 0; + _cairo_atomic_int_set_relaxed (&pool->top, 0); return NULL; } @@ -67,13 +67,13 @@ _freed_pool_put_search (freed_pool_t *pool, void *ptr) for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) { if (_atomic_store (&pool->pool[i], ptr)) { - pool->top = i + 1; + _cairo_atomic_int_set_relaxed (&pool->top, i + 1); return; } } /* full */ - pool->top = i; + _cairo_atomic_int_set_relaxed (&pool->top, i); free (ptr); } @@ -87,7 +87,7 @@ _freed_pool_reset (freed_pool_t *pool) pool->pool[i] = NULL; } - pool->top = 0; + _cairo_atomic_int_set_relaxed (&pool->top, 0); } #endif diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-freelist-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-freelist-private.h index 8fe6516f385..f85f6891412 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-freelist-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-freelist-private.h @@ -133,7 +133,7 @@ _cairo_freepool_free (cairo_freepool_t *freepool, void *ptr) node->next = freepool->first_free_node; freepool->first_free_node = node; - VG (VALGRIND_MAKE_MEM_NOACCESS (node, freepool->nodesize)); + VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freepool->nodesize)); } #endif /* CAIRO_FREELIST_H */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-freelist.c b/Build/source/libs/cairo/cairo-src/src/cairo-freelist.c index d596eab81dc..7f2f3b30b81 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-freelist.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-freelist.c @@ -61,7 +61,7 @@ _cairo_freelist_alloc (cairo_freelist_t *freelist) return node; } - return malloc (freelist->nodesize); + return _cairo_malloc (freelist->nodesize); } void * @@ -80,7 +80,7 @@ _cairo_freelist_free (cairo_freelist_t *freelist, void *voidnode) if (node) { node->next = freelist->first_free_node; freelist->first_free_node = node; - VG (VALGRIND_MAKE_MEM_NOACCESS (node, freelist->nodesize)); + VG (VALGRIND_MAKE_MEM_UNDEFINED (node, freelist->nodesize)); } } @@ -97,7 +97,7 @@ _cairo_freepool_init (cairo_freepool_t *freepool, unsigned nodesize) freepool->embedded_pool.rem = sizeof (freepool->embedded_data); freepool->embedded_pool.data = freepool->embedded_data; - VG (VALGRIND_MAKE_MEM_NOACCESS (freepool->embedded_data, sizeof (freepool->embedded_data))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (freepool->embedded_data, sizeof (freepool->embedded_data))); } void @@ -119,7 +119,7 @@ _cairo_freepool_fini (cairo_freepool_t *freepool) pool = next; } - VG (VALGRIND_MAKE_MEM_NOACCESS (freepool, sizeof (freepool))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (freepool, sizeof (freepool))); } void * @@ -139,7 +139,7 @@ _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool) else poolsize = (128 * freepool->nodesize + 8191) & -8192; - pool = malloc (sizeof (cairo_freelist_pool_t) + poolsize); + pool = _cairo_malloc (sizeof (cairo_freelist_pool_t) + poolsize); if (unlikely (pool == NULL)) return pool; @@ -152,7 +152,7 @@ _cairo_freepool_alloc_from_new_pool (cairo_freepool_t *freepool) pool->rem = poolsize - freepool->nodesize; pool->data = (uint8_t *) (pool + 1) + freepool->nodesize; - VG (VALGRIND_MAKE_MEM_NOACCESS (pool->data, pool->rem)); + VG (VALGRIND_MAKE_MEM_UNDEFINED (pool->data, pool->rem)); return pool + 1; } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-ft-font.c b/Build/source/libs/cairo/cairo-src/src/cairo-ft-font.c index 462d1e25fd8..325dd61b47b 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-ft-font.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-ft-font.c @@ -58,6 +58,7 @@ #include FT_BITMAP_H #include FT_TRUETYPE_TABLES_H #include FT_XFREE86_H +#include FT_MULTIPLE_MASTERS_H #if HAVE_FT_GLYPHSLOT_EMBOLDEN #include FT_SYNTHESIS_H #endif @@ -92,7 +93,6 @@ #define FT_LCD_FILTER_LEGACY 16 #endif -#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0) @@ -168,6 +168,10 @@ struct _cairo_ft_unscaled_font { cairo_matrix_t current_shape; FT_Matrix Current_Shape; + unsigned int have_color_set : 1; + unsigned int have_color : 1; /* true if the font contains color glyphs */ + FT_Fixed *variations; /* variation settings that FT_Face came */ + cairo_mutex_t mutex; int lock_count; @@ -187,6 +191,21 @@ typedef struct _cairo_ft_options { unsigned int synth_flags; } cairo_ft_options_t; +static void +_cairo_ft_options_init_copy (cairo_ft_options_t *options, + const cairo_ft_options_t *other) +{ + _cairo_font_options_init_copy (&options->base, &other->base); + options->load_flags = other->load_flags; + options->synth_flags = other->synth_flags; +} + +static void +_cairo_ft_options_fini (cairo_ft_options_t *options) +{ + _cairo_font_options_fini (&options->base); +} + struct _cairo_ft_font_face { cairo_font_face_t base; @@ -223,7 +242,10 @@ _ft_to_cairo_error (FT_Error error) * Populate as needed. */ switch (error) { - default: return CAIRO_STATUS_NO_MEMORY; + case FT_Err_Out_Of_Memory: + return CAIRO_STATUS_NO_MEMORY; + default: + return CAIRO_STATUS_FREETYPE_ERROR; } } @@ -278,7 +300,7 @@ _cairo_ft_unscaled_font_map_create (void) * detect some other call path. */ assert (cairo_ft_unscaled_font_map == NULL); - font_map = malloc (sizeof (cairo_ft_unscaled_font_map_t)); + font_map = _cairo_malloc (sizeof (cairo_ft_unscaled_font_map_t)); if (unlikely (font_map == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -419,9 +441,27 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled, _cairo_unscaled_font_init (&unscaled->base, &cairo_ft_unscaled_font_backend); + unscaled->variations = NULL; + if (from_face) { unscaled->from_face = TRUE; - _cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, face); + _cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, id, face); + + + unscaled->have_color = FT_HAS_COLOR (face) != 0; + unscaled->have_color_set = TRUE; + +#ifdef HAVE_FT_GET_VAR_DESIGN_COORDINATES + { + FT_MM_Var *ft_mm_var; + if (0 == FT_Get_MM_Var (face, &ft_mm_var)) + { + unscaled->variations = calloc (ft_mm_var->num_axis, sizeof (FT_Fixed)); + if (unscaled->variations) + FT_Get_Var_Design_Coordinates (face, ft_mm_var->num_axis, unscaled->variations); + } + } +#endif } else { char *filename_copy; @@ -433,6 +473,8 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled, return _cairo_error (CAIRO_STATUS_NO_MEMORY); _cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL); + + unscaled->have_color_set = FALSE; } unscaled->have_scale = FALSE; @@ -463,6 +505,8 @@ _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled) free (unscaled->filename); unscaled->filename = NULL; + free (unscaled->variations); + CAIRO_MUTEX_FINI (unscaled->mutex); } @@ -475,7 +519,7 @@ _cairo_ft_unscaled_font_keys_equal (const void *key_a, if (unscaled_a->id == unscaled_b->id && unscaled_a->from_face == unscaled_b->from_face) - { + { if (unscaled_a->from_face) return unscaled_a->face == unscaled_b->face; @@ -519,7 +563,7 @@ _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face, } /* Otherwise create it and insert into hash table. */ - unscaled = malloc (sizeof (cairo_ft_unscaled_font_t)); + unscaled = _cairo_malloc (sizeof (cairo_ft_unscaled_font_t)); if (unlikely (unscaled == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto UNWIND_FONT_MAP_LOCK; @@ -596,7 +640,7 @@ static cairo_status_t _cairo_ft_unscaled_font_create_from_face (FT_Face face, cairo_ft_unscaled_font_t **out) { - return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face, out); + return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, face->face_index, face, out); } static cairo_bool_t @@ -700,6 +744,9 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled) unscaled->face = face; + unscaled->have_color = FT_HAS_COLOR (face) != 0; + unscaled->have_color_set = TRUE; + font_map->num_open_faces++; return face; @@ -929,6 +976,11 @@ _compute_xrender_bitmap_size(FT_Bitmap *target, pitch = width * 4; break; + case FT_PIXEL_MODE_BGRA: + /* each pixel is replicated into a 32-bit ARGB value */ + pitch = width * 4; + break; + default: /* unsupported source format */ return -1; } @@ -1086,7 +1138,7 @@ _fill_xrender_bitmap(FT_Bitmap *target, } break; - default: /* FT_PIXEL_MODE_LCD_V */ + case FT_PIXEL_MODE_LCD_V: /* convert vertical RGB into ARGB32 */ if (!bgr) { @@ -1123,6 +1175,15 @@ _fill_xrender_bitmap(FT_Bitmap *target, } } } + break; + + case FT_PIXEL_MODE_BGRA: + for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) + memcpy (dstLine, srcLine, width * 4); + break; + + default: + assert (0); } } @@ -1228,7 +1289,6 @@ _get_bitmap_surface (FT_Bitmap *bitmap, component_alpha = TRUE; } break; -#ifdef FT_LOAD_COLOR case FT_PIXEL_MODE_BGRA: stride = width * 4; if (own_buffer) { @@ -1240,9 +1300,17 @@ _get_bitmap_surface (FT_Bitmap *bitmap, memcpy (data, bitmap->buffer, stride * height); } + + if (!_cairo_is_little_endian ()) + { + /* Byteswap. */ + unsigned int i, count = height * width; + uint32_t *p = (uint32_t *) data; + for (i = 0; i < count; i++) + p[i] = be32_to_cpu (p[i]); + } format = CAIRO_FORMAT_ARGB32; break; -#endif case FT_PIXEL_MODE_GRAY2: case FT_PIXEL_MODE_GRAY4: convert: @@ -1423,6 +1491,7 @@ _render_glyph_outline (FT_Face face, (*surface) = (cairo_image_surface_t *) cairo_image_surface_create_for_data (NULL, format, 0, 0, 0); + pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE); if ((*surface)->base.status) return (*surface)->base.status; } else { @@ -1647,6 +1716,10 @@ _transform_glyph_bitmap (cairo_matrix_t * shape, old_image = (*surface); (*surface) = (cairo_image_surface_t *)image; + + /* Note: we converted subpixel-rendered RGBA images to grayscale, + * so, no need to copy component alpha to new image. */ + cairo_surface_destroy (&old_image->base); cairo_surface_set_device_offset (&(*surface)->base, @@ -1685,6 +1758,7 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret) #ifdef FC_HINT_STYLE int hintstyle; #endif + char *variations; _cairo_font_options_init_default (&ft_options.base); ft_options.load_flags = FT_LOAD_DEFAULT; @@ -1826,6 +1900,13 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret) if (embolden) ft_options.synth_flags |= CAIRO_FT_SYNTHESIZE_BOLD; +#ifndef FC_FONT_VARIATIONS +#define FC_FONT_VARIATIONS "fontvariations" +#endif + if (FcPatternGetString (pattern, FC_FONT_VARIATIONS, 0, (FcChar8 **) &variations) == FcResultMatch) { + ft_options.base.variations = strdup (variations); + } + *ret = ft_options; } #endif @@ -1903,6 +1984,24 @@ _cairo_ft_options_merge (cairo_ft_options_t *options, } } + if (other->base.variations) { + if (options->base.variations) { + char *p; + + /* 'merge' variations by concatenating - later entries win */ + p = malloc (strlen (other->base.variations) + strlen (options->base.variations) + 2); + p[0] = 0; + strcat (p, other->base.variations); + strcat (p, ","); + strcat (p, options->base.variations); + free (options->base.variations); + options->base.variations = p; + } + else { + options->base.variations = strdup (other->base.variations); + } + } + options->load_flags = load_flags | load_target; options->synth_flags = other->synth_flags; } @@ -1928,7 +2027,7 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_font_face, if (unlikely (face == NULL)) /* backend error */ return _cairo_error (CAIRO_STATUS_NO_MEMORY); - scaled_font = malloc (sizeof (cairo_ft_scaled_font_t)); + scaled_font = _cairo_malloc (sizeof (cairo_ft_scaled_font_t)); if (unlikely (scaled_font == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto FAIL; @@ -2205,6 +2304,99 @@ _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font, } } +static void +cairo_ft_apply_variations (FT_Face face, + cairo_ft_scaled_font_t *scaled_font) +{ + FT_MM_Var *ft_mm_var; + FT_Error ret; + unsigned int instance_id = scaled_font->unscaled->id >> 16; + + ret = FT_Get_MM_Var (face, &ft_mm_var); + if (ret == 0) { + FT_Fixed *current_coords; + FT_Fixed *coords; + unsigned int i; + const char *p; + + coords = malloc (sizeof (FT_Fixed) * ft_mm_var->num_axis); + /* FIXME check coords. */ + + if (scaled_font->unscaled->variations) + { + memcpy (coords, scaled_font->unscaled->variations, ft_mm_var->num_axis * sizeof (*coords)); + } + else if (instance_id && instance_id <= ft_mm_var->num_namedstyles) + { + FT_Var_Named_Style *instance = &ft_mm_var->namedstyle[instance_id - 1]; + memcpy (coords, instance->coords, ft_mm_var->num_axis * sizeof (*coords)); + } + else + for (i = 0; i < ft_mm_var->num_axis; i++) + coords[i] = ft_mm_var->axis[i].def; + + p = scaled_font->ft_options.base.variations; + while (p && *p) { + const char *start; + const char *end, *end2; + FT_ULong tag; + double value; + + while (_cairo_isspace (*p)) p++; + + start = p; + end = strchr (p, ','); + if (end && (end - p < 6)) + goto skip; + + tag = FT_MAKE_TAG(p[0], p[1], p[2], p[3]); + + p += 4; + while (_cairo_isspace (*p)) p++; + if (*p == '=') p++; + + if (p - start < 5) + goto skip; + + value = _cairo_strtod (p, (char **) &end2); + + while (end2 && _cairo_isspace (*end2)) end2++; + + if (end2 && (*end2 != ',' && *end2 != '\0')) + goto skip; + + for (i = 0; i < ft_mm_var->num_axis; i++) { + if (ft_mm_var->axis[i].tag == tag) { + coords[i] = (FT_Fixed)(value*65536); + break; + } + } + +skip: + p = end ? end + 1 : NULL; + } + + current_coords = malloc (sizeof (FT_Fixed) * ft_mm_var->num_axis); +#ifdef HAVE_FT_GET_VAR_DESIGN_COORDINATES + ret = FT_Get_Var_Design_Coordinates (face, ft_mm_var->num_axis, current_coords); + if (ret == 0) { + for (i = 0; i < ft_mm_var->num_axis; i++) { + if (coords[i] != current_coords[i]) + break; + } + if (i == ft_mm_var->num_axis) + goto done; + } +#endif + + FT_Set_Var_Design_Coordinates (face, ft_mm_var->num_axis, coords); +done: + free (coords); + free (current_coords); + free (ft_mm_var); + } +} + static cairo_int_status_t _cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph, @@ -2227,6 +2419,8 @@ _cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font, if (unlikely (status)) return status; + cairo_ft_apply_variations (face, scaled_font); + error = FT_Load_Glyph (face, _cairo_scaled_glyph_index(scaled_glyph), load_flags); @@ -2279,8 +2473,10 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && - (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0) + (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) == 0) { load_flags |= FT_LOAD_NO_BITMAP; + } /* * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as @@ -2291,19 +2487,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, vertical_layout = TRUE; } -#ifdef FT_LOAD_COLOR - /* Color-glyph support: - * - * This flags needs plumbing through fontconfig (does it?), and - * maybe we should cache color and grayscale bitmaps separately - * such that users of the font (ie. the surface) can choose which - * version to use based on target content type. - * - * Moreover, none of our backends and compositors currently support - * color glyphs. As such, this is currently disabled. - */ - /* load_flags |= FT_LOAD_COLOR; */ -#endif + load_flags |= FT_LOAD_COLOR; if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { @@ -2416,7 +2600,8 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, &fs_metrics); } - if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { +LOAD: + if (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) { cairo_image_surface_t *surface; if (!scaled_glyph_loaded) { @@ -2444,16 +2629,35 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, { status = _transform_glyph_bitmap (&unscaled->current_shape, &surface); - if (unlikely (status)) - cairo_surface_destroy (&surface->base); - } + if (unlikely (status)) + cairo_surface_destroy (&surface->base); + } } if (unlikely (status)) goto FAIL; - _cairo_scaled_glyph_set_surface (scaled_glyph, - &scaled_font->base, - surface); + if (pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 && + !pixman_image_get_component_alpha (surface->pixman_image)) { + _cairo_scaled_glyph_set_color_surface (scaled_glyph, + &scaled_font->base, + surface); + } else { + _cairo_scaled_glyph_set_surface (scaled_glyph, + &scaled_font->base, + surface); + } + } + + if (((info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) != 0) && + ((scaled_glyph->has_info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)) { + /* + * A kludge -- load again, without color. + * No need to load the metrics again, though + */ + scaled_glyph_loaded = FALSE; + info &= ~CAIRO_SCALED_GLYPH_INFO_METRICS; + load_flags &= ~FT_LOAD_COLOR; + goto LOAD; } if (info & CAIRO_SCALED_GLYPH_INFO_PATH) { @@ -2463,7 +2667,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, * A kludge -- the above code will trash the outline, * so reload it. This will probably never occur though */ - if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { + if ((info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) != 0) { scaled_glyph_loaded = FALSE; load_flags |= FT_LOAD_NO_BITMAP; } @@ -2592,11 +2796,79 @@ _cairo_ft_index_to_ucs4(void *abstract_font, return CAIRO_STATUS_SUCCESS; } -static cairo_bool_t -_cairo_ft_is_synthetic (void *abstract_font) +static cairo_int_status_t +_cairo_ft_is_synthetic (void *abstract_font, + cairo_bool_t *is_synthetic) { + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_ft_scaled_font_t *scaled_font = abstract_font; - return scaled_font->ft_options.synth_flags != 0; + cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; + FT_Face face; + FT_Error error; + + if (scaled_font->ft_options.synth_flags != 0) { + *is_synthetic = TRUE; + return status; + } + + *is_synthetic = FALSE; + face = _cairo_ft_unscaled_font_lock_face (unscaled); + if (!face) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { + FT_MM_Var *mm_var = NULL; + FT_Fixed *coords = NULL; + int num_axis; + + /* If this is an MM or variable font we can't assume the current outlines + * are the same as the font tables */ + *is_synthetic = TRUE; + + error = FT_Get_MM_Var (face, &mm_var); + if (error) { + status = _cairo_error (_ft_to_cairo_error (error)); + goto cleanup; + } + + num_axis = mm_var->num_axis; + coords = _cairo_malloc_ab (num_axis, sizeof(FT_Fixed)); + if (!coords) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto cleanup; + } + +#if FREETYPE_MAJOR > 2 || ( FREETYPE_MAJOR == 2 && FREETYPE_MINOR >= 8) + /* If FT_Get_Var_Blend_Coordinates() is available, we can check if the + * current design coordinates are the default coordinates. In this case + * the current outlines match the font tables. + */ + { + int i; + + FT_Get_Var_Blend_Coordinates (face, num_axis, coords); + *is_synthetic = FALSE; + for (i = 0; i < num_axis; i++) { + if (coords[i]) { + *is_synthetic = TRUE; + break; + } + } + } +#endif + + cleanup: + free (coords); +#if HAVE_FT_DONE_MM_VAR + FT_Done_MM_Var (face->glyph->library, mm_var); +#else + free (mm_var); +#endif + } + + _cairo_ft_unscaled_font_unlock_face (unscaled); + + return status; } static cairo_int_status_t @@ -2738,6 +3010,22 @@ _cairo_ft_load_type1_data (void *abstract_font, return status; } +static cairo_bool_t +_cairo_ft_has_color_glyphs (void *scaled) +{ + cairo_ft_unscaled_font_t *unscaled = ((cairo_ft_scaled_font_t *)scaled)->unscaled; + + if (!unscaled->have_color_set) { + FT_Face face; + face = _cairo_ft_unscaled_font_lock_face (unscaled); + if (unlikely (face == NULL)) + return FALSE; + _cairo_ft_unscaled_font_unlock_face (unscaled); + } + + return unscaled->have_color; +} + static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = { CAIRO_FONT_TYPE_FT, _cairo_ft_scaled_font_fini, @@ -2748,7 +3036,8 @@ static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = { _cairo_ft_index_to_ucs4, _cairo_ft_is_synthetic, _cairo_index_to_glyph_name, - _cairo_ft_load_type1_data + _cairo_ft_load_type1_data, + _cairo_ft_has_color_glyphs }; /* #cairo_ft_font_face_t */ @@ -2879,6 +3168,8 @@ _cairo_ft_font_face_destroy (void *abstract_face) font_face->unscaled = NULL; } + _cairo_ft_options_fini (&font_face->ft_options); + #if CAIRO_HAS_FC_FONT if (font_face->pattern) { FcPatternDestroy (font_face->pattern); @@ -2964,13 +3255,16 @@ _cairo_ft_font_face_create_for_pattern (FcPattern *pattern) { cairo_ft_font_face_t *font_face; - font_face = malloc (sizeof (cairo_ft_font_face_t)); + font_face = _cairo_malloc (sizeof (cairo_ft_font_face_t)); if (unlikely (font_face == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *) &_cairo_font_face_nil; } font_face->unscaled = NULL; + + _get_pattern_ft_options (pattern, &font_face->ft_options); + font_face->next = NULL; font_face->pattern = FcPatternDuplicate (pattern); @@ -3023,7 +3317,7 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, } /* No match found, create a new one */ - font_face = malloc (sizeof (cairo_ft_font_face_t)); + font_face = _cairo_malloc (sizeof (cairo_ft_font_face_t)); if (unlikely (!font_face)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; @@ -3032,7 +3326,7 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, font_face->unscaled = unscaled; _cairo_unscaled_font_reference (&unscaled->base); - font_face->ft_options = *ft_options; + _cairo_ft_options_init_copy (&font_face->ft_options, ft_options); if (unscaled->faces && unscaled->faces->unscaled == NULL) { /* This "zombie" font_face (from _cairo_ft_font_face_destroy) @@ -3279,6 +3573,7 @@ _cairo_ft_resolve_pattern (FcPattern *pattern, _get_pattern_ft_options (resolved, &ft_options); font_face = _cairo_ft_font_face_create (unscaled, &ft_options); + _cairo_ft_options_fini (&ft_options); _cairo_unscaled_font_destroy (&unscaled->base); FREE_RESOLVED: @@ -3353,6 +3648,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern) _get_pattern_ft_options (pattern, &ft_options); font_face = _cairo_ft_font_face_create (unscaled, &ft_options); + _cairo_ft_options_fini (&ft_options); _cairo_unscaled_font_destroy (&unscaled->base); return font_face; @@ -3506,7 +3802,8 @@ cairo_ft_font_face_get_synthesize (cairo_font_face_t *font_face) * cairo_ft_font_face_create_for_ft_face()). * * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType - * backend font and scales it appropriately for the font. You must + * backend font and scales it appropriately for the font and applies OpenType + * font variations if applicable. You must * release the face with cairo_ft_scaled_font_unlock_face() * when you are done using it. Since the #FT_Face object can be * shared between multiple #cairo_scaled_font_t objects, you must not @@ -3559,6 +3856,8 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font) return NULL; } + cairo_ft_apply_variations (face, scaled_font); + /* Note: We deliberately release the unscaled font's mutex here, * so that we are not holding a lock across two separate calls to * cairo function, (which would give the application some diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c index 5b1411472d0..5477ef0d8ac 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c @@ -52,9 +52,96 @@ #include "cairo-error-private.h" #include "cairo-image-surface-private.h" +/* FIXME: Copy of same routine in cairo-gl-msaa-compositor.c */ +static cairo_int_status_t +_draw_int_rect (cairo_gl_context_t *ctx, + cairo_gl_composite_t *setup, + cairo_rectangle_int_t *rect) +{ + cairo_box_t box; + cairo_point_t quad[4]; + + _cairo_box_from_rectangle (&box, rect); + quad[0].x = box.p1.x; + quad[0].y = box.p1.y; + quad[1].x = box.p1.x; + quad[1].y = box.p2.y; + quad[2].x = box.p2.x; + quad[2].y = box.p2.y; + quad[3].x = box.p2.x; + quad[3].y = box.p1.y; + + return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad); +} + +static cairo_int_status_t +_blit_texture_to_renderbuffer (cairo_gl_surface_t *surface) +{ + cairo_gl_context_t *ctx = NULL; + cairo_gl_composite_t setup; + cairo_surface_pattern_t pattern; + cairo_rectangle_int_t extents; + cairo_int_status_t status; + + /* FIXME: This only permits blit when glesv3 is enabled. But note that + glesv2 with the ANGLE extension should also be able to support this feature, + so once the ANGLE support code is in place this check can be relaxed. */ + if (((cairo_gl_context_t *)surface->base.device)->gl_flavor != CAIRO_GL_FLAVOR_ES3) + return CAIRO_INT_STATUS_SUCCESS; + + if (! surface->content_in_texture) + return CAIRO_INT_STATUS_SUCCESS; + + memset (&setup, 0, sizeof (cairo_gl_composite_t)); + + status = _cairo_gl_composite_set_operator (&setup, + CAIRO_OPERATOR_SOURCE, + FALSE); + + if (status) + return status; + + setup.dst = surface; + setup.clip_region = surface->clip_region; + + _cairo_pattern_init_for_surface (&pattern, &surface->base); + status = _cairo_gl_composite_set_source (&setup, &pattern.base, + NULL, NULL, FALSE); + _cairo_pattern_fini (&pattern.base); + + if (unlikely (status)) + goto FAIL; + + _cairo_gl_composite_set_multisample (&setup); + + status = _cairo_gl_composite_begin (&setup, &ctx); + + if (unlikely (status)) + goto FAIL; + + extents.x = extents.y = 0; + extents.width = surface->width; + extents.height = surface->height; + + status = _draw_int_rect (ctx, &setup, &extents); + + if (status == CAIRO_INT_STATUS_SUCCESS) + surface->content_in_texture = FALSE; + +FAIL: + _cairo_gl_composite_fini (&setup); + + if (ctx) { + _cairo_gl_composite_flush (ctx); + status = _cairo_gl_context_release (ctx, status); + } + + return status; +} + cairo_int_status_t _cairo_gl_composite_set_source (cairo_gl_composite_t *setup, - const cairo_pattern_t *pattern, + const cairo_pattern_t *pattern, const cairo_rectangle_int_t *sample, const cairo_rectangle_int_t *extents, cairo_bool_t use_texgen) @@ -68,8 +155,13 @@ void _cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup, const cairo_gl_operand_t *source) { + cairo_int_status_t status; + _cairo_gl_operand_destroy (&setup->src); _cairo_gl_operand_copy (&setup->src, source); + + if (source->type == CAIRO_GL_OPERAND_TEXTURE) + status = _cairo_gl_surface_resolve_multisampling (source->texture.surface); } void @@ -89,7 +181,7 @@ _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup, { _cairo_gl_operand_destroy (&setup->mask); if (pattern == NULL) - return CAIRO_STATUS_SUCCESS; + return CAIRO_STATUS_SUCCESS; return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst, sample, extents, use_texgen); @@ -99,9 +191,13 @@ void _cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup, const cairo_gl_operand_t *mask) { + cairo_int_status_t status; _cairo_gl_operand_destroy (&setup->mask); - if (mask) + if (mask) { _cairo_gl_operand_copy (&setup->mask, mask); + if (mask->type == CAIRO_GL_OPERAND_TEXTURE) + status = _cairo_gl_surface_resolve_multisampling (mask->texture.surface); + } } void @@ -118,7 +214,7 @@ _cairo_gl_composite_set_multisample (cairo_gl_composite_t *setup) void _cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup, - cairo_region_t *clip_region) + cairo_region_t *clip_region) { setup->clip_region = clip_region; } @@ -142,8 +238,8 @@ _cairo_gl_composite_bind_to_shader (cairo_gl_context_t *ctx, static void _cairo_gl_texture_set_filter (cairo_gl_context_t *ctx, - GLuint target, - cairo_filter_t filter) + GLuint target, + cairo_filter_t filter) { switch (filter) { case CAIRO_FILTER_FAST: @@ -165,16 +261,17 @@ _cairo_gl_texture_set_filter (cairo_gl_context_t *ctx, static void _cairo_gl_texture_set_extend (cairo_gl_context_t *ctx, - GLuint target, - cairo_extend_t extend) + GLuint target, + cairo_extend_t extend) { GLint wrap_mode; assert (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base) || - (extend != CAIRO_EXTEND_REPEAT && extend != CAIRO_EXTEND_REFLECT)); + (extend != CAIRO_EXTEND_REPEAT && extend != CAIRO_EXTEND_REFLECT)); switch (extend) { case CAIRO_EXTEND_NONE: - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) wrap_mode = GL_CLAMP_TO_EDGE; else wrap_mode = GL_CLAMP_TO_BORDER; @@ -207,10 +304,10 @@ _cairo_gl_texture_set_extend (cairo_gl_context_t *ctx, static void _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit, - cairo_gl_operand_t *operand, - unsigned int vertex_offset, - cairo_bool_t vertex_size_changed) + cairo_gl_tex_t tex_unit, + cairo_gl_operand_t *operand, + unsigned int vertex_offset, + cairo_bool_t vertex_size_changed) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; cairo_bool_t needs_setup; @@ -219,36 +316,36 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx, * to no shaders (or back) */ needs_setup = vertex_size_changed; needs_setup |= _cairo_gl_operand_needs_setup (&ctx->operands[tex_unit], - operand, - vertex_offset); + operand, + vertex_offset); if (needs_setup) { - _cairo_gl_composite_flush (ctx); - _cairo_gl_context_destroy_operand (ctx, tex_unit); + _cairo_gl_composite_flush (ctx); + _cairo_gl_context_destroy_operand (ctx, tex_unit); } memcpy (&ctx->operands[tex_unit], operand, sizeof (cairo_gl_operand_t)); ctx->operands[tex_unit].vertex_offset = vertex_offset; if (! needs_setup) - return; + return; switch (operand->type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: - break; - /* fall through */ + break; + /* fall through */ case CAIRO_GL_OPERAND_CONSTANT: - break; + break; case CAIRO_GL_OPERAND_TEXTURE: - glActiveTexture (GL_TEXTURE0 + tex_unit); - glBindTexture (ctx->tex_target, operand->texture.tex); - _cairo_gl_texture_set_extend (ctx, ctx->tex_target, - operand->texture.attributes.extend); - _cairo_gl_texture_set_filter (ctx, ctx->tex_target, - operand->texture.attributes.filter); + glActiveTexture (GL_TEXTURE0 + tex_unit); + glBindTexture (ctx->tex_target, operand->texture.tex); + _cairo_gl_texture_set_extend (ctx, ctx->tex_target, + operand->texture.attributes.extend); + _cairo_gl_texture_set_filter (ctx, ctx->tex_target, + operand->texture.attributes.filter); if (! operand->texture.texgen) { dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2, @@ -256,15 +353,15 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx, ctx->vb + vertex_offset); dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); } - break; + break; case CAIRO_GL_OPERAND_LINEAR_GRADIENT: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - glActiveTexture (GL_TEXTURE0 + tex_unit); - glBindTexture (ctx->tex_target, operand->gradient.gradient->tex); - _cairo_gl_texture_set_extend (ctx, ctx->tex_target, operand->gradient.extend); - _cairo_gl_texture_set_filter (ctx, ctx->tex_target, CAIRO_FILTER_BILINEAR); + glActiveTexture (GL_TEXTURE0 + tex_unit); + glBindTexture (ctx->tex_target, operand->gradient.gradient->tex); + _cairo_gl_texture_set_extend (ctx, ctx->tex_target, operand->gradient.extend); + _cairo_gl_texture_set_filter (ctx, ctx->tex_target, CAIRO_FILTER_BILINEAR); if (! operand->gradient.texgen) { dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2, @@ -299,7 +396,7 @@ _cairo_gl_context_setup_spans (cairo_gl_context_t *ctx, void _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit) + cairo_gl_tex_t tex_unit) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; @@ -309,21 +406,21 @@ _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, switch (ctx->operands[tex_unit].type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: - break; - /* fall through */ + break; + /* fall through */ case CAIRO_GL_OPERAND_CONSTANT: - break; + break; case CAIRO_GL_OPERAND_TEXTURE: - dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - break; + dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); + break; case CAIRO_GL_OPERAND_LINEAR_GRADIENT: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - break; + dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); + break; } memset (&ctx->operands[tex_unit], 0, sizeof (cairo_gl_operand_t)); @@ -331,7 +428,7 @@ _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, static void _cairo_gl_set_operator (cairo_gl_context_t *ctx, - cairo_operator_t op, + cairo_operator_t op, cairo_bool_t component_alpha) { struct { @@ -359,7 +456,7 @@ _cairo_gl_set_operator (cairo_gl_context_t *ctx, assert (op < ARRAY_LENGTH (blend_factors)); /* different dst and component_alpha changes cause flushes elsewhere */ if (ctx->current_operator != op) - _cairo_gl_composite_flush (ctx); + _cairo_gl_composite_flush (ctx); ctx->current_operator = op; src_factor = blend_factors[op].src; @@ -384,23 +481,23 @@ _cairo_gl_set_operator (cairo_gl_context_t *ctx, } if (ctx->current_target->base.content == CAIRO_CONTENT_ALPHA) { - glBlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor); + glBlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor); } else if (ctx->current_target->base.content == CAIRO_CONTENT_COLOR) { - glBlendFuncSeparate (src_factor, dst_factor, GL_ONE, GL_ONE); + glBlendFuncSeparate (src_factor, dst_factor, GL_ONE, GL_ONE); } else { - glBlendFunc (src_factor, dst_factor); + glBlendFunc (src_factor, dst_factor); } } static cairo_status_t _cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup) + cairo_gl_composite_t *setup) { cairo_gl_shader_t *pre_shader = NULL; cairo_status_t status; /* For CLEAR, cairo's rendering equation (quoting Owen's description in: - * http://lists.cairographics.org/archives/cairo/2005-August/004992.html) + * https://lists.cairographics.org/archives/cairo/2005-August/004992.html) * is: * mask IN clip ? src OP dest : dest * or more simply: @@ -420,7 +517,7 @@ _cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx, * mask IN clip ? 0 : dest */ if (setup->op == CAIRO_OPERATOR_CLEAR) { - _cairo_gl_solid_operand_init (&setup->src, CAIRO_COLOR_WHITE); + _cairo_gl_solid_operand_init (&setup->src, CAIRO_COLOR_WHITE); setup->op = CAIRO_OPERATOR_DEST_OUT; } @@ -477,17 +574,17 @@ _cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx, if (setup->op == CAIRO_OPERATOR_OVER) { setup->op = CAIRO_OPERATOR_ADD; status = _cairo_gl_get_shader_by_type (ctx, - &setup->src, - &setup->mask, + &setup->src, + &setup->mask, setup->spans, - CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA, - &pre_shader); - if (unlikely (status)) - return status; + CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA, + &pre_shader); + if (unlikely (status)) + return status; } if (ctx->pre_shader != pre_shader) - _cairo_gl_composite_flush (ctx); + _cairo_gl_composite_flush (ctx); ctx->pre_shader = pre_shader; return CAIRO_STATUS_SUCCESS; @@ -661,7 +758,7 @@ _cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup, if (setup->clip) return _cairo_gl_composite_setup_painted_clipping (setup, ctx, - vertex_size); + vertex_size); disable_all_clipping: _disable_stencil_buffer (); glDisable (GL_SCISSOR_TEST); @@ -701,13 +798,13 @@ _cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup, component_alpha ? CAIRO_GL_SHADER_IN_CA_SOURCE : CAIRO_GL_SHADER_IN_NORMAL, - &shader); + &shader); if (unlikely (status)) { ctx->pre_shader = NULL; return status; } if (ctx->current_shader != shader) - _cairo_gl_composite_flush (ctx); + _cairo_gl_composite_flush (ctx); status = CAIRO_STATUS_SUCCESS; @@ -769,7 +866,7 @@ _cairo_gl_composite_begin (cairo_gl_composite_t *setup, FAIL: if (unlikely (status)) - status = _cairo_gl_context_release (ctx, status); + status = _cairo_gl_context_release (ctx, status); return status; } @@ -800,17 +897,17 @@ _cairo_gl_composite_draw_triangles (cairo_gl_context_t *ctx, unsigned int count) { if (! ctx->pre_shader) { - glDrawArrays (GL_TRIANGLES, 0, count); + glDrawArrays (GL_TRIANGLES, 0, count); } else { - cairo_gl_shader_t *prev_shader = ctx->current_shader; + cairo_gl_shader_t *prev_shader = ctx->current_shader; - _cairo_gl_set_shader (ctx, ctx->pre_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE); - glDrawArrays (GL_TRIANGLES, 0, count); + _cairo_gl_set_shader (ctx, ctx->pre_shader); + _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE); + glDrawArrays (GL_TRIANGLES, 0, count); - _cairo_gl_set_shader (ctx, prev_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE); - glDrawArrays (GL_TRIANGLES, 0, count); + _cairo_gl_set_shader (ctx, prev_shader); + _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE); + glDrawArrays (GL_TRIANGLES, 0, count); } } @@ -849,7 +946,7 @@ _cairo_gl_composite_flush (cairo_gl_context_t *ctx) int i; if (_cairo_gl_context_is_flushed (ctx)) - return; + return; count = ctx->vb_offset / ctx->vertex_size; _cairo_gl_composite_unmap_vertex_buffer (ctx); @@ -931,8 +1028,8 @@ _cairo_gl_composite_emit_point (cairo_gl_context_t *ctx, static void _cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2) + GLfloat x1, GLfloat y1, + GLfloat x2, GLfloat y2) { _cairo_gl_composite_prepare_buffer (ctx, 6, CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); @@ -962,9 +1059,9 @@ _cairo_gl_context_emit_rect (cairo_gl_context_t *ctx, static void _cairo_gl_composite_emit_span (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - uint8_t alpha) + GLfloat x1, GLfloat y1, + GLfloat x2, GLfloat y2, + uint8_t alpha) { _cairo_gl_composite_prepare_buffer (ctx, 6, CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); @@ -1038,7 +1135,7 @@ _cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx) switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: case CAIRO_GL_OPERAND_CONSTANT: break; @@ -1079,10 +1176,10 @@ _cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx, static void _cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - GLfloat glyph_x1, GLfloat glyph_y1, - GLfloat glyph_x2, GLfloat glyph_y2) + GLfloat x1, GLfloat y1, + GLfloat x2, GLfloat y2, + GLfloat glyph_x1, GLfloat glyph_y1, + GLfloat glyph_x2, GLfloat glyph_y2) { _cairo_gl_composite_prepare_buffer (ctx, 6, CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); @@ -1130,7 +1227,7 @@ _cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx) switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: case CAIRO_GL_OPERAND_CONSTANT: return _cairo_gl_composite_emit_solid_glyph; @@ -1157,13 +1254,13 @@ _cairo_gl_composite_set_operator (cairo_gl_composite_t *setup, cairo_bool_t assume_component_alpha) { if (assume_component_alpha) { - if (op != CAIRO_OPERATOR_CLEAR && - op != CAIRO_OPERATOR_OVER && - op != CAIRO_OPERATOR_ADD) - return UNSUPPORTED ("unsupported component alpha operator"); + if (op != CAIRO_OPERATOR_CLEAR && + op != CAIRO_OPERATOR_OVER && + op != CAIRO_OPERATOR_ADD) + return UNSUPPORTED ("unsupported component alpha operator"); } else { - if (! _cairo_gl_operator_is_supported (op)) - return UNSUPPORTED ("unsupported operator"); + if (! _cairo_gl_operator_is_supported (op)) + return UNSUPPORTED ("unsupported operator"); } setup->op = op; @@ -1172,12 +1269,14 @@ _cairo_gl_composite_set_operator (cairo_gl_composite_t *setup, cairo_status_t _cairo_gl_composite_init (cairo_gl_composite_t *setup, - cairo_operator_t op, - cairo_gl_surface_t *dst, - cairo_bool_t assume_component_alpha) + cairo_operator_t op, + cairo_gl_surface_t *dst, + cairo_bool_t assume_component_alpha) { cairo_status_t status; + status = _blit_texture_to_renderbuffer (dst); + memset (setup, 0, sizeof (cairo_gl_composite_t)); status = _cairo_gl_composite_set_operator (setup, op, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-device.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-device.c index 7235d9ae123..258b4c50dbc 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-device.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-device.c @@ -71,7 +71,7 @@ _gl_flush (void *device) status = _cairo_gl_context_acquire (device, &ctx); if (unlikely (status)) - return status; + return status; _cairo_gl_composite_flush (ctx); @@ -79,8 +79,8 @@ _gl_flush (void *device) _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK); if (ctx->clip_region) { - cairo_region_destroy (ctx->clip_region); - ctx->clip_region = NULL; + cairo_region_destroy (ctx->clip_region); + ctx->clip_region = NULL; } ctx->current_target = NULL; @@ -171,7 +171,8 @@ test_can_read_bgra (cairo_gl_flavor_t gl_flavor) if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) return TRUE; - assert (gl_flavor == CAIRO_GL_FLAVOR_ES); + assert (gl_flavor == CAIRO_GL_FLAVOR_ES3 || + gl_flavor == CAIRO_GL_FLAVOR_ES2); /* For OpenGL ES we have to look for the specific extension and BGRA only * matches cairo's integer packed bytes on little-endian machines. */ @@ -190,7 +191,8 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) int n; cairo_bool_t is_desktop = gl_flavor == CAIRO_GL_FLAVOR_DESKTOP; - cairo_bool_t is_gles = gl_flavor == CAIRO_GL_FLAVOR_ES; + cairo_bool_t is_gles = (gl_flavor == CAIRO_GL_FLAVOR_ES3 || + gl_flavor == CAIRO_GL_FLAVOR_ES2); _cairo_device_init (&ctx->base, &_cairo_gl_device_backend); @@ -263,43 +265,49 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) } #endif -#if CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_EXT) +#if CAIRO_HAS_GLESV3_SURFACE + if (is_gles && ctx->has_packed_depth_stencil) { + glGetIntegerv(GL_MAX_SAMPLES, &ctx->num_samples); + } + +#elif CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_EXT) if (is_gles && ctx->has_packed_depth_stencil && _cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) { glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples); } -#endif -#if CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_IMG) if (is_gles && ctx->has_packed_depth_stencil && _cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture")) { glGetIntegerv(GL_MAX_SAMPLES_IMG, &ctx->num_samples); } #endif - ctx->supports_msaa = ctx->num_samples > 1; + /* we always use renderbuffer for rendering in glesv3 */ + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) + ctx->supports_msaa = TRUE; + else + ctx->supports_msaa = ctx->num_samples > 1; if (ctx->num_samples > MAX_MSAA_SAMPLES) ctx->num_samples = MAX_MSAA_SAMPLES; - ctx->current_operator = -1; ctx->gl_flavor = gl_flavor; status = _cairo_gl_context_init_shaders (ctx); if (unlikely (status)) - return status; + return status; status = _cairo_cache_init (&ctx->gradients, - _cairo_gl_gradient_equal, - NULL, - (cairo_destroy_func_t) _cairo_gl_gradient_destroy, - CAIRO_GL_GRADIENT_CACHE_SIZE); + _cairo_gl_gradient_equal, + NULL, + (cairo_destroy_func_t) _cairo_gl_gradient_destroy, + CAIRO_GL_GRADIENT_CACHE_SIZE); if (unlikely (status)) - return status; + return status; ctx->vbo_size = _cairo_gl_get_vbo_size(); - ctx->vb = malloc (ctx->vbo_size); + ctx->vb = _cairo_malloc (ctx->vbo_size); if (unlikely (ctx->vb == NULL)) { _cairo_cache_fini (&ctx->gradients); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -326,16 +334,16 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) void _cairo_gl_context_activate (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit) + cairo_gl_tex_t tex_unit) { if (ctx->max_textures <= (GLint) tex_unit) { - if (tex_unit < 2) { - _cairo_gl_composite_flush (ctx); - _cairo_gl_context_destroy_operand (ctx, ctx->max_textures - 1); - } - glActiveTexture (ctx->max_textures - 1); + if (tex_unit < 2) { + _cairo_gl_composite_flush (ctx); + _cairo_gl_context_destroy_operand (ctx, ctx->max_textures - 1); + } + glActiveTexture (ctx->max_textures - 1); } else { - glActiveTexture (GL_TEXTURE0 + tex_unit); + glActiveTexture (GL_TEXTURE0 + tex_unit); } } @@ -349,13 +357,15 @@ _get_depth_stencil_format (cairo_gl_context_t *ctx) return GL_DEPTH_STENCIL; #endif -#if CAIRO_HAS_GLESV2_SURFACE +#if CAIRO_HAS_GLESV2_SURFACE && !CAIRO_HAS_GLESV3_SURFACE if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) return GL_DEPTH24_STENCIL8_OES; #endif #if CAIRO_HAS_GL_SURFACE return GL_DEPTH_STENCIL; +#elif CAIRO_HAS_GLESV3_SURFACE + return GL_DEPTH24_STENCIL8; #elif CAIRO_HAS_GLESV2_SURFACE return GL_DEPTH24_STENCIL8_OES; #endif @@ -381,15 +391,15 @@ _cairo_gl_ensure_msaa_gles_framebuffer (cairo_gl_context_t *ctx, } #endif -static void +void _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) + cairo_gl_surface_t *surface) { GLenum status; cairo_gl_dispatch_t *dispatch = &ctx->dispatch; if (likely (surface->fb)) - return; + return; /* Create a framebuffer object wrapping the texture so that we can render * to it. @@ -402,7 +412,7 @@ _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx, does not require an explicit multisample resolution. */ #if CAIRO_HAS_GLESV2_SURFACE if (surface->supports_msaa && _cairo_gl_msaa_compositor_enabled () && - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) { + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { _cairo_gl_ensure_msaa_gles_framebuffer (ctx, surface); } else #endif @@ -436,13 +446,14 @@ _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx, str, status); } } -#if CAIRO_HAS_GL_SURFACE +#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE static void _cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface) { assert (surface->supports_msaa); - assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP); + assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3); if (surface->msaa_fb) return; @@ -460,7 +471,11 @@ _cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx, this information. */ ctx->dispatch.RenderbufferStorageMultisample (GL_RENDERBUFFER, ctx->num_samples, +#if CAIRO_HAS_GLESV3_SURFACE + GL_RGBA8, +#else GL_RGBA, +#endif surface->width, surface->height); ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER, @@ -472,6 +487,11 @@ _cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx, glDisable (GL_SCISSOR_TEST); glClearColor (0, 0, 0, 0); glClear (GL_COLOR_BUFFER_BIT); + + /* for glesv3 with multisample renderbuffer, we always render to + this renderbuffer */ + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) + surface->msaa_active = TRUE; } #endif @@ -484,14 +504,15 @@ _cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx, return TRUE; _cairo_gl_ensure_framebuffer (ctx, surface); -#if CAIRO_HAS_GL_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) +#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) _cairo_gl_ensure_multisampling (ctx, surface); #endif dispatch->GenRenderbuffers (1, &surface->msaa_depth_stencil); dispatch->BindRenderbuffer (GL_RENDERBUFFER, - surface->msaa_depth_stencil); + surface->msaa_depth_stencil); dispatch->RenderbufferStorageMultisample (GL_RENDERBUFFER, ctx->num_samples, @@ -499,8 +520,9 @@ _cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx, surface->width, surface->height); -#if CAIRO_HAS_GL_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) { +#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) { dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, @@ -509,7 +531,7 @@ _cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx, #endif #if CAIRO_HAS_GLESV2_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) { + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, @@ -615,7 +637,7 @@ _gl_identity_ortho (GLfloat *m, #undef M } -#if CAIRO_HAS_GL_SURFACE +#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE static void bind_multisample_framebuffer (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface) @@ -624,14 +646,19 @@ bind_multisample_framebuffer (cairo_gl_context_t *ctx, cairo_bool_t scissor_test_enabled; assert (surface->supports_msaa); - assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP); + assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3); _cairo_gl_ensure_framebuffer (ctx, surface); _cairo_gl_ensure_multisampling (ctx, surface); if (surface->msaa_active) { +#if CAIRO_HAS_GL_SURFACE glEnable (GL_MULTISAMPLE); +#endif ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb); + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) + surface->content_in_texture = FALSE; return; } @@ -642,7 +669,9 @@ bind_multisample_framebuffer (cairo_gl_context_t *ctx, glDisable (GL_STENCIL_TEST); glDisable (GL_SCISSOR_TEST); +#if CAIRO_HAS_GL_SURFACE glEnable (GL_MULTISAMPLE); +#endif /* The last time we drew to the surface, we were not using multisampling, so we need to blit from the non-multisampling framebuffer into the @@ -651,17 +680,24 @@ bind_multisample_framebuffer (cairo_gl_context_t *ctx, ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->fb); ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height, 0, 0, surface->width, surface->height, - GL_COLOR_BUFFER_BIT, GL_NEAREST); + GL_COLOR_BUFFER_BIT +#if CAIRO_HAS_GL_SURFACE + | GL_STENCIL_BUFFER_BIT +#endif + , + GL_NEAREST); ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb); if (stencil_test_enabled) glEnable (GL_STENCIL_TEST); if (scissor_test_enabled) glEnable (GL_SCISSOR_TEST); + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) + surface->content_in_texture = FALSE; } #endif -#if CAIRO_HAS_GL_SURFACE +#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE static void bind_singlesample_framebuffer (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface) @@ -669,11 +705,15 @@ bind_singlesample_framebuffer (cairo_gl_context_t *ctx, cairo_bool_t stencil_test_enabled; cairo_bool_t scissor_test_enabled; - assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP); + assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3); _cairo_gl_ensure_framebuffer (ctx, surface); if (! surface->msaa_active) { +#if CAIRO_HAS_GL_SURFACE glDisable (GL_MULTISAMPLE); +#endif + ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); return; } @@ -685,7 +725,9 @@ bind_singlesample_framebuffer (cairo_gl_context_t *ctx, glDisable (GL_STENCIL_TEST); glDisable (GL_SCISSOR_TEST); +#if CAIRO_HAS_GL_SURFACE glDisable (GL_MULTISAMPLE); +#endif /* The last time we drew to the surface, we were using multisampling, so we need to blit from the multisampling framebuffer into the @@ -712,13 +754,13 @@ _cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx, if (_cairo_gl_surface_is_texture (surface)) { /* OpenGL ES surfaces only have either a multisample framebuffer or a * singlesample framebuffer, so we cannot switch back and forth. */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) { + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { _cairo_gl_ensure_framebuffer (ctx, surface); ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); return; } -#if CAIRO_HAS_GL_SURFACE +#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE if (multisampling) bind_multisample_framebuffer (ctx, surface); else @@ -737,23 +779,28 @@ _cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx, #endif } - surface->msaa_active = multisampling; + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) + surface->msaa_active = multisampling; } void _cairo_gl_context_set_destination (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface, - cairo_bool_t multisampling) + cairo_gl_surface_t *surface, + cairo_bool_t multisampling) { cairo_bool_t changing_surface, changing_sampling; /* The decision whether or not to use multisampling happens when * we create an OpenGL ES surface, so we can never switch modes. */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) multisampling = surface->msaa_active; + /* For GLESV3, we always use renderbuffer for drawing */ + else if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) + multisampling = TRUE; changing_surface = ctx->current_target != surface || surface->needs_update; - changing_sampling = surface->msaa_active != multisampling; + changing_sampling = (surface->msaa_active != multisampling || + surface->content_in_texture); if (! changing_surface && ! changing_sampling) return; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-dispatch.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-dispatch.c index 76c3115ba37..a49199dbb0a 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-dispatch.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-dispatch.c @@ -124,7 +124,11 @@ _cairo_gl_dispatch_init_buffers (cairo_gl_dispatch_t *dispatch, else return CAIRO_STATUS_DEVICE_ERROR; } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES && + else if (gl_flavor == CAIRO_GL_FLAVOR_ES3) + { + dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; + } + else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 && gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) { dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; @@ -156,7 +160,11 @@ _cairo_gl_dispatch_init_shaders (cairo_gl_dispatch_t *dispatch, else return CAIRO_STATUS_DEVICE_ERROR; } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES && + else if (gl_flavor == CAIRO_GL_FLAVOR_ES3) + { + dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; + } + else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 && gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) { dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; @@ -189,7 +197,11 @@ _cairo_gl_dispatch_init_fbo (cairo_gl_dispatch_t *dispatch, else return CAIRO_STATUS_DEVICE_ERROR; } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES && + else if (gl_flavor == CAIRO_GL_FLAVOR_ES3) + { + dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; + } + else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 && gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) { dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; @@ -214,7 +226,7 @@ _cairo_gl_dispatch_init_multisampling (cairo_gl_dispatch_t *dispatch, /* For the multisampling table, there are two GLES versions of the * extension, so we put one in the EXT slot and one in the real ES slot.*/ cairo_gl_dispatch_name_t dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - if (gl_flavor == CAIRO_GL_FLAVOR_ES) { + if (gl_flavor == CAIRO_GL_FLAVOR_ES2) { if (_cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT; else if (_cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture")) diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-glyphs.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-glyphs.c index 8a1a548d939..5923af44147 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-glyphs.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-glyphs.c @@ -120,10 +120,10 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx, /* search for an unlocked slot */ if (status == CAIRO_INT_STATUS_UNSUPPORTED) { status = _cairo_rtree_evict_random (&cache->rtree, - width, height, &node); + width, height, &node); if (status == CAIRO_INT_STATUS_SUCCESS) { status = _cairo_rtree_node_insert (&cache->rtree, - node, width, height, &node); + node, width, height, &node); } } if (status) @@ -132,9 +132,9 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx, /* XXX: Make sure we use the mask texture. This should work automagically somehow */ glActiveTexture (GL_TEXTURE1); status = _cairo_gl_surface_draw_image (cache->surface, glyph_surface, - 0, 0, - glyph_surface->width, glyph_surface->height, - node->x, node->y, FALSE); + 0, 0, + glyph_surface->width, glyph_surface->height, + node->x, node->y, FALSE); if (unlikely (status)) return status; @@ -174,7 +174,7 @@ _cairo_gl_glyph_cache_lock (cairo_gl_glyph_cache_t *cache, static cairo_status_t cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx, cairo_format_t format, - cairo_gl_glyph_cache_t **cache_out) + cairo_gl_glyph_cache_t **cache_out) { cairo_gl_glyph_cache_t *cache; cairo_content_t content; @@ -185,12 +185,12 @@ cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx, case CAIRO_FORMAT_ARGB32: case CAIRO_FORMAT_RGB24: cache = &ctx->glyph_cache[0]; - content = CAIRO_CONTENT_COLOR_ALPHA; + content = CAIRO_CONTENT_COLOR_ALPHA; break; case CAIRO_FORMAT_A8: case CAIRO_FORMAT_A1: cache = &ctx->glyph_cache[1]; - content = CAIRO_CONTENT_ALPHA; + content = CAIRO_CONTENT_ALPHA; break; default: case CAIRO_FORMAT_INVALID: @@ -202,9 +202,9 @@ cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx, cairo_surface_t *surface; surface = _cairo_gl_surface_create_scratch_for_caching (ctx, - content, - GLYPH_CACHE_WIDTH, - GLYPH_CACHE_HEIGHT); + content, + GLYPH_CACHE_WIDTH, + GLYPH_CACHE_HEIGHT); if (unlikely (surface->status)) return surface->status; @@ -281,9 +281,9 @@ render_glyphs (cairo_gl_surface_t *dst, if (scaled_glyph->surface->format != last_format) { status = cairo_gl_context_get_glyph_cache (ctx, scaled_glyph->surface->format, - &cache); - if (unlikely (status)) - goto FINISH; + &cache); + if (unlikely (status)) + goto FINISH; last_format = scaled_glyph->surface->format; @@ -291,8 +291,8 @@ render_glyphs (cairo_gl_surface_t *dst, *has_component_alpha |= cache->surface->operand.texture.attributes.has_component_alpha; /* XXX Shoot me. */ - status = _cairo_gl_composite_begin (&setup, &ctx); - status = _cairo_gl_context_release (ctx, status); + status = _cairo_gl_composite_begin (&setup, &ctx); + status = _cairo_gl_context_release (ctx, status); if (unlikely (status)) goto FINISH; @@ -363,11 +363,11 @@ render_glyphs_via_mask (cairo_gl_surface_t *dst, /* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */ mask = cairo_gl_surface_create (dst->base.device, - CAIRO_CONTENT_COLOR_ALPHA, - info->extents.width, - info->extents.height); + CAIRO_CONTENT_COLOR_ALPHA, + info->extents.width, + info->extents.height); if (unlikely (mask->status)) - return mask->status; + return mask->status; status = render_glyphs ((cairo_gl_surface_t *) mask, info->extents.x, info->extents.y, @@ -385,11 +385,11 @@ render_glyphs_via_mask (cairo_gl_surface_t *dst, mask_pattern.base.extend = CAIRO_EXTEND_NONE; cairo_matrix_init_translate (&mask_pattern.base.matrix, - dst_x-info->extents.x, dst_y-info->extents.y); + dst_x-info->extents.x, dst_y-info->extents.y); _cairo_pattern_init_for_surface (&source_pattern, source); cairo_matrix_init_translate (&source_pattern.base.matrix, - dst_x-info->extents.x, dst_y-info->extents.y); + dst_x-info->extents.x, dst_y-info->extents.y); clip = _cairo_clip_copy (clip); clip_extents.x = info->extents.x - dst_x; @@ -399,7 +399,7 @@ render_glyphs_via_mask (cairo_gl_surface_t *dst, clip = _cairo_clip_intersect_rectangle (clip, &clip_extents); status = _cairo_surface_mask (&dst->base, op, - &source_pattern.base, + &source_pattern.base, &mask_pattern.base, clip); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-gradient-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-gl-gradient-private.h index 77f9bbdc5f5..0d9f41f54b4 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-gradient-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-gradient-private.h @@ -51,12 +51,15 @@ #include "cairo-gl.h" -#if CAIRO_HAS_GL_SURFACE -#include -#include +#if CAIRO_HAS_GLESV3_SURFACE +#include +#include #elif CAIRO_HAS_GLESV2_SURFACE #include #include +#elif CAIRO_HAS_GL_SURFACE +#include +#include #endif #define CAIRO_GL_GRADIENT_CACHE_SIZE 4096 diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-gradient.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-gradient.c index ac3292101ec..6107bea1e08 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-gradient.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-gradient.c @@ -47,7 +47,7 @@ static int _cairo_gl_gradient_sample_width (unsigned int n_stops, - const cairo_gradient_stop_t *stops) + const cairo_gradient_stop_t *stops) { unsigned int n; int width; @@ -106,10 +106,10 @@ static uint32_t color_stop_to_pixel(const cairo_gradient_stop_t *stop) static cairo_status_t _cairo_gl_gradient_render (const cairo_gl_context_t *ctx, - unsigned int n_stops, - const cairo_gradient_stop_t *stops, - void *bytes, - int width) + unsigned int n_stops, + const cairo_gradient_stop_t *stops, + void *bytes, + int width) { pixman_image_t *gradient, *image; pixman_gradient_stop_t pixman_stops_stack[32]; @@ -169,11 +169,11 @@ _cairo_gl_gradient_render (const cairo_gl_context_t *ctx, } pixman_image_composite32 (PIXMAN_OP_SRC, - gradient, NULL, image, - 0, 0, - 0, 0, - 0, 0, - width, 1); + gradient, NULL, image, + 0, 0, + 0, 0, + 0, 0, + width, 1); pixman_image_unref (gradient); pixman_image_unref (image); @@ -190,18 +190,18 @@ _cairo_gl_gradient_render (const cairo_gl_context_t *ctx, static unsigned long _cairo_gl_gradient_hash (unsigned int n_stops, - const cairo_gradient_stop_t *stops) + const cairo_gradient_stop_t *stops) { return _cairo_hash_bytes (n_stops, - stops, - sizeof (cairo_gradient_stop_t) * n_stops); + stops, + sizeof (cairo_gradient_stop_t) * n_stops); } static cairo_gl_gradient_t * _cairo_gl_gradient_lookup (cairo_gl_context_t *ctx, - unsigned long hash, - unsigned int n_stops, - const cairo_gradient_stop_t *stops) + unsigned long hash, + unsigned int n_stops, + const cairo_gradient_stop_t *stops) { cairo_gl_gradient_t lookup; @@ -219,16 +219,16 @@ _cairo_gl_gradient_equal (const void *key_a, const void *key_b) const cairo_gl_gradient_t *b = key_b; if (a->n_stops != b->n_stops) - return FALSE; + return FALSE; return memcmp (a->stops, b->stops, a->n_stops * sizeof (cairo_gradient_stop_t)) == 0; } cairo_int_status_t _cairo_gl_gradient_create (cairo_gl_context_t *ctx, - unsigned int n_stops, - const cairo_gradient_stop_t *stops, - cairo_gl_gradient_t **gradient_out) + unsigned int n_stops, + const cairo_gradient_stop_t *stops, + cairo_gl_gradient_t **gradient_out) { unsigned long hash; cairo_gl_gradient_t *gradient; @@ -248,7 +248,7 @@ _cairo_gl_gradient_create (cairo_gl_context_t *ctx, return CAIRO_STATUS_SUCCESS; } - gradient = malloc (sizeof (cairo_gl_gradient_t) + sizeof (cairo_gradient_stop_t) * (n_stops - 1)); + gradient = _cairo_malloc (sizeof (cairo_gl_gradient_t) + sizeof (cairo_gradient_stop_t) * (n_stops - 1)); if (gradient == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -282,7 +282,8 @@ _cairo_gl_gradient_create (cairo_gl_context_t *ctx, * In OpenGL ES 2.0 no format conversion is allowed i.e. 'internalFormat' * must match 'format' in glTexImage2D. */ - if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES) + if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 || + _cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) internal_format = GL_BGRA; else internal_format = GL_RGBA; @@ -330,8 +331,8 @@ _cairo_gl_gradient_destroy (cairo_gl_gradient_t *gradient) if (_cairo_gl_context_acquire (gradient->device, &ctx) == CAIRO_STATUS_SUCCESS) { /* The gradient my still be active in the last operation, so flush */ _cairo_gl_composite_flush (ctx); - glDeleteTextures (1, &gradient->tex); - ignore = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); + glDeleteTextures (1, &gradient->tex); + ignore = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); } free (gradient); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-info.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-info.c index acefbb91059..26b7b45511d 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-info.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-info.c @@ -65,8 +65,10 @@ _cairo_gl_get_flavor (void) if (version == NULL) flavor = CAIRO_GL_FLAVOR_NONE; - else if (strstr (version, "OpenGL ES") != NULL) - flavor = CAIRO_GL_FLAVOR_ES; + else if (strstr (version, "OpenGL ES 3") != NULL) + flavor = CAIRO_GL_FLAVOR_ES3; + else if (strstr (version, "OpenGL ES 2") != NULL) + flavor = CAIRO_GL_FLAVOR_ES2; else flavor = CAIRO_GL_FLAVOR_DESKTOP; @@ -80,7 +82,7 @@ _cairo_gl_get_vbo_size (void) const char *env = getenv ("CAIRO_GL_VBO_SIZE"); if (env == NULL) { - vbo_size = CAIRO_GL_VBO_SIZE_DEFAULT; + vbo_size = CAIRO_GL_VBO_SIZE_DEFAULT; } else { errno = 0; vbo_size = strtol (env, NULL, 10); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-msaa-compositor.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-msaa-compositor.c index 83e8eb2d160..7a83dd21942 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-msaa-compositor.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-msaa-compositor.c @@ -224,8 +224,8 @@ _should_use_unbounded_surface (cairo_composite_rectangles_t *composite) /* This isn't just an optimization. It also detects when painting is used to paint back the unbounded surface, preventing infinite recursion. */ return ! (source->x <= 0 && source->y <= 0 && - source->height + source->y >= dst->height && - source->width + source->x >= dst->width); + source->height + source->y >= dst->height && + source->width + source->x >= dst->width); } static cairo_surface_t* @@ -237,10 +237,10 @@ _prepare_unbounded_surface (cairo_gl_surface_t *dst) dst->width, dst->height); if (surface == NULL) - return NULL; + return NULL; if (unlikely (surface->status)) { - cairo_surface_destroy (surface); - return NULL; + cairo_surface_destroy (surface); + return NULL; } return surface; } @@ -273,6 +273,8 @@ static cairo_bool_t can_use_msaa_compositor (cairo_gl_surface_t *surface, cairo_antialias_t antialias) { + cairo_gl_flavor_t gl_flavor = ((cairo_gl_context_t *) surface->base.device)->gl_flavor; + query_surface_capabilities (surface); if (! surface->supports_stencil) return FALSE; @@ -280,8 +282,10 @@ can_use_msaa_compositor (cairo_gl_surface_t *surface, /* Multisampling OpenGL ES surfaces only maintain one multisampling framebuffer and thus must use the spans compositor to do non-antialiased rendering. */ - if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES + if ((gl_flavor == CAIRO_GL_FLAVOR_ES3 || + gl_flavor == CAIRO_GL_FLAVOR_ES2) && surface->supports_msaa + && surface->num_samples > 1 && antialias == CAIRO_ANTIALIAS_NONE) return FALSE; @@ -357,13 +361,13 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos else status = _draw_traps (ctx, &setup, &traps); if (unlikely (status)) - goto finish; + goto finish; /* Now draw the second pass. */ status = _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD, FALSE /* assume_component_alpha */); if (unlikely (status)) - goto finish; + goto finish; status = _cairo_gl_composite_set_source (&setup, &composite->source_pattern.base, &composite->source_sample_area, @@ -372,12 +376,15 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos if (unlikely (status)) goto finish; status = _cairo_gl_composite_set_mask (&setup, - &composite->mask_pattern.base, + &composite->mask_pattern.base, &composite->source_sample_area, &composite->bounded, FALSE); if (unlikely (status)) goto finish; + + _cairo_gl_context_set_destination (ctx, dst, setup.multisample); + status = _cairo_gl_set_operands_and_operator (&setup, ctx); if (unlikely (status)) goto finish; @@ -546,9 +553,9 @@ _stroke_shaper_add_quad (void *closure, } static cairo_int_status_t -_prevent_overlapping_strokes (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_composite_rectangles_t *composite, +_prevent_overlapping_strokes (cairo_gl_context_t *ctx, + cairo_gl_composite_t *setup, + cairo_composite_rectangles_t *composite, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm) @@ -582,6 +589,7 @@ _prevent_overlapping_strokes (cairo_gl_context_t *ctx, scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST); if (! scissor_was_enabled) { _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, + FALSE, /* is_vector */ &stroke_extents); _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents); } @@ -633,6 +641,7 @@ query_surface_capabilities (cairo_gl_surface_t *surface) glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); surface->supports_stencil = stencil_bits > 0; surface->supports_msaa = samples > 1; + surface->num_samples = samples; status = _cairo_gl_context_release (ctx, status); } @@ -823,7 +832,7 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor, else status = _draw_traps (ctx, &setup, &traps); if (unlikely (status)) - goto cleanup_setup; + goto cleanup_setup; cleanup_setup: _cairo_gl_composite_fini (&setup); @@ -935,10 +944,13 @@ _cairo_gl_msaa_compositor_init (cairo_compositor_t *compositor, const cairo_compositor_t * _cairo_gl_msaa_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_compositor_t compositor; - if (compositor.delegate == NULL) + if (_cairo_atomic_init_once_enter(&once)) { _cairo_gl_msaa_compositor_init (&compositor, _cairo_gl_span_compositor_get ()); + _cairo_atomic_init_once_leave(&once); + } return &compositor; } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-operand.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-operand.c index 1d1465a0be9..a754bde2f31 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-operand.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-operand.c @@ -55,7 +55,7 @@ static cairo_int_status_t _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst, const cairo_gradient_pattern_t *pattern, - cairo_gl_gradient_t **gradient) + cairo_gl_gradient_t **gradient) { cairo_gl_context_t *ctx; cairo_status_t status; @@ -130,7 +130,7 @@ _cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand, status = _cairo_gl_surface_resolve_multisampling (surface); if (unlikely (status)) - return status; + return status; attributes = &operand->texture.attributes; @@ -336,7 +336,7 @@ fail: void _cairo_gl_solid_operand_init (cairo_gl_operand_t *operand, - const cairo_color_t *color) + const cairo_color_t *color) { operand->type = CAIRO_GL_OPERAND_CONSTANT; operand->constant.color[0] = color->red * color->alpha; @@ -373,7 +373,7 @@ _cairo_gl_operand_translate (cairo_gl_operand_t *operand, static cairo_status_t _cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *pattern, + const cairo_pattern_t *pattern, cairo_gl_surface_t *dst, cairo_bool_t use_texgen) { @@ -482,9 +482,9 @@ _cairo_gl_operand_copy (cairo_gl_operand_t *dst, break; default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: - break; + break; } } @@ -505,9 +505,9 @@ _cairo_gl_operand_destroy (cairo_gl_operand_t *operand) break; default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: - break; + break; } operand->type = CAIRO_GL_OPERAND_NONE; @@ -515,8 +515,8 @@ _cairo_gl_operand_destroy (cairo_gl_operand_t *operand) cairo_int_status_t _cairo_gl_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *pattern, - cairo_gl_surface_t *dst, + const cairo_pattern_t *pattern, + cairo_gl_surface_t *dst, const cairo_rectangle_int_t *sample, const cairo_rectangle_int_t *extents, cairo_bool_t use_texgen) @@ -614,25 +614,25 @@ _cairo_gl_operand_get_extend (cairo_gl_operand_t *operand) void _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, - cairo_gl_operand_t *operand, - cairo_gl_tex_t tex_unit) + cairo_gl_operand_t *operand, + cairo_gl_tex_t tex_unit) { const cairo_matrix_t *texgen = NULL; switch (operand->type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: return; case CAIRO_GL_OPERAND_CONSTANT: _cairo_gl_shader_bind_vec4 (ctx, - ctx->current_shader->constant_location[tex_unit], - operand->constant.color[0], - operand->constant.color[1], - operand->constant.color[2], - operand->constant.color[3]); + ctx->current_shader->constant_location[tex_unit], + operand->constant.color[0], + operand->constant.color[1], + operand->constant.color[2], + operand->constant.color[3]); return; case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: @@ -650,7 +650,7 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, _cairo_gl_shader_bind_float (ctx, ctx->current_shader->radius_0_location[tex_unit], operand->gradient.radius_0); - /* fall through */ + /* fall through */ case CAIRO_GL_OPERAND_LINEAR_GRADIENT: case CAIRO_GL_OPERAND_TEXTURE: /* @@ -658,7 +658,8 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, * with CAIRO_EXTEND_NONE). When bilinear filtering is enabled, * these shaders need the texture dimensions for their calculations. */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES && + if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && _cairo_gl_operand_get_extend (operand) == CAIRO_EXTEND_NONE && _cairo_gl_operand_get_gl_filter (operand) == GL_LINEAR) { @@ -695,37 +696,37 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, cairo_bool_t _cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest, - cairo_gl_operand_t *source, - unsigned int vertex_offset) + cairo_gl_operand_t *source, + unsigned int vertex_offset) { if (dest->type != source->type) - return TRUE; + return TRUE; if (dest->vertex_offset != vertex_offset) - return TRUE; + return TRUE; switch (source->type) { case CAIRO_GL_OPERAND_NONE: - return FALSE; + return FALSE; case CAIRO_GL_OPERAND_CONSTANT: - return dest->constant.color[0] != source->constant.color[0] || - dest->constant.color[1] != source->constant.color[1] || - dest->constant.color[2] != source->constant.color[2] || - dest->constant.color[3] != source->constant.color[3]; + return dest->constant.color[0] != source->constant.color[0] || + dest->constant.color[1] != source->constant.color[1] || + dest->constant.color[2] != source->constant.color[2] || + dest->constant.color[3] != source->constant.color[3]; case CAIRO_GL_OPERAND_TEXTURE: - return dest->texture.surface != source->texture.surface || - dest->texture.attributes.extend != source->texture.attributes.extend || - dest->texture.attributes.filter != source->texture.attributes.filter || - dest->texture.attributes.has_component_alpha != source->texture.attributes.has_component_alpha; + return dest->texture.surface != source->texture.surface || + dest->texture.attributes.extend != source->texture.attributes.extend || + dest->texture.attributes.filter != source->texture.attributes.filter || + dest->texture.attributes.has_component_alpha != source->texture.attributes.has_component_alpha; case CAIRO_GL_OPERAND_LINEAR_GRADIENT: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - /* XXX: improve this */ - return TRUE; + /* XXX: improve this */ + return TRUE; default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - break; + ASSERT_NOT_REACHED; + break; } return TRUE; } @@ -736,33 +737,33 @@ _cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand) switch (operand->type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: case CAIRO_GL_OPERAND_CONSTANT: - return 0; + return 0; case CAIRO_GL_OPERAND_TEXTURE: - return operand->texture.texgen ? 0 : 2 * sizeof (GLfloat); + return operand->texture.texgen ? 0 : 2 * sizeof (GLfloat); case CAIRO_GL_OPERAND_LINEAR_GRADIENT: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - return operand->gradient.texgen ? 0 : 2 * sizeof (GLfloat); + return operand->gradient.texgen ? 0 : 2 * sizeof (GLfloat); } } void _cairo_gl_operand_emit (cairo_gl_operand_t *operand, - GLfloat ** vb, - GLfloat x, - GLfloat y) + GLfloat ** vb, + GLfloat x, + GLfloat y) { switch (operand->type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: case CAIRO_GL_OPERAND_CONSTANT: - break; + break; case CAIRO_GL_OPERAND_LINEAR_GRADIENT: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: @@ -775,18 +776,18 @@ _cairo_gl_operand_emit (cairo_gl_operand_t *operand, *(*vb)++ = s; *(*vb)++ = t; - } + } break; case CAIRO_GL_OPERAND_TEXTURE: if (! operand->texture.texgen) { - cairo_surface_attributes_t *src_attributes = &operand->texture.attributes; - double s = x; - double t = y; - - cairo_matrix_transform_point (&src_attributes->matrix, &s, &t); - *(*vb)++ = s; - *(*vb)++ = t; - } - break; + cairo_surface_attributes_t *src_attributes = &operand->texture.attributes; + double s = x; + double t = y; + + cairo_matrix_transform_point (&src_attributes->matrix, &s, &t); + *(*vb)++ = s; + *(*vb)++ = t; + } + break; } } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-gl-private.h index cb915c8cf25..f02a58763e9 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-private.h @@ -60,12 +60,15 @@ #include -#if CAIRO_HAS_GL_SURFACE -#include -#include +#if CAIRO_HAS_GLESV3_SURFACE +#include +#include #elif CAIRO_HAS_GLESV2_SURFACE #include #include +#elif CAIRO_HAS_GL_SURFACE +#include +#include #endif #include "cairo-gl-ext-def-private.h" @@ -99,14 +102,15 @@ typedef struct _cairo_gl_surface cairo_gl_surface_t; -/* GL flavor */ +/* GL flavor is the type of GL supported by the underlying platform. */ typedef enum cairo_gl_flavor { CAIRO_GL_FLAVOR_NONE = 0, CAIRO_GL_FLAVOR_DESKTOP = 1, - CAIRO_GL_FLAVOR_ES = 2 + CAIRO_GL_FLAVOR_ES2 = 2, + CAIRO_GL_FLAVOR_ES3 = 3 } cairo_gl_flavor_t; -/* Indices for vertex attributes used by BindAttribLocation etc */ +/* Indices for vertex attributes used by BindAttribLocation, etc. */ enum { CAIRO_GL_VERTEX_ATTRIB_INDEX = 0, CAIRO_GL_COLOR_ATTRIB_INDEX = 1, @@ -169,7 +173,7 @@ struct _cairo_gl_surface { GLuint fb; /* GL framebuffer object wrapping our data. */ GLuint depth_stencil; /* GL renderbuffer object for holding stencil buffer clip. */ -#if CAIRO_HAS_GL_SURFACE +#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE GLuint msaa_rb; /* The ARB MSAA path uses a renderbuffer. */ GLuint msaa_fb; #endif @@ -178,8 +182,12 @@ struct _cairo_gl_surface { cairo_bool_t stencil_and_msaa_caps_initialized; cairo_bool_t supports_stencil; /* Stencil support for for non-texture surfaces. */ cairo_bool_t supports_msaa; + GLint num_samples; cairo_bool_t msaa_active; /* Whether the multisampling framebuffer is active or not. */ + cairo_bool_t content_in_texture; /* whether we just uploaded image + to texture, used for certain + gles2 extensions and glesv3 */ cairo_clip_t *clip_on_stencil_buffer; int owns_tex; @@ -801,6 +809,10 @@ _cairo_gl_composite_glyphs_with_clip (void *_dst, cairo_composite_glyphs_info_t *info, cairo_clip_t *clip); +cairo_private void +_cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx, + cairo_gl_surface_t *surface); + cairo_private cairo_surface_t * _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, cairo_content_t content, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-shaders.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-shaders.c index fe975d2d7c9..c43cf3b18d5 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-shaders.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-shaders.c @@ -132,7 +132,7 @@ _cairo_gl_shader_cache_destroy (void *data) _cairo_gl_shader_fini (entry->ctx, &entry->shader); if (entry->ctx->current_shader == &entry->shader) - entry->ctx->current_shader = NULL; + entry->ctx->current_shader = NULL; free (entry); } @@ -171,12 +171,12 @@ _cairo_gl_context_init_shaders (cairo_gl_context_t *ctx) memset (ctx->vertex_shaders, 0, sizeof (ctx->vertex_shaders)); status = _cairo_cache_init (&ctx->shaders, - ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ? + ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ? _cairo_gl_shader_cache_equal_desktop : _cairo_gl_shader_cache_equal_gles2, - NULL, - _cairo_gl_shader_cache_destroy, - CAIRO_GL_MAX_SHADERS_PER_CONTEXT); + NULL, + _cairo_gl_shader_cache_destroy, + CAIRO_GL_MAX_SHADERS_PER_CONTEXT); if (unlikely (status)) return status; @@ -225,68 +225,68 @@ cairo_gl_operand_get_var_type (cairo_gl_operand_t *operand) switch (operand->type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: case CAIRO_GL_OPERAND_CONSTANT: - return CAIRO_GL_VAR_NONE; + return CAIRO_GL_VAR_NONE; case CAIRO_GL_OPERAND_LINEAR_GRADIENT: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - return operand->gradient.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS; + return operand->gradient.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS; case CAIRO_GL_OPERAND_TEXTURE: - return operand->texture.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS; + return operand->texture.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS; } } static void cairo_gl_shader_emit_variable (cairo_output_stream_t *stream, - cairo_gl_var_type_t type, - cairo_gl_tex_t name) + cairo_gl_var_type_t type, + cairo_gl_tex_t name) { switch (type) { default: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_VAR_NONE: - break; + break; case CAIRO_GL_VAR_TEXCOORDS: - _cairo_output_stream_printf (stream, + _cairo_output_stream_printf (stream, "attribute vec4 MultiTexCoord%d;\n" - "varying vec2 %s_texcoords;\n", - name, - operand_names[name]); - break; + "varying vec2 %s_texcoords;\n", + name, + operand_names[name]); + break; case CAIRO_GL_VAR_TEXGEN: - _cairo_output_stream_printf (stream, + _cairo_output_stream_printf (stream, "uniform mat3 %s_texgen;\n" - "varying vec2 %s_texcoords;\n", - operand_names[name], - operand_names[name]); - break; + "varying vec2 %s_texcoords;\n", + operand_names[name], + operand_names[name]); + break; } } static void cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream, - cairo_gl_var_type_t type, - cairo_gl_tex_t name) + cairo_gl_var_type_t type, + cairo_gl_tex_t name) { switch (type) { default: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_VAR_NONE: - break; + break; case CAIRO_GL_VAR_TEXCOORDS: - _cairo_output_stream_printf (stream, - " %s_texcoords = MultiTexCoord%d.xy;\n", - operand_names[name], name); - break; + _cairo_output_stream_printf (stream, + " %s_texcoords = MultiTexCoord%d.xy;\n", + operand_names[name], name); + break; case CAIRO_GL_VAR_TEXGEN: - _cairo_output_stream_printf (stream, + _cairo_output_stream_printf (stream, " %s_texcoords = (%s_texgen * Vertex.xyw).xy;\n", - operand_names[name], operand_names[name]); - break; + operand_names[name], operand_names[name]); + break; } } @@ -304,9 +304,9 @@ cairo_gl_shader_def_coverage (cairo_output_stream_t *stream) static cairo_status_t cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src, - cairo_gl_var_type_t mask, + cairo_gl_var_type_t mask, cairo_bool_t use_coverage, - cairo_gl_var_type_t dest, + cairo_gl_var_type_t dest, char **out) { cairo_output_stream_t *stream = _cairo_memory_stream_create (); @@ -361,9 +361,9 @@ _cairo_gl_shader_needs_border_fade (cairo_gl_operand_t *operand) static void cairo_gl_shader_emit_color (cairo_output_stream_t *stream, - cairo_gl_context_t *ctx, - cairo_gl_operand_t *op, - cairo_gl_tex_t name) + cairo_gl_context_t *ctx, + cairo_gl_operand_t *op, + cairo_gl_tex_t name) { const char *namestr = operand_names[name]; const char *rectstr = (ctx->tex_target == GL_TEXTURE_RECTANGLE ? "Rect" : ""); @@ -371,25 +371,25 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, switch (op->type) { case CAIRO_GL_OPERAND_COUNT: default: - ASSERT_NOT_REACHED; - break; + ASSERT_NOT_REACHED; + break; case CAIRO_GL_OPERAND_NONE: - _cairo_output_stream_printf (stream, - "vec4 get_%s()\n" - "{\n" - " return vec4 (0, 0, 0, 1);\n" - "}\n", - namestr); - break; + _cairo_output_stream_printf (stream, + "vec4 get_%s()\n" + "{\n" + " return vec4 (0, 0, 0, 1);\n" + "}\n", + namestr); + break; case CAIRO_GL_OPERAND_CONSTANT: - _cairo_output_stream_printf (stream, - "uniform vec4 %s_constant;\n" - "vec4 get_%s()\n" - "{\n" - " return %s_constant;\n" - "}\n", - namestr, namestr, namestr); - break; + _cairo_output_stream_printf (stream, + "uniform vec4 %s_constant;\n" + "vec4 get_%s()\n" + "{\n" + " return %s_constant;\n" + "}\n", + namestr, namestr, namestr); + break; case CAIRO_GL_OPERAND_TEXTURE: _cairo_output_stream_printf (stream, "uniform sampler2D%s %s_sampler;\n" @@ -398,7 +398,8 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, "vec4 get_%s()\n" "{\n", rectstr, namestr, namestr, namestr, namestr); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES && + if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && _cairo_gl_shader_needs_border_fade (op)) { _cairo_output_stream_printf (stream, @@ -415,7 +416,7 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, "}\n", rectstr, namestr, namestr, namestr); } - break; + break; case CAIRO_GL_OPERAND_LINEAR_GRADIENT: _cairo_output_stream_printf (stream, "varying vec2 %s_texcoords;\n" @@ -425,7 +426,8 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, "vec4 get_%s()\n" "{\n", namestr, namestr, rectstr, namestr, namestr); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES && + if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && _cairo_gl_shader_needs_border_fade (op)) { _cairo_output_stream_printf (stream, @@ -462,7 +464,8 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, " float is_valid = step (-%s_radius_0, t * %s_circle_d.z);\n", namestr, namestr, rectstr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES && + if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && _cairo_gl_shader_needs_border_fade (op)) { _cairo_output_stream_printf (stream, @@ -507,7 +510,8 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, " float upper_t = mix (t.y, t.x, is_valid.x);\n", namestr, namestr, rectstr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES && + if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && _cairo_gl_shader_needs_border_fade (op)) { _cairo_output_stream_printf (stream, @@ -653,11 +657,11 @@ _cairo_gl_shader_emit_wrap (cairo_gl_context_t *ctx, static cairo_status_t cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx, - cairo_gl_shader_in_t in, - cairo_gl_operand_t *src, - cairo_gl_operand_t *mask, + cairo_gl_shader_in_t in, + cairo_gl_operand_t *src, + cairo_gl_operand_t *mask, cairo_bool_t use_coverage, - cairo_gl_operand_type_t dest_type, + cairo_gl_operand_type_t dest_type, char **out) { cairo_output_stream_t *stream = _cairo_memory_stream_create (); @@ -674,7 +678,8 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx, _cairo_gl_shader_emit_wrap (ctx, stream, src, CAIRO_GL_TEX_SOURCE); _cairo_gl_shader_emit_wrap (ctx, stream, mask, CAIRO_GL_TEX_MASK); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) { + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { if (_cairo_gl_shader_needs_border_fade (src)) _cairo_gl_shader_emit_border_fade (stream, src, CAIRO_GL_TEX_SOURCE); if (_cairo_gl_shader_needs_border_fade (mask)) @@ -691,35 +696,35 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx, } _cairo_output_stream_printf (stream, - "void main()\n" - "{\n"); + "void main()\n" + "{\n"); switch (in) { case CAIRO_GL_SHADER_IN_COUNT: default: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_SHADER_IN_NORMAL: - _cairo_output_stream_printf (stream, - " gl_FragColor = get_source() * get_mask().a%s;\n", + _cairo_output_stream_printf (stream, + " gl_FragColor = get_source() * get_mask().a%s;\n", coverage_str); - break; + break; case CAIRO_GL_SHADER_IN_CA_SOURCE: - _cairo_output_stream_printf (stream, - " gl_FragColor = get_source() * get_mask()%s;\n", + _cairo_output_stream_printf (stream, + " gl_FragColor = get_source() * get_mask()%s;\n", coverage_str); - break; + break; case CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA: - _cairo_output_stream_printf (stream, - " gl_FragColor = get_source().a * get_mask()%s;\n", + _cairo_output_stream_printf (stream, + " gl_FragColor = get_source().a * get_mask()%s;\n", coverage_str); - break; + break; } _cairo_output_stream_write (stream, - "}\n\0", 3); + "}\n\0", 3); status = _cairo_memory_stream_destroy (stream, &source, &length); if (unlikely (status)) - return status; + return status; *out = (char *) source; return CAIRO_STATUS_SUCCESS; @@ -995,7 +1000,7 @@ _cairo_gl_set_shader (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader) { if (ctx->current_shader == shader) - return; + return; if (shader) ctx->dispatch.UseProgram (shader->program); @@ -1007,11 +1012,11 @@ _cairo_gl_set_shader (cairo_gl_context_t *ctx, cairo_status_t _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, - cairo_gl_operand_t *source, - cairo_gl_operand_t *mask, + cairo_gl_operand_t *source, + cairo_gl_operand_t *mask, cairo_bool_t use_coverage, - cairo_gl_shader_in_t in, - cairo_gl_shader_t **shader) + cairo_gl_shader_in_t in, + cairo_gl_shader_t **shader) { cairo_shader_cache_entry_t lookup, *entry; char *fs_source; @@ -1040,8 +1045,8 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, entry = _cairo_cache_lookup (&ctx->shaders, &lookup.base); if (entry) { - assert (entry->shader.program); - *shader = &entry->shader; + assert (entry->shader.program); + *shader = &entry->shader; return CAIRO_STATUS_SUCCESS; } @@ -1055,10 +1060,10 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, if (unlikely (status)) return status; - entry = malloc (sizeof (cairo_shader_cache_entry_t)); + entry = _cairo_malloc (sizeof (cairo_shader_cache_entry_t)); if (unlikely (entry == NULL)) { - free (fs_source); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + free (fs_source); + return _cairo_error (CAIRO_STATUS_NO_MEMORY); } memcpy (entry, &lookup, sizeof (cairo_shader_cache_entry_t)); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-source.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-source.c index 12235295f40..7e0ee4a826f 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-source.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-source.c @@ -69,14 +69,15 @@ _cairo_gl_pattern_to_source (cairo_surface_t *dst, if (pattern == NULL) return _cairo_gl_white_source (); - source = malloc (sizeof (*source)); + source = _cairo_malloc (sizeof (*source)); if (unlikely (source == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&source->base, &cairo_gl_source_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + FALSE); /* is_vector */ *src_x = *src_y = 0; status = _cairo_gl_operand_init (&source->operand, pattern, @@ -96,14 +97,15 @@ _cairo_gl_white_source (void) { cairo_gl_source_t *source; - source = malloc (sizeof (*source)); + source = _cairo_malloc (sizeof (*source)); if (unlikely (source == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&source->base, &cairo_gl_source_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + FALSE); /* is_vector */ _cairo_gl_solid_operand_init (&source->operand, CAIRO_COLOR_WHITE); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-spans-compositor.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-spans-compositor.c index 4317ccd074a..0a4538a047c 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-spans-compositor.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-spans-compositor.c @@ -139,27 +139,27 @@ _cairo_gl_unbounded_spans (void *abstract_renderer, r->xmax, y + height, 0); } else { - if (spans[0].x != r->xmin) { + if (spans[0].x != r->xmin) { emit (r->ctx, r->xmin, y, spans[0].x, y + height, 0); - } + } - do { + do { emit (r->ctx, spans[0].x, y, spans[1].x, y + height, r->opacity * spans[0].coverage); - spans++; - } while (--num_spans > 1); + spans++; + } while (--num_spans > 1); - if (spans[0].x != r->xmax) { + if (spans[0].x != r->xmax) { emit (r->ctx, spans[0].x, y, r->xmax, y + height, 0); - } + } } r->ymin = y + height; @@ -189,27 +189,27 @@ _cairo_gl_clipped_spans (void *abstract_renderer, r->xmax, y + height, 0); } else { - if (spans[0].x != r->xmin) { + if (spans[0].x != r->xmin) { emit (r->ctx, r->xmin, y, spans[0].x, y + height, 0); - } + } - do { + do { emit (r->ctx, spans[0].x, y, spans[1].x, y + height, r->opacity * spans[0].coverage); - spans++; - } while (--num_spans > 1); + spans++; + } while (--num_spans > 1); - if (spans[0].x != r->xmax) { + if (spans[0].x != r->xmax) { emit (r->ctx, spans[0].x, y, r->xmax, y + height, 0); - } + } } r->ymin = y + height; @@ -273,13 +273,13 @@ fill_boxes (void *_dst, TRACE ((stderr, "%s\n", __FUNCTION__)); status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) - goto FAIL; + goto FAIL; _cairo_gl_composite_set_solid_source (&setup, color); status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) - goto FAIL; + goto FAIL; emit_aligned_boxes (ctx, boxes); status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); @@ -341,14 +341,14 @@ static cairo_int_status_t copy_boxes (void *_dst, status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE, _dst, FALSE); if (unlikely (status)) - goto FAIL; + goto FAIL; _cairo_gl_composite_set_source_operand (&setup, &src->operand); _cairo_gl_operand_translate (&setup.src, -dx, -dy); status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) - goto FAIL; + goto FAIL; emit_aligned_boxes (ctx, boxes); status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); @@ -396,7 +396,7 @@ composite_boxes (void *_dst, status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) - goto FAIL; + goto FAIL; _cairo_gl_composite_set_source_operand (&setup, src_operand); @@ -408,7 +408,7 @@ composite_boxes (void *_dst, status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) - goto FAIL; + goto FAIL; emit_aligned_boxes (ctx, boxes); status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); @@ -454,17 +454,17 @@ _cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t *_r, return CAIRO_INT_STATUS_UNSUPPORTED; status = _cairo_gl_composite_init (&r->setup, - op, (cairo_gl_surface_t *)composite->surface, - FALSE); + op, (cairo_gl_surface_t *)composite->surface, + FALSE); if (unlikely (status)) - goto FAIL; + goto FAIL; status = _cairo_gl_composite_set_source (&r->setup, source, &composite->source_sample_area, &composite->unbounded, TRUE); if (unlikely (status)) - goto FAIL; + goto FAIL; r->opacity = 1.0; if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) { @@ -483,7 +483,7 @@ _cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t *_r, status = _cairo_gl_composite_begin (&r->setup, &r->ctx); if (unlikely (status)) - goto FAIL; + goto FAIL; r->emit = _cairo_gl_context_choose_emit_span (r->ctx); if (composite->is_bounded) { @@ -491,13 +491,13 @@ _cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t *_r, r->base.render_rows = _cairo_gl_bounded_opaque_spans; else r->base.render_rows = _cairo_gl_bounded_spans; - r->base.finish = _cairo_gl_finish_bounded_spans; + r->base.finish = _cairo_gl_finish_bounded_spans; } else { if (needs_clip) r->base.render_rows = _cairo_gl_clipped_spans; else r->base.render_rows = _cairo_gl_unbounded_spans; - r->base.finish = _cairo_gl_finish_unbounded_spans; + r->base.finish = _cairo_gl_finish_unbounded_spans; r->xmin = composite->unbounded.x; r->xmax = composite->unbounded.x + composite->unbounded.width; r->ymin = composite->unbounded.y; @@ -528,10 +528,11 @@ _cairo_gl_span_renderer_fini (cairo_abstract_span_renderer_t *_r, const cairo_compositor_t * _cairo_gl_span_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_spans_compositor_t spans; static cairo_compositor_t shape; - if (spans.base.delegate == NULL) { + if (_cairo_atomic_init_once_enter(&once)) { /* The fallback to traps here is essentially just for glyphs... */ _cairo_shape_mask_compositor_init (&shape, _cairo_gl_traps_compositor_get()); @@ -547,6 +548,8 @@ _cairo_gl_span_compositor_get (void) //spans.check_span_renderer = check_span_renderer; spans.renderer_init = _cairo_gl_span_renderer_init; spans.renderer_fini = _cairo_gl_span_renderer_fini; + + _cairo_atomic_init_once_leave(&once); } return &spans.base; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-surface.c index cfccf4dfda5..12ea3ddc4b4 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-surface.c @@ -389,11 +389,13 @@ _cairo_gl_surface_init (cairo_device_t *device, _cairo_surface_init (&surface->base, &_cairo_gl_surface_backend, device, - content); + content, + FALSE); /* is_vector */ surface->width = width; surface->height = height; surface->needs_update = FALSE; + surface->content_in_texture = FALSE; _cairo_gl_surface_embedded_operand_init (surface); } @@ -432,6 +434,7 @@ _cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx, _cairo_gl_surface_init (&ctx->base, surface, content, width, height); surface->supports_msaa = ctx->supports_msaa; + surface->num_samples = ctx->num_samples; surface->supports_stencil = TRUE; /* Create the texture used to store the surface's data. */ @@ -523,7 +526,7 @@ _cairo_gl_surface_create_scratch_for_caching (cairo_gl_context_t *ctx, static cairo_status_t _cairo_gl_surface_clear (cairo_gl_surface_t *surface, - const cairo_color_t *color) + const cairo_color_t *color) { cairo_gl_context_t *ctx; cairo_status_t status; @@ -535,16 +538,16 @@ _cairo_gl_surface_clear (cairo_gl_surface_t *surface, _cairo_gl_context_set_destination (ctx, surface, surface->msaa_active); if (surface->base.content & CAIRO_CONTENT_COLOR) { - r = color->red * color->alpha; - g = color->green * color->alpha; - b = color->blue * color->alpha; + r = color->red * color->alpha; + g = color->green * color->alpha; + b = color->blue * color->alpha; } else { - r = g = b = 0; + r = g = b = 0; } if (surface->base.content & CAIRO_CONTENT_ALPHA) { - a = color->alpha; + a = color->alpha; } else { - a = 1.0; + a = 1.0; } glDisable (GL_SCISSOR_TEST); @@ -711,11 +714,11 @@ cairo_gl_surface_set_size (cairo_surface_t *abstract_surface, if (unlikely (abstract_surface->finished)) { _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - return; + return; } if (! _cairo_surface_is_gl (abstract_surface) || - _cairo_gl_surface_is_texture (surface)) { + _cairo_gl_surface_is_texture (surface)) { _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); return; @@ -760,7 +763,7 @@ cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface) if (unlikely (abstract_surface->finished)) { _cairo_surface_set_error (abstract_surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - return; + return; } if (! _cairo_surface_is_gl (abstract_surface)) { @@ -771,11 +774,11 @@ cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface) if (! _cairo_gl_surface_is_texture (surface)) { cairo_gl_context_t *ctx; - cairo_status_t status; + cairo_status_t status; - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return; + status = _cairo_gl_context_acquire (surface->base.device, &ctx); + if (unlikely (status)) + return; /* For swapping on EGL, at least, we need a valid context/target. */ _cairo_gl_context_set_destination (ctx, surface, FALSE); @@ -784,9 +787,9 @@ cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface) ctx->swap_buffers (ctx, surface); - status = _cairo_gl_context_release (ctx, status); - if (status) - status = _cairo_surface_set_error (abstract_surface, status); + status = _cairo_gl_context_release (ctx, status); + if (status) + status = _cairo_surface_set_error (abstract_surface, status); } } @@ -801,7 +804,7 @@ _cairo_gl_surface_create_similar (void *abstract_surface, cairo_status_t status; if (! _cairo_gl_surface_size_valid (abstract_surface, width, height)) - return _cairo_image_surface_create_with_content (content, width, height); + return _cairo_image_surface_create_with_content (content, width, height); status = _cairo_gl_context_acquire (surface->device, &ctx); if (unlikely (status)) @@ -811,8 +814,8 @@ _cairo_gl_surface_create_similar (void *abstract_surface, status = _cairo_gl_context_release (ctx, status); if (unlikely (status)) { - cairo_surface_destroy (surface); - return _cairo_surface_create_in_error (status); + cairo_surface_destroy (surface); + return _cairo_surface_create_in_error (status); } return surface; @@ -833,13 +836,13 @@ _cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst, status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE, dst, FALSE); if (unlikely (status)) - goto CLEANUP; + goto CLEANUP; _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_BLACK); status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) - goto CLEANUP; + goto CLEANUP; _cairo_gl_context_emit_rect (ctx, x, y, x + width, y + height); @@ -867,12 +870,54 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, cairo_image_surface_t *clone = NULL; cairo_gl_context_t *ctx; int cpp; + cairo_image_surface_t *rgba_clone = NULL; cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; status = _cairo_gl_context_acquire (dst->base.device, &ctx); if (unlikely (status)) return status; + if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 || + _cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) { + pixman_format_code_t pixman_format; + cairo_surface_pattern_t pattern; + cairo_bool_t require_conversion = FALSE; + pixman_format = _cairo_is_little_endian () ? PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8; + + if (src->base.content != CAIRO_CONTENT_ALPHA) { + if (src->pixman_format != pixman_format) + require_conversion = TRUE; + } + else if (dst->base.content != CAIRO_CONTENT_ALPHA) { + require_conversion = TRUE; + } + else if (src->pixman_format != PIXMAN_a8) { + pixman_format = PIXMAN_a8; + require_conversion = TRUE; + } + + if (require_conversion) { + rgba_clone = (cairo_image_surface_t *) + _cairo_image_surface_create_with_pixman_format (NULL, + pixman_format, + src->width, + src->height, + 0); + if (unlikely (rgba_clone->base.status)) + goto FAIL; + + _cairo_pattern_init_for_surface (&pattern, &src->base); + status = _cairo_surface_paint (&rgba_clone->base, + CAIRO_OPERATOR_SOURCE, + &pattern.base, NULL); + _cairo_pattern_fini (&pattern.base); + if (unlikely (status)) + goto FAIL; + + src = rgba_clone; + } + } + if (! _cairo_gl_get_image_format_and_type (ctx->gl_flavor, src->pixman_format, &internal_format, @@ -890,7 +935,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, is_supported = _cairo_gl_get_image_format_and_type (ctx->gl_flavor, clone->pixman_format, - &internal_format, + &internal_format, &format, &type, &has_alpha, @@ -921,7 +966,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, * alignment constraint */ if (src->stride < 0 || - (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES && + (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 && (src->width * cpp < src->stride - 3 || width != src->width))) { @@ -937,11 +982,20 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, else { glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp); } - _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); + /* we must resolve the renderbuffer to texture before we + upload image */ + status = _cairo_gl_surface_resolve_multisampling (dst); + if (unlikely (status)) { + free (data_start_gles2); + goto FAIL; + } + + _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); glBindTexture (ctx->tex_target, dst->tex); glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -960,26 +1014,28 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, dst_x, dst_y, width, height); } + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) + dst->content_in_texture = TRUE; } else { - cairo_surface_t *tmp; - - tmp = _cairo_gl_surface_create_scratch (ctx, - dst->base.content, - width, height); - if (unlikely (tmp->status)) - goto FAIL; - - status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp, - src, - src_x, src_y, - width, height, - 0, 0, force_flush); - if (status == CAIRO_INT_STATUS_SUCCESS) { - cairo_surface_pattern_t tmp_pattern; + cairo_surface_t *tmp; + + tmp = _cairo_gl_surface_create_scratch (ctx, + dst->base.content, + width, height); + if (unlikely (tmp->status)) + goto FAIL; + + status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp, + src, + src_x, src_y, + width, height, + 0, 0, force_flush); + if (status == CAIRO_INT_STATUS_SUCCESS) { + cairo_surface_pattern_t tmp_pattern; cairo_rectangle_int_t r; cairo_clip_t *clip; - _cairo_pattern_init_for_surface (&tmp_pattern, tmp); + _cairo_pattern_init_for_surface (&tmp_pattern, tmp); cairo_matrix_init_translate (&tmp_pattern.base.matrix, -dst_x, -dst_y); tmp_pattern.base.filter = CAIRO_FILTER_NEAREST; @@ -995,17 +1051,22 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, &tmp_pattern.base, clip); _cairo_clip_destroy (clip); - _cairo_pattern_fini (&tmp_pattern.base); - } + _cairo_pattern_fini (&tmp_pattern.base); + } - cairo_surface_destroy (tmp); + cairo_surface_destroy (tmp); + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) + dst->content_in_texture = TRUE; } FAIL: status = _cairo_gl_context_release (ctx, status); if (clone) - cairo_surface_destroy (&clone->base); + cairo_surface_destroy (&clone->base); + + if (rgba_clone) + cairo_surface_destroy (&rgba_clone->base); return status; } @@ -1025,28 +1086,28 @@ _cairo_gl_surface_finish (void *abstract_surface) status = _cairo_gl_context_acquire (surface->base.device, &ctx); if (unlikely (status)) - return status; + return status; if (ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE); + ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) + _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE); if (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK); + ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) + _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK); if (ctx->current_target == surface) ctx->current_target = NULL; if (surface->fb) - ctx->dispatch.DeleteFramebuffers (1, &surface->fb); + ctx->dispatch.DeleteFramebuffers (1, &surface->fb); if (surface->depth_stencil) - ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil); + ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil); if (surface->owns_tex) glDeleteTextures (1, &surface->tex); if (surface->msaa_depth_stencil) ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil); -#if CAIRO_HAS_GL_SURFACE +#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE if (surface->msaa_fb) ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb); if (surface->msaa_rb) @@ -1098,7 +1159,8 @@ _cairo_gl_surface_map_to_image (void *abstract_surface, return NULL; } - if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES) { + if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES3 || + _cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2) { /* If only RGBA is supported, we must download data in a compatible * format. This means that pixman will convert the data on the CPU when * interacting with other image surfaces. For ALPHA, GLES2 does not @@ -1147,13 +1209,29 @@ _cairo_gl_surface_map_to_image (void *abstract_surface, * fall back instead. */ _cairo_gl_composite_flush (ctx); - _cairo_gl_context_set_destination (ctx, surface, FALSE); + + if (ctx->gl_flavor != CAIRO_GL_FLAVOR_ES3) { + _cairo_gl_context_set_destination (ctx, surface, FALSE); + } else { + if (surface->content_in_texture) { + _cairo_gl_ensure_framebuffer (ctx, surface); + ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); + } else { + status = _cairo_gl_surface_resolve_multisampling (surface); + if (unlikely (status)) { + status = _cairo_gl_context_release (ctx, status); + cairo_surface_destroy (&image->base); + return _cairo_image_surface_create_in_error (status); + } + } + } flipped = ! _cairo_gl_surface_is_texture (surface); mesa_invert = flipped && ctx->has_mesa_pack_invert; glPixelStorei (GL_PACK_ALIGNMENT, 4); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp); if (mesa_invert) glPixelStorei (GL_PACK_INVERT_MESA, 1); @@ -1181,7 +1259,7 @@ _cairo_gl_surface_map_to_image (void *abstract_surface, uint8_t *bot = image->data + (image->height-1)*image->stride; if (image->stride > (int)sizeof(stack)) { - row = malloc (image->stride); + row = _cairo_malloc (image->stride); if (unlikely (row == NULL)) { cairo_surface_destroy (&image->base); return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1291,13 +1369,13 @@ _cairo_gl_surface_flush (void *abstract_surface, unsigned flags) status = _cairo_gl_context_acquire (surface->base.device, &ctx); if (unlikely (status)) - return status; + return status; if ((ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) || - (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) || - (ctx->current_target == surface)) + ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) || + (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE && + ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) || + (ctx->current_target == surface)) _cairo_gl_composite_flush (ctx); status = _cairo_gl_surface_resolve_multisampling (surface); @@ -1318,7 +1396,10 @@ _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface) return CAIRO_INT_STATUS_SUCCESS; /* GLES surfaces do not need explicit resolution. */ - if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES) + if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES2) + return CAIRO_INT_STATUS_SUCCESS; + else if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES3 && + surface->content_in_texture) return CAIRO_INT_STATUS_SUCCESS; if (! _cairo_gl_surface_is_texture (surface)) @@ -1328,10 +1409,20 @@ _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface) if (unlikely (status)) return status; - ctx->current_target = surface; +#if CAIRO_HAS_GLESV3_SURFACE + _cairo_gl_composite_flush (ctx); + ctx->current_target = NULL; + _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE); + if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) + surface->content_in_texture = TRUE; -#if CAIRO_HAS_GL_SURFACE +#elif CAIRO_HAS_GL_SURFACE + ctx->current_target = surface; _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE); + +#else + ctx->current_target = surface; + #endif status = _cairo_gl_context_release (ctx, status); @@ -1353,14 +1444,14 @@ _cairo_gl_surface_paint (void *surface, { /* simplify the common case of clearing the surface */ if (clip == NULL) { - if (op == CAIRO_OPERATOR_CLEAR) - return _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT); + if (op == CAIRO_OPERATOR_CLEAR) + return _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT); else if (source->type == CAIRO_PATTERN_TYPE_SOLID && - (op == CAIRO_OPERATOR_SOURCE || - (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) { - return _cairo_gl_surface_clear (surface, - &((cairo_solid_pattern_t *) source)->color); - } + (op == CAIRO_OPERATOR_SOURCE || + (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) { + return _cairo_gl_surface_clear (surface, + &((cairo_solid_pattern_t *) source)->color); + } } return _cairo_compositor_paint (get_compositor (surface), surface, @@ -1379,16 +1470,16 @@ _cairo_gl_surface_mask (void *surface, } static cairo_int_status_t -_cairo_gl_surface_stroke (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) +_cairo_gl_surface_stroke (void *surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_path_fixed_t *path, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) { return _cairo_compositor_stroke (get_compositor (surface), surface, op, source, path, style, @@ -1398,13 +1489,13 @@ _cairo_gl_surface_stroke (void *surface, static cairo_int_status_t _cairo_gl_surface_fill (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t*path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_path_fixed_t*path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias, + const cairo_clip_t *clip) { return _cairo_compositor_fill (get_compositor (surface), surface, op, source, path, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-traps-compositor.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-traps-compositor.c index 125ed4eabcb..7938c5b20a5 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-traps-compositor.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-traps-compositor.c @@ -137,13 +137,13 @@ fill_boxes (void *_dst, status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) - goto FAIL; + goto FAIL; _cairo_gl_composite_set_solid_source (&setup, color); status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) - goto FAIL; + goto FAIL; emit_aligned_boxes (ctx, boxes); status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); @@ -173,7 +173,7 @@ composite_boxes (void *_dst, status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) - goto FAIL; + goto FAIL; _cairo_gl_composite_set_source_operand (&setup, source_to_operand (abstract_src)); @@ -185,7 +185,7 @@ composite_boxes (void *_dst, status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) - goto FAIL; + goto FAIL; emit_aligned_boxes (ctx, boxes); status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); @@ -215,7 +215,7 @@ composite (void *_dst, status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) - goto FAIL; + goto FAIL; _cairo_gl_composite_set_source_operand (&setup, source_to_operand (abstract_src)); @@ -227,7 +227,7 @@ composite (void *_dst, status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) - goto FAIL; + goto FAIL; /* XXX clip */ _cairo_gl_context_emit_rect (ctx, dst_x, dst_y, dst_x+width, dst_y+height); @@ -303,36 +303,6 @@ traps_to_operand (void *_dst, return image->status; } - /* GLES2 only supports RGB/RGBA when uploading */ - if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES) { - cairo_surface_pattern_t pattern; - cairo_surface_t *rgba_image; - - /* XXX perform this fixup inside _cairo_gl_draw_image() */ - - rgba_image = - _cairo_image_surface_create_with_pixman_format (NULL, - _cairo_is_little_endian () ? PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8, - extents->width, - extents->height, - 0); - if (unlikely (rgba_image->status)) - return rgba_image->status; - - _cairo_pattern_init_for_surface (&pattern, image); - status = _cairo_surface_paint (rgba_image, CAIRO_OPERATOR_SOURCE, - &pattern.base, NULL); - _cairo_pattern_fini (&pattern.base); - - cairo_surface_destroy (image); - image = rgba_image; - - if (unlikely (status)) { - cairo_surface_destroy (image); - return status; - } - } - mask = _cairo_surface_create_scratch (_dst, CAIRO_CONTENT_COLOR_ALPHA, extents->width, @@ -394,7 +364,7 @@ composite_traps (void *_dst, status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) - goto FAIL; + goto FAIL; _cairo_gl_composite_set_source_operand (&setup, source_to_operand (abstract_src)); @@ -405,7 +375,7 @@ composite_traps (void *_dst, status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) - goto FAIL; + goto FAIL; /* XXX clip */ _cairo_gl_context_emit_rect (ctx, @@ -494,7 +464,7 @@ composite_tristrip (void *_dst, status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); if (unlikely (status)) - goto FAIL; + goto FAIL; _cairo_gl_composite_set_source_operand (&setup, source_to_operand (abstract_src)); @@ -503,7 +473,7 @@ composite_tristrip (void *_dst, status = _cairo_gl_composite_begin (&setup, &ctx); if (unlikely (status)) - goto FAIL; + goto FAIL; /* XXX clip */ _cairo_gl_context_emit_rect (ctx, @@ -530,9 +500,10 @@ check_composite (const cairo_composite_rectangles_t *extents) const cairo_compositor_t * _cairo_gl_traps_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_traps_compositor_t compositor; - if (compositor.base.delegate == NULL) { + if (_cairo_atomic_init_once_enter(&once)) { _cairo_traps_compositor_init (&compositor, &_cairo_fallback_compositor); compositor.acquire = acquire; compositor.release = release; @@ -552,6 +523,8 @@ _cairo_gl_traps_compositor_get (void) compositor.composite_tristrip = composite_tristrip; compositor.check_composite_glyphs = _cairo_gl_check_composite_glyphs; compositor.composite_glyphs = _cairo_gl_composite_glyphs; + + _cairo_atomic_init_once_leave(&once); } return &compositor.base; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl.h b/Build/source/libs/cairo/cairo-src/src/cairo-gl.h index 9fd7608f5cf..7cd869c76b1 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl.h @@ -62,7 +62,7 @@ #include "cairo.h" -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV2_SURFACE +#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV2_SURFACE || CAIRO_HAS_GLESV3_SURFACE CAIRO_BEGIN_DECLS diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-glx-context.c b/Build/source/libs/cairo/cairo-src/src/cairo-glx-context.c index 3761b9079a4..66f5a0d1b45 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-glx-context.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-glx-context.c @@ -310,7 +310,7 @@ cairo_gl_surface_create_for_window (cairo_device_t *device, return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); if (width <= 0 || height <= 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); surface = calloc (1, sizeof (cairo_glx_surface_t)); if (unlikely (surface == NULL)) diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gstate-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-gstate-private.h index b2ccc76d145..198c6699855 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gstate-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gstate-private.h @@ -323,6 +323,15 @@ _cairo_gstate_show_surface (cairo_gstate_t *gstate, double width, double height); +cairo_private cairo_status_t +_cairo_gstate_tag_begin (cairo_gstate_t *gstate, + const char *tag_name, + const char *attributes); + +cairo_private cairo_status_t +_cairo_gstate_tag_end (cairo_gstate_t *gstate, + const char *tag_name); + cairo_private cairo_status_t _cairo_gstate_set_font_size (cairo_gstate_t *gstate, double size); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gstate.c b/Build/source/libs/cairo/cairo-src/src/cairo-gstate.c index b4e988e96d8..ff0cb8be734 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gstate.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gstate.c @@ -45,12 +45,6 @@ #include "cairo-pattern-private.h" #include "cairo-traps-private.h" -#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) -#define ISFINITE(x) isfinite (x) -#else -#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */ -#endif - static cairo_status_t _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other); @@ -225,7 +219,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate) cairo_pattern_destroy (gstate->source); gstate->source = NULL; - VG (VALGRIND_MAKE_MEM_NOACCESS (gstate, sizeof (cairo_gstate_t))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (gstate, sizeof (cairo_gstate_t))); } /** @@ -247,7 +241,7 @@ _cairo_gstate_save (cairo_gstate_t **gstate, cairo_gstate_t **freelist) top = *freelist; if (top == NULL) { - top = malloc (sizeof (cairo_gstate_t)); + top = _cairo_malloc (sizeof (cairo_gstate_t)); if (unlikely (top == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } else @@ -1228,6 +1222,7 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate, _cairo_path_fixed_approximate_stroke_extents (path, &gstate->stroke_style, &gstate->ctm, + gstate->target->is_vector, &extents); if (x < extents.x || x > extents.x + extents.width || y < extents.y || y > extents.y + extents.height) @@ -1645,6 +1640,65 @@ _cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate) return list; } +cairo_status_t +_cairo_gstate_tag_begin (cairo_gstate_t *gstate, + const char *tag_name, const char *attributes) +{ + cairo_pattern_union_t source_pattern; + cairo_stroke_style_t style; + double dash[2]; + cairo_status_t status; + cairo_matrix_t aggregate_transform; + cairo_matrix_t aggregate_transform_inverse; + + status = _cairo_gstate_get_pattern_status (gstate->source); + if (unlikely (status)) + return status; + + cairo_matrix_multiply (&aggregate_transform, + &gstate->ctm, + &gstate->target->device_transform); + cairo_matrix_multiply (&aggregate_transform_inverse, + &gstate->target->device_transform_inverse, + &gstate->ctm_inverse); + + memcpy (&style, &gstate->stroke_style, sizeof (gstate->stroke_style)); + if (_cairo_stroke_style_dash_can_approximate (&gstate->stroke_style, &aggregate_transform, gstate->tolerance)) { + style.dash = dash; + _cairo_stroke_style_dash_approximate (&gstate->stroke_style, &gstate->ctm, gstate->tolerance, + &style.dash_offset, + style.dash, + &style.num_dashes); + } + + _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); + + return _cairo_surface_tag (gstate->target, + TRUE, /* begin */ + tag_name, + attributes ? attributes : "", + &source_pattern.base, + &style, + &aggregate_transform, + &aggregate_transform_inverse, + gstate->clip); +} + +cairo_status_t +_cairo_gstate_tag_end (cairo_gstate_t *gstate, + const char *tag_name) +{ + return _cairo_surface_tag (gstate->target, + FALSE, /* begin */ + tag_name, + NULL, /* attributes */ + NULL, /* source */ + NULL, /* stroke_style */ + NULL, /* ctm */ + NULL, /* ctm_inverse*/ + NULL); /* clip */ +} + static void _cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate) { @@ -2159,7 +2213,7 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate, *num_transformed_glyphs = 0; return; } - /* XXX We currently drop any glyphs that has its position outside + /* XXX We currently drop any glyphs that have their position outside * of the surface boundaries by a safety margin depending on the * font scale. This however can fail in extreme cases where the * font has really long swashes for example... We can correctly diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-hash.c b/Build/source/libs/cairo/cairo-src/src/cairo-hash.c index 928c74b8bd6..5a789906f2b 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-hash.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-hash.c @@ -164,7 +164,7 @@ _cairo_hash_table_create (cairo_hash_keys_equal_func_t keys_equal) { cairo_hash_table_t *hash_table; - hash_table = malloc (sizeof (cairo_hash_table_t)); + hash_table = _cairo_malloc (sizeof (cairo_hash_table_t)); if (unlikely (hash_table == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-image-compositor.c b/Build/source/libs/cairo/cairo-src/src/cairo-image-compositor.c index 48072f81bd0..bbf4cf2281d 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-image-compositor.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-image-compositor.c @@ -820,6 +820,18 @@ get_glyph_cache (void) return global_glyph_cache; } +void +_cairo_image_compositor_reset_static_data (void) +{ + CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex); + + if (global_glyph_cache) + pixman_glyph_cache_destroy (global_glyph_cache); + global_glyph_cache = NULL; + + CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex); +} + void _cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph) @@ -945,6 +957,11 @@ out_unlock: return status; } #else +void +_cairo_image_compositor_reset_static_data (void) +{ +} + void _cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph) @@ -1244,11 +1261,12 @@ check_composite (const cairo_composite_rectangles_t *extents) const cairo_compositor_t * _cairo_image_traps_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_traps_compositor_t compositor; - if (compositor.base.delegate == NULL) { - _cairo_traps_compositor_init (&compositor, - &__cairo_no_compositor); + if (_cairo_atomic_init_once_enter(&once)) { + _cairo_traps_compositor_init(&compositor, + &__cairo_no_compositor); compositor.acquire = acquire; compositor.release = release; compositor.set_clip_region = set_clip_region; @@ -1269,6 +1287,8 @@ _cairo_image_traps_compositor_get (void) #endif compositor.check_composite_glyphs = check_composite_glyphs; compositor.composite_glyphs = composite_glyphs; + + _cairo_atomic_init_once_leave(&once); } return &compositor.base; @@ -1277,9 +1297,10 @@ _cairo_image_traps_compositor_get (void) const cairo_compositor_t * _cairo_image_mask_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_mask_compositor_t compositor; - if (compositor.base.delegate == NULL) { + if (_cairo_atomic_init_once_enter(&once)) { _cairo_mask_compositor_init (&compositor, _cairo_image_traps_compositor_get ()); compositor.acquire = acquire; @@ -1296,6 +1317,8 @@ _cairo_image_mask_compositor_get (void) compositor.composite_boxes = composite_boxes; compositor.check_composite_glyphs = check_composite_glyphs; compositor.composite_glyphs = composite_glyphs; + + _cairo_atomic_init_once_leave(&once); } return &compositor.base; @@ -1575,7 +1598,7 @@ typedef struct _cairo_image_span_renderer { pixman_image_t *src, *mask; union { struct fill { - int stride; + ptrdiff_t stride; uint8_t *data; uint32_t pixel; } fill; @@ -1594,7 +1617,7 @@ typedef struct _cairo_image_span_renderer { struct finish { cairo_rectangle_int_t extents; int src_x, src_y; - int stride; + ptrdiff_t stride; uint8_t *data; } mask; } u; @@ -1763,7 +1786,7 @@ _fill16_spans (void *abstract_renderer, int y, int h, if (spans[0].coverage) { int len = spans[1].x - spans[0].x; uint16_t *d = (uint16_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*2); - while (len--) + while (len-- > 0) *d++ = r->u.fill.pixel; } spans++; @@ -1775,7 +1798,7 @@ _fill16_spans (void *abstract_renderer, int y, int h, do { int len = spans[1].x - spans[0].x; uint16_t *d = (uint16_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*2); - while (len--) + while (len-- > 0) *d++ = r->u.fill.pixel; yy++; } while (--hh); @@ -1805,7 +1828,7 @@ _fill32_spans (void *abstract_renderer, int y, int h, spans[0].x, y, len, 1, r->u.fill.pixel); } else { uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4); - while (len--) + while (len-- > 0) *d++ = r->u.fill.pixel; } } @@ -1823,7 +1846,7 @@ _fill32_spans (void *abstract_renderer, int y, int h, do { int len = spans[1].x - spans[0].x; uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4); - while (len--) + while (len-- > 0) *d++ = r->u.fill.pixel; yy++; } while (--hh); @@ -2180,7 +2203,7 @@ _fill_a8_lerp_opaque_spans (void *abstract_renderer, int y, int h, uint8_t s = mul8_8(a, r->u.fill.pixel); uint8_t *dst = d + spans[0].x; a = ~a; - while (len--) { + while (len-- > 0) { uint8_t t = mul8_8(*dst, a); *dst++ = t + s; } @@ -2206,7 +2229,7 @@ _fill_a8_lerp_opaque_spans (void *abstract_renderer, int y, int h, do { int len = spans[1].x - spans[0].x; uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x; - while (len--) { + while (len-- > 0) { uint8_t t = mul8_8(*d, a); *d++ = t + s; } @@ -2266,7 +2289,7 @@ _fill_xrgb32_lerp_opaque_spans (void *abstract_renderer, int y, int h, do { int len = spans[1].x - spans[0].x; uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4); - while (len--) + while (len-- > 0) *d++ = r->u.fill.pixel; yy++; } while (--hh); @@ -2276,7 +2299,7 @@ _fill_xrgb32_lerp_opaque_spans (void *abstract_renderer, int y, int h, do { int len = spans[1].x - spans[0].x; uint32_t *d = (uint32_t *)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4); - while (len--) { + while (len-- > 0) { *d = lerp8x4 (r->u.fill.pixel, a, *d); d++; } @@ -2308,7 +2331,7 @@ _fill_a8_lerp_spans (void *abstract_renderer, int y, int h, uint8_t *d = r->u.fill.data + r->u.fill.stride*y + spans[0].x; uint16_t p = (uint16_t)a * r->u.fill.pixel + 0x7f; uint16_t ia = ~a; - while (len--) { + while (len-- > 0) { uint16_t t = *d*ia + p; *d++ = (t + (t>>8)) >> 8; } @@ -2325,7 +2348,7 @@ _fill_a8_lerp_spans (void *abstract_renderer, int y, int h, do { int len = spans[1].x - spans[0].x; uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x; - while (len--) { + while (len-- > 0) { uint16_t t = *d*ia + p; *d++ = (t + (t>>8)) >> 8; } @@ -2354,7 +2377,7 @@ _fill_xrgb32_lerp_spans (void *abstract_renderer, int y, int h, if (a) { int len = spans[1].x - spans[0].x; uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4); - while (len--) { + while (len-- > 0) { *d = lerp8x4 (r->u.fill.pixel, a, *d); d++; } @@ -2369,7 +2392,7 @@ _fill_xrgb32_lerp_spans (void *abstract_renderer, int y, int h, do { int len = spans[1].x - spans[0].x; uint32_t *d = (uint32_t *)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4); - while (len--) { + while (len-- > 0) { *d = lerp8x4 (r->u.fill.pixel, a, *d); d++; } @@ -2407,7 +2430,7 @@ _blit_xrgb32_lerp_spans (void *abstract_renderer, int y, int h, else memcpy(d, s, len*4); } else { - while (len--) { + while (len-- > 0) { *d = lerp8x4 (*s, a, *d); s++, d++; } @@ -2430,7 +2453,7 @@ _blit_xrgb32_lerp_spans (void *abstract_renderer, int y, int h, else memcpy(d, s, len * 4); } else { - while (len--) { + while (len-- > 0) { *d = lerp8x4 (*s, a, *d); s++, d++; } @@ -2911,7 +2934,7 @@ inplace_renderer_init (cairo_image_span_renderer_t *r, /* Create an effectively unbounded mask by repeating the single line */ buf = r->_buf; if (width > SZ_BUF) { - buf = malloc (width); + buf = _cairo_malloc (width); if (unlikely (buf == NULL)) { pixman_image_unref (r->src); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -3105,10 +3128,11 @@ span_renderer_fini (cairo_abstract_span_renderer_t *_r, const cairo_compositor_t * _cairo_image_spans_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_spans_compositor_t spans; static cairo_compositor_t shape; - if (spans.base.delegate == NULL) { + if (_cairo_atomic_init_once_enter(&once)) { _cairo_shape_mask_compositor_init (&shape, _cairo_image_traps_compositor_get()); shape.glyphs = NULL; @@ -3131,6 +3155,8 @@ _cairo_image_spans_compositor_get (void) //spans.check_span_renderer = check_span_renderer; spans.renderer_init = span_renderer_init; spans.renderer_fini = span_renderer_fini; + + _cairo_atomic_init_once_leave(&once); } return &spans.base; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-image-source.c b/Build/source/libs/cairo/cairo-src/src/cairo-image-source.c index 950053db2c1..0b50afcad32 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-image-source.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-image-source.c @@ -872,7 +872,7 @@ create_separable_convolution (int *n_values, size_y = (1 << ysubsample) * ywidth; *n_values = 4 + size_x + size_y; - params = malloc (*n_values * sizeof (pixman_fixed_t)); + params = _cairo_malloc (*n_values * sizeof (pixman_fixed_t)); if (!params) return 0; params[0] = pixman_int_to_fixed (xwidth); @@ -1077,11 +1077,11 @@ attach_proxy (cairo_surface_t *source, { struct proxy *proxy; - proxy = malloc (sizeof (*proxy)); + proxy = _cairo_malloc (sizeof (*proxy)); if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content); + _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content, FALSE); proxy->image = image; _cairo_surface_attach_snapshot (source, &proxy->base, NULL); @@ -1113,10 +1113,12 @@ _pixman_image_for_recording (cairo_image_surface_t *dst, { cairo_surface_t *source, *clone, *proxy; cairo_rectangle_int_t limit; + cairo_rectangle_int_t src_limit; pixman_image_t *pixman_image; cairo_status_t status; cairo_extend_t extend; cairo_matrix_t *m, matrix; + double sx = 1.0, sy = 1.0; int tx = 0, ty = 0; TRACE ((stderr, "%s\n", __FUNCTION__)); @@ -1124,34 +1126,38 @@ _pixman_image_for_recording (cairo_image_surface_t *dst, *ix = *iy = 0; source = _cairo_pattern_get_source (pattern, &limit); + src_limit = limit; extend = pattern->base.extend; if (_cairo_rectangle_contains_rectangle (&limit, sample)) extend = CAIRO_EXTEND_NONE; + if (extend == CAIRO_EXTEND_NONE) { if (! _cairo_rectangle_intersect (&limit, sample)) return _pixman_transparent_image (); + } - if (! _cairo_matrix_is_identity (&pattern->base.matrix)) { - double x1, y1, x2, y2; - - matrix = pattern->base.matrix; - status = cairo_matrix_invert (&matrix); - assert (status == CAIRO_STATUS_SUCCESS); - - x1 = limit.x; - y1 = limit.y; - x2 = limit.x + limit.width; - y2 = limit.y + limit.height; - - _cairo_matrix_transform_bounding_box (&matrix, - &x1, &y1, &x2, &y2, NULL); + if (! _cairo_matrix_is_identity (&pattern->base.matrix)) { + double x1, y1, x2, y2; - limit.x = floor (x1); - limit.y = floor (y1); - limit.width = ceil (x2) - limit.x; - limit.height = ceil (y2) - limit.y; - } + matrix = pattern->base.matrix; + status = cairo_matrix_invert (&matrix); + assert (status == CAIRO_STATUS_SUCCESS); + + x1 = limit.x; + y1 = limit.y; + x2 = limit.x + limit.width; + y2 = limit.y + limit.height; + + _cairo_matrix_transform_bounding_box (&matrix, + &x1, &y1, &x2, &y2, NULL); + + limit.x = floor (x1); + limit.y = floor (y1); + limit.width = ceil (x2) - limit.x; + limit.height = ceil (y2) - limit.y; + sx = (double)src_limit.width / limit.width; + sy = (double)src_limit.height / limit.height; } tx = limit.x; ty = limit.y; @@ -1183,7 +1189,9 @@ _pixman_image_for_recording (cairo_image_surface_t *dst, cairo_matrix_translate (&matrix, tx, ty); m = &matrix; } else { - /* XXX extract scale factor for repeating patterns */ + cairo_matrix_init_scale (&matrix, sx, sy); + cairo_matrix_translate (&matrix, src_limit.x/sx, src_limit.y/sy); + m = &matrix; } /* Handle recursion by returning future reads from the current image */ @@ -1199,11 +1207,22 @@ done: pixman_image = pixman_image_ref (((cairo_image_surface_t *)clone)->pixman_image); cairo_surface_destroy (clone); - *ix = -limit.x; - *iy = -limit.y; - if (extend != CAIRO_EXTEND_NONE) { + if (extend == CAIRO_EXTEND_NONE) { + *ix = -limit.x; + *iy = -limit.y; + } else { + cairo_pattern_union_t tmp_pattern; + _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base); + matrix = pattern->base.matrix; + status = cairo_matrix_invert(&matrix); + assert (status == CAIRO_STATUS_SUCCESS); + cairo_matrix_translate (&matrix, src_limit.x, src_limit.y); + cairo_matrix_scale (&matrix, sx, sy); + status = cairo_matrix_invert(&matrix); + assert (status == CAIRO_STATUS_SUCCESS); + cairo_pattern_set_matrix (&tmp_pattern.base, &matrix); if (! _pixman_image_set_properties (pixman_image, - &pattern->base, extents, + &tmp_pattern.base, extents, ix, iy)) { pixman_image_unref (pixman_image); pixman_image= NULL; @@ -1388,7 +1407,7 @@ _pixman_image_for_surface (cairo_image_surface_t *dst, return NULL; } - cleanup = malloc (sizeof (*cleanup)); + cleanup = _cairo_malloc (sizeof (*cleanup)); if (unlikely (cleanup == NULL)) { _cairo_surface_release_source_image (pattern->surface, image, extra); pixman_image_unref (pixman_image); @@ -1479,7 +1498,7 @@ _pixman_image_for_raster (cairo_image_surface_t *dst, return NULL; } - cleanup = malloc (sizeof (*cleanup)); + cleanup = _cairo_malloc (sizeof (*cleanup)); if (unlikely (cleanup == NULL)) { pixman_image_unref (pixman_image); _cairo_surface_release_source_image (surface, image, extra); @@ -1575,7 +1594,7 @@ _cairo_image_source_create_for_pattern (cairo_surface_t *dst, TRACE ((stderr, "%s\n", __FUNCTION__)); - source = malloc (sizeof (cairo_image_source_t)); + source = _cairo_malloc (sizeof (cairo_image_source_t)); if (unlikely (source == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1592,7 +1611,8 @@ _cairo_image_source_create_for_pattern (cairo_surface_t *dst, _cairo_surface_init (&source->base, &_cairo_image_source_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + FALSE); /* is_vector */ source->is_opaque_solid = pattern == NULL || _cairo_pattern_is_opaque_solid (pattern); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-image-surface-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-image-surface-private.h index 8ca694c5e3e..2b7921133f7 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-image-surface-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-image-surface-private.h @@ -40,6 +40,7 @@ #include "cairo-surface-private.h" +#include #include CAIRO_BEGIN_DECLS @@ -71,7 +72,7 @@ struct _cairo_image_surface { int width; int height; - int stride; + ptrdiff_t stride; int depth; unsigned owns_data : 1; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-image-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-image-surface.c index 1fd563d1c34..2ee1cad42cf 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-image-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-image-surface.c @@ -52,6 +52,7 @@ #include "cairo-recording-surface-private.h" #include "cairo-region-private.h" #include "cairo-scaled-font-private.h" +#include "cairo-surface-snapshot-inline.h" #include "cairo-surface-snapshot-private.h" #include "cairo-surface-subsurface-private.h" @@ -181,14 +182,15 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, { cairo_image_surface_t *surface; - surface = malloc (sizeof (cairo_image_surface_t)); + surface = _cairo_malloc (sizeof (cairo_image_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &_cairo_image_surface_backend, NULL, /* device */ - _cairo_content_from_pixman_format (pixman_format)); + _cairo_content_from_pixman_format (pixman_format), + FALSE); /* is_vector */ _cairo_image_surface_init (surface, pixman_image, pixman_format); @@ -369,8 +371,8 @@ _cairo_image_surface_create_with_pixman_format (unsigned char *data, * @height: height of the surface, in pixels * * Creates an image surface of the specified format and - * dimensions. Initially the surface contents are all - * 0. (Specifically, within each pixel, each color or alpha channel + * dimensions. Initially the surface contents are set to 0. + * (Specifically, within each pixel, each color or alpha channel * belonging to format will be 0. The contents of bits within a pixel, * but not belonging to the given format are undefined). * @@ -1152,79 +1154,87 @@ cleanup: return (cairo_image_surface_t *) _cairo_surface_create_in_error (status); } -cairo_image_transparency_t -_cairo_image_analyze_transparency (cairo_image_surface_t *image) +static cairo_image_transparency_t +_cairo_image_compute_transparency (cairo_image_surface_t *image) { int x, y; - - if (image->transparency != CAIRO_IMAGE_UNKNOWN) - return image->transparency; + cairo_image_transparency_t transparency; if ((image->base.content & CAIRO_CONTENT_ALPHA) == 0) - return image->transparency = CAIRO_IMAGE_IS_OPAQUE; + return CAIRO_IMAGE_IS_OPAQUE; if (image->base.is_clear) - return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA; + return CAIRO_IMAGE_HAS_BILEVEL_ALPHA; if ((image->base.content & CAIRO_CONTENT_COLOR) == 0) { if (image->format == CAIRO_FORMAT_A1) { - return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA; + return CAIRO_IMAGE_HAS_BILEVEL_ALPHA; } else if (image->format == CAIRO_FORMAT_A8) { for (y = 0; y < image->height; y++) { uint8_t *alpha = (uint8_t *) (image->data + y * image->stride); for (x = 0; x < image->width; x++, alpha++) { if (*alpha > 0 && *alpha < 255) - return image->transparency = CAIRO_IMAGE_HAS_ALPHA; + return CAIRO_IMAGE_HAS_ALPHA; } } - return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA; + return CAIRO_IMAGE_HAS_BILEVEL_ALPHA; } else { - return image->transparency = CAIRO_IMAGE_HAS_ALPHA; + return CAIRO_IMAGE_HAS_ALPHA; } } if (image->format == CAIRO_FORMAT_RGB16_565) { - image->transparency = CAIRO_IMAGE_IS_OPAQUE; return CAIRO_IMAGE_IS_OPAQUE; } if (image->format != CAIRO_FORMAT_ARGB32) - return image->transparency = CAIRO_IMAGE_HAS_ALPHA; + return CAIRO_IMAGE_HAS_ALPHA; - image->transparency = CAIRO_IMAGE_IS_OPAQUE; + transparency = CAIRO_IMAGE_IS_OPAQUE; for (y = 0; y < image->height; y++) { uint32_t *pixel = (uint32_t *) (image->data + y * image->stride); for (x = 0; x < image->width; x++, pixel++) { int a = (*pixel & 0xff000000) >> 24; if (a > 0 && a < 255) { - return image->transparency = CAIRO_IMAGE_HAS_ALPHA; + return CAIRO_IMAGE_HAS_ALPHA; } else if (a == 0) { - image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA; + transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA; } } } - return image->transparency; + return transparency; } -cairo_image_color_t -_cairo_image_analyze_color (cairo_image_surface_t *image) +cairo_image_transparency_t +_cairo_image_analyze_transparency (cairo_image_surface_t *image) { - int x, y; + if (_cairo_surface_is_snapshot (&image->base)) { + if (image->transparency == CAIRO_IMAGE_UNKNOWN) + image->transparency = _cairo_image_compute_transparency (image); - if (image->color != CAIRO_IMAGE_UNKNOWN_COLOR) - return image->color; + return image->transparency; + } + + return _cairo_image_compute_transparency (image); +} + +static cairo_image_color_t +_cairo_image_compute_color (cairo_image_surface_t *image) +{ + int x, y; + cairo_image_color_t color; if (image->format == CAIRO_FORMAT_A1) - return image->color = CAIRO_IMAGE_IS_MONOCHROME; + return CAIRO_IMAGE_IS_MONOCHROME; if (image->format == CAIRO_FORMAT_A8) - return image->color = CAIRO_IMAGE_IS_GRAYSCALE; + return CAIRO_IMAGE_IS_GRAYSCALE; if (image->format == CAIRO_FORMAT_ARGB32) { - image->color = CAIRO_IMAGE_IS_MONOCHROME; + color = CAIRO_IMAGE_IS_MONOCHROME; for (y = 0; y < image->height; y++) { uint32_t *pixel = (uint32_t *) (image->data + y * image->stride); @@ -1241,16 +1251,16 @@ _cairo_image_analyze_color (cairo_image_surface_t *image) b = (b * 255 + a / 2) / a; } if (!(r == g && g == b)) - return image->color = CAIRO_IMAGE_IS_COLOR; + return CAIRO_IMAGE_IS_COLOR; else if (r > 0 && r < 255) - image->color = CAIRO_IMAGE_IS_GRAYSCALE; + color = CAIRO_IMAGE_IS_GRAYSCALE; } } - return image->color; + return color; } if (image->format == CAIRO_FORMAT_RGB24) { - image->color = CAIRO_IMAGE_IS_MONOCHROME; + color = CAIRO_IMAGE_IS_MONOCHROME; for (y = 0; y < image->height; y++) { uint32_t *pixel = (uint32_t *) (image->data + y * image->stride); @@ -1259,15 +1269,28 @@ _cairo_image_analyze_color (cairo_image_surface_t *image) int g = (*pixel & 0x0000ff00) >> 8; int b = (*pixel & 0x000000ff); if (!(r == g && g == b)) - return image->color = CAIRO_IMAGE_IS_COLOR; + return CAIRO_IMAGE_IS_COLOR; else if (r > 0 && r < 255) - image->color = CAIRO_IMAGE_IS_GRAYSCALE; + color = CAIRO_IMAGE_IS_GRAYSCALE; } } + return color; + } + + return CAIRO_IMAGE_IS_COLOR; +} + +cairo_image_color_t +_cairo_image_analyze_color (cairo_image_surface_t *image) +{ + if (_cairo_surface_is_snapshot (&image->base)) { + if (image->color == CAIRO_IMAGE_UNKNOWN_COLOR) + image->color = _cairo_image_compute_color (image); + return image->color; } - return image->color = CAIRO_IMAGE_IS_COLOR; + return _cairo_image_compute_color (image); } cairo_image_surface_t * diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-line.c b/Build/source/libs/cairo/cairo-src/src/cairo-line.c index cb13927bdce..dc00a9cb19d 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-line.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-line.c @@ -110,9 +110,9 @@ lines_compare_x_for_y_general (const cairo_line_t *a, * should prevent that before the tessellation algorithm * begins. */ - int32_t dx; - int32_t adx, ady; - int32_t bdx, bdy; + int32_t dx = 0; + int32_t adx = 0, ady = 0; + int32_t bdx = 0, bdy = 0; enum { HAVE_NONE = 0x0, HAVE_DX = 0x1, @@ -218,7 +218,7 @@ lines_compare_x_for_y (const cairo_line_t *a, HAVE_BX = 0x2, HAVE_BOTH = HAVE_AX | HAVE_BX } have_ax_bx = HAVE_BOTH; - int32_t ax, bx; + int32_t ax = 0, bx = 0; if (y == a->p1.y) ax = a->p1.x; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-lzw.c b/Build/source/libs/cairo/cairo-src/src/cairo-lzw.c index de7f9998376..f27b3c33842 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-lzw.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-lzw.c @@ -73,7 +73,7 @@ _lzw_buf_init (lzw_buf_t *buf, int size) buf->pending = 0; buf->pending_bits = 0; - buf->data = malloc (size); + buf->data = _cairo_malloc (size); if (unlikely (buf->data == NULL)) { buf->data_size = 0; buf->status = _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-malloc-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-malloc-private.h index 1e2c67f8d9a..570f7cb0ee7 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-malloc-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-malloc-private.h @@ -60,7 +60,7 @@ **/ #define _cairo_malloc(size) \ - ((size) ? malloc((unsigned) (size)) : NULL) + ((size) > 0 ? malloc((unsigned) (size)) : NULL) /** * _cairo_malloc_ab: diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-matrix.c b/Build/source/libs/cairo/cairo-src/src/cairo-matrix.c index ae498f5151a..f3cf684c9d6 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-matrix.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-matrix.c @@ -40,12 +40,6 @@ #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */ -#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) -#define ISFINITE(x) isfinite (x) -#else -#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */ -#endif - /** * SECTION:cairo-matrix * @Title: cairo_matrix_t diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-mempool.c b/Build/source/libs/cairo/cairo-src/src/cairo-mempool.c index 751ede320f3..ce40ce521ff 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-mempool.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-mempool.c @@ -316,7 +316,7 @@ _cairo_mempool_init (cairo_mempool_t *pool, for (i = 0; i < ARRAY_LENGTH (pool->free); i++) cairo_list_init (&pool->free[i]); - pool->map = malloc ((num_blocks + 7) >> 3); + pool->map = _cairo_malloc ((num_blocks + 7) >> 3); if (pool->map == NULL) { free (pool->blocks); return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-mesh-pattern-rasterizer.c b/Build/source/libs/cairo/cairo-src/src/cairo-mesh-pattern-rasterizer.c index 1b63ca8a660..e7f0db666ae 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-mesh-pattern-rasterizer.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-mesh-pattern-rasterizer.c @@ -470,7 +470,7 @@ draw_pixel (unsigned char *data, int width, int height, int stride, tg += tg >> 16; tb += tb >> 16; - *((uint32_t*) (data + y*stride + 4*x)) = ((ta << 16) & 0xff000000) | + *((uint32_t*) (data + y*(ptrdiff_t)stride + 4*x)) = ((ta << 16) & 0xff000000) | ((tr >> 8) & 0xff0000) | ((tg >> 16) & 0xff00) | (tb >> 24); } } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-misc.c b/Build/source/libs/cairo/cairo-src/src/cairo-misc.c index 3c7c959862d..6e63bc7e6ea 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-misc.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-misc.c @@ -41,6 +41,13 @@ #include "cairoint.h" #include "cairo-error-private.h" +#include +#include +#include +#ifdef HAVE_XLOCALE_H +#include +#endif + COMPILE_TIME_ASSERT ((int)CAIRO_STATUS_LAST_STATUS < (int)CAIRO_INT_STATUS_UNSUPPORTED); COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127); @@ -49,7 +56,7 @@ COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127); * @Title: Error handling * @Short_Description: Decoding cairo's status * @See_Also: cairo_status(), cairo_surface_status(), cairo_pattern_status(), - * cairo_font_face_status(), cairo_scaled_font_status(), + * cairo_font_face_status(), cairo_scaled_font_status(), * cairo_region_status() * * Cairo uses a single status type to represent all kinds of errors. A status @@ -158,6 +165,14 @@ cairo_status_to_string (cairo_status_t status) return "the target device has been finished"; case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: return "CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID used but no CAIRO_MIME_TYPE_JBIG2_GLOBAL data provided"; + case CAIRO_STATUS_PNG_ERROR: + return "error occurred in libpng while reading from or writing to a PNG file"; + case CAIRO_STATUS_FREETYPE_ERROR: + return "error occurred in libfreetype"; + case CAIRO_STATUS_WIN32_GDI_ERROR: + return "error occurred in the Windows Graphics Device Interface"; + case CAIRO_STATUS_TAG_ERROR: + return "invalid tag name, attributes, or nesting"; default: case CAIRO_STATUS_LAST_STATUS: return ""; @@ -763,7 +778,7 @@ _cairo_half_from_float (float f) # include const char * -cairo_get_locale_decimal_point (void) +_cairo_get_locale_decimal_point (void) { struct lconv *locale_data = localeconv (); return locale_data->decimal_point; @@ -772,12 +787,160 @@ cairo_get_locale_decimal_point (void) #else /* Android's Bionic libc doesn't provide decimal_point */ const char * -cairo_get_locale_decimal_point (void) +_cairo_get_locale_decimal_point (void) { return "."; } #endif +#if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L) + +static locale_t C_locale; + +static locale_t +get_C_locale (void) +{ + locale_t C; + +retry: + C = (locale_t) _cairo_atomic_ptr_get ((void **) &C_locale); + + if (unlikely (!C)) { + C = newlocale (LC_ALL_MASK, "C", NULL); + + if (!_cairo_atomic_ptr_cmpxchg ((void **) &C_locale, NULL, C)) { + freelocale (C_locale); + goto retry; + } + } + + return C; +} + +double +_cairo_strtod (const char *nptr, char **endptr) +{ + return strtod_l (nptr, endptr, get_C_locale ()); +} + +#else + +/* strtod replacement that ignores locale and only accepts decimal points */ +double +_cairo_strtod (const char *nptr, char **endptr) +{ + const char *decimal_point; + int decimal_point_len; + const char *p; + char buf[100]; + char *bufptr; + char *bufend = buf + sizeof(buf) - 1; + double value; + char *end; + int delta; + cairo_bool_t have_dp; + + decimal_point = _cairo_get_locale_decimal_point (); + decimal_point_len = strlen (decimal_point); + assert (decimal_point_len != 0); + + p = nptr; + bufptr = buf; + delta = 0; + have_dp = FALSE; + while (*p && _cairo_isspace (*p)) { + p++; + delta++; + } + + while (*p && (bufptr + decimal_point_len < bufend)) { + if (_cairo_isdigit (*p)) { + *bufptr++ = *p; + } else if (*p == '.') { + if (have_dp) + break; + strncpy (bufptr, decimal_point, decimal_point_len); + bufptr += decimal_point_len; + delta -= decimal_point_len - 1; + have_dp = TRUE; + } else { + break; + } + p++; + } + *bufptr = 0; + + value = strtod (buf, &end); + if (endptr) { + if (end == buf) + *endptr = (char*)(nptr); + else + *endptr = (char*)(nptr + (end - buf) + delta); + } + + return value; +} +#endif + +/** + * _cairo_fopen: + * @filename: filename to open + * @mode: mode string with which to open the file + * @file_out: reference to file handle + * + * Exactly like the C library function, but possibly doing encoding + * conversion on the filename. On all platforms, the filename is + * passed directly to the system, but on Windows, the filename is + * interpreted as UTF-8, rather than in a codepage that would depend + * on system settings. + * + * Return value: CAIRO_STATUS_SUCCESS when the filename was converted + * successfully to the native encoding, or the error reported by + * _cairo_utf8_to_utf16 otherwise. To check if the file handle could + * be obtained, dereference file_out and compare its value against + * NULL + **/ +cairo_status_t +_cairo_fopen (const char *filename, const char *mode, FILE **file_out) +{ + FILE *result; +#ifdef _WIN32 /* also defined on x86_64 */ + uint16_t *filename_w; + uint16_t *mode_w; + cairo_status_t status; + + *file_out = NULL; + + if (filename == NULL || mode == NULL) { + errno = EINVAL; + return CAIRO_STATUS_SUCCESS; + } + + if ((status = _cairo_utf8_to_utf16 (filename, -1, &filename_w, NULL)) != CAIRO_STATUS_SUCCESS) { + errno = EINVAL; + return status; + } + + if ((status = _cairo_utf8_to_utf16 (mode, -1, &mode_w, NULL)) != CAIRO_STATUS_SUCCESS) { + free (filename_w); + errno = EINVAL; + return status; + } + + result = _wfopen(filename_w, mode_w); + + free (filename_w); + free (mode_w); + +#else /* Use fopen directly */ + result = fopen (filename, mode); +#endif + + *file_out = result; + + return CAIRO_STATUS_SUCCESS; +} + #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -854,13 +1017,13 @@ typedef struct _cairo_intern_string { static cairo_hash_table_t *_cairo_intern_string_ht; -static unsigned long -_intern_string_hash (const char *str, int len) +unsigned long +_cairo_string_hash (const char *str, int len) { const signed char *p = (const signed char *) str; unsigned int h = *p; - for (p += 1; --len; p++) + for (p += 1; len > 0; len--, p++) h = (h << 5) - h + *p; return h; @@ -890,7 +1053,7 @@ _cairo_intern_string (const char **str_inout, int len) if (len < 0) len = strlen (str); - tmpl.hash_entry.hash = _intern_string_hash (str, len); + tmpl.hash_entry.hash = _cairo_string_hash (str, len); tmpl.len = len; tmpl.string = (char *) str; @@ -906,7 +1069,7 @@ _cairo_intern_string (const char **str_inout, int len) istring = _cairo_hash_table_lookup (_cairo_intern_string_ht, &tmpl.hash_entry); if (istring == NULL) { - istring = malloc (sizeof (cairo_intern_string_t) + len + 1); + istring = _cairo_malloc (sizeof (cairo_intern_string_t) + len + 1); if (likely (istring != NULL)) { istring->hash_entry.hash = tmpl.hash_entry.hash; istring->len = tmpl.len; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-mono-scan-converter.c b/Build/source/libs/cairo/cairo-src/src/cairo-mono-scan-converter.c index 2a9546cf82a..891f435c9eb 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-mono-scan-converter.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-mono-scan-converter.c @@ -587,7 +587,7 @@ _cairo_mono_scan_converter_create (int xmin, cairo_mono_scan_converter_t *self; cairo_status_t status; - self = malloc (sizeof(struct _cairo_mono_scan_converter)); + self = _cairo_malloc (sizeof(struct _cairo_mono_scan_converter)); if (unlikely (self == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto bail_nomem; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-os2-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-os2-surface.c index 1ab50f97798..84f08c8077f 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-os2-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-os2-surface.c @@ -198,7 +198,7 @@ void *_buffer_alloc (size_t a, size_t b, const unsigned int size) return NULL; #else /* Clear the malloc'd buffer the way DosAllocMem() does. */ - buffer = malloc (nbytes); + buffer = _cairo_malloc (nbytes); if (buffer) { memset (buffer, 0, nbytes); } @@ -718,7 +718,7 @@ cairo_os2_surface_create (HPS hps_client_window, } /* Allocate an OS/2 surface structure. */ - local_os2_surface = (cairo_os2_surface_t *) malloc (sizeof (cairo_os2_surface_t)); + local_os2_surface = (cairo_os2_surface_t *) _cairo_malloc (sizeof (cairo_os2_surface_t)); if (!local_os2_surface) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto error_exit; @@ -780,7 +780,8 @@ cairo_os2_surface_create (HPS hps_client_window, _cairo_surface_init (&local_os2_surface->base, &cairo_os2_surface_backend, NULL, /* device */ - _cairo_content_from_format (CAIRO_FORMAT_ARGB32)); + _cairo_content_from_format (CAIRO_FORMAT_ARGB32), + FALSE); /* is_vector */ /* Successful exit */ return (cairo_surface_t *)local_os2_surface; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-output-stream.c b/Build/source/libs/cairo/cairo-src/src/cairo-output-stream.c index 05d9a2a005d..935fa44c332 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-output-stream.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-output-stream.c @@ -147,7 +147,7 @@ _cairo_output_stream_create (cairo_write_func_t write_func, { cairo_output_stream_with_closure_t *stream; - stream = malloc (sizeof (cairo_output_stream_with_closure_t)); + stream = _cairo_malloc (sizeof (cairo_output_stream_with_closure_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -173,7 +173,7 @@ _cairo_output_stream_create_in_error (cairo_status_t status) if (status == CAIRO_STATUS_WRITE_ERROR) return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; - stream = malloc (sizeof (cairo_output_stream_t)); + stream = _cairo_malloc (sizeof (cairo_output_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -293,7 +293,7 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream, /* Format a double in a locale independent way and trim trailing * zeros. Based on code from Alex Larson . - * http://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html + * https://mail.gnome.org/archives/gtk-devel-list/2001-October/msg00087.html * * The code in the patch is copyright Red Hat, Inc under the LGPL, but * has been relicensed under the LGPL/MPL dual license for inclusion @@ -312,7 +312,7 @@ _cairo_dtostr (char *buffer, size_t size, double d, cairo_bool_t limited_precisi if (d == 0.0) d = 0.0; - decimal_point = cairo_get_locale_decimal_point (); + decimal_point = _cairo_get_locale_decimal_point (); decimal_point_len = strlen (decimal_point); assert (decimal_point_len != 0); @@ -639,7 +639,7 @@ _cairo_output_stream_create_for_file (FILE *file) return (cairo_output_stream_t *) &_cairo_output_stream_nil_write_error; } - stream = malloc (sizeof *stream); + stream = _cairo_malloc (sizeof *stream); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -657,11 +657,16 @@ _cairo_output_stream_create_for_filename (const char *filename) { stdio_stream_t *stream; FILE *file; + cairo_status_t status; if (filename == NULL) return _cairo_null_stream_create (); - file = fopen (filename, "wb"); + status = _cairo_fopen (filename, "wb", &file); + + if (status != CAIRO_STATUS_SUCCESS) + return _cairo_output_stream_create_in_error (status); + if (file == NULL) { switch (errno) { case ENOMEM: @@ -673,7 +678,7 @@ _cairo_output_stream_create_for_filename (const char *filename) } } - stream = malloc (sizeof *stream); + stream = _cairo_malloc (sizeof *stream); if (unlikely (stream == NULL)) { fclose (file); _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); @@ -717,7 +722,7 @@ _cairo_memory_stream_create (void) { memory_stream_t *stream; - stream = malloc (sizeof *stream); + stream = _cairo_malloc (sizeof *stream); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -744,7 +749,7 @@ _cairo_memory_stream_destroy (cairo_output_stream_t *abstract_stream, stream = (memory_stream_t *) abstract_stream; *length_out = _cairo_array_num_elements (&stream->array); - *data_out = malloc (*length_out); + *data_out = _cairo_malloc (*length_out); if (unlikely (*data_out == NULL)) { status = _cairo_output_stream_destroy (abstract_stream); assert (status == CAIRO_STATUS_SUCCESS); @@ -794,7 +799,7 @@ _cairo_null_stream_create (void) { cairo_output_stream_t *stream; - stream = malloc (sizeof *stream); + stream = _cairo_malloc (sizeof *stream); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-paginated-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-paginated-private.h index b827faba0ef..b85a5db6b76 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-paginated-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-paginated-private.h @@ -56,7 +56,7 @@ struct _cairo_paginated_surface_backend { * CAIRO_PAGINATED_MODE_RENDER. See more details in the * documentation for _cairo_paginated_surface_create below. */ - void + cairo_warn cairo_int_status_t (*set_paginated_mode) (void *surface, cairo_paginated_mode_t mode); @@ -77,7 +77,23 @@ struct _cairo_paginated_surface_backend { cairo_bool_t fallbacks_required); cairo_bool_t - (*supports_fine_grained_fallbacks) (void *surface); + (*supports_fine_grained_fallbacks) (void *surface); + + /* Optional. Indicates whether the page requires a thumbnail image to be + * supplied. If a thumbnail is required, set width, heigh to size required + * and return TRUE. + */ + cairo_bool_t + (*requires_thumbnail_image) (void *surface, + int *width, + int *height); + + /* If thumbbail image requested, this function will be called before + * _show_page(). + */ + cairo_warn cairo_int_status_t + (*set_thumbnail_image) (void *surface, + cairo_image_surface_t *image); }; /* A #cairo_paginated_surface_t provides a very convenient wrapper that diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-paginated-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-paginated-surface.c index 68e4e0e34fd..fc16f790be8 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-paginated-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-paginated-surface.c @@ -98,7 +98,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target, cairo_paginated_surface_t *surface; cairo_status_t status; - surface = malloc (sizeof (cairo_paginated_surface_t)); + surface = _cairo_malloc (sizeof (cairo_paginated_surface_t)); if (unlikely (surface == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto FAIL; @@ -107,7 +107,8 @@ _cairo_paginated_surface_create (cairo_surface_t *target, _cairo_surface_init (&surface->base, &cairo_paginated_surface_backend, NULL, /* device */ - content); + content, + target->is_vector); /* Override surface->base.type with target's type so we don't leak * evidence of the paginated wrapper out to the user. */ @@ -289,6 +290,63 @@ _cairo_paginated_surface_release_source_image (void *abstract_surface, cairo_surface_destroy (&image->base); } +static cairo_int_status_t +_paint_thumbnail_image (cairo_paginated_surface_t *surface, + int width, + int height) +{ + cairo_surface_pattern_t pattern; + cairo_rectangle_int_t extents; + double x_scale; + double y_scale; + cairo_surface_t *image = NULL; + cairo_surface_t *opaque = NULL; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + + _cairo_surface_get_extents (surface->target, &extents); + x_scale = (double)width / extents.width; + y_scale = (double)height / extents.height; + + image = _cairo_paginated_surface_create_image_surface (surface, width, height); + cairo_surface_set_device_scale (image, x_scale, y_scale); + cairo_surface_set_device_offset (image, -extents.x*x_scale, -extents.y*y_scale); + status = _cairo_recording_surface_replay (surface->recording_surface, image); + if (unlikely (status)) + goto cleanup; + + /* flatten transparency */ + + opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); + if (unlikely (opaque->status)) { + status = opaque->status; + goto cleanup; + } + + status = _cairo_surface_paint (opaque, + CAIRO_OPERATOR_SOURCE, + &_cairo_pattern_white.base, + NULL); + if (unlikely (status)) + goto cleanup; + + _cairo_pattern_init_for_surface (&pattern, image); + pattern.base.filter = CAIRO_FILTER_NEAREST; + status = _cairo_surface_paint (opaque, CAIRO_OPERATOR_OVER, &pattern.base, NULL); + _cairo_pattern_fini (&pattern.base); + if (unlikely (status)) + goto cleanup; + + status = surface->backend->set_thumbnail_image (surface->target, (cairo_image_surface_t *)opaque); + + cleanup: + if (image) + cairo_surface_destroy (image); + if (opaque) + cairo_surface_destroy (opaque); + + return status; +} + static cairo_int_status_t _paint_fallback_image (cairo_paginated_surface_t *surface, cairo_rectangle_int_t *rect) @@ -351,10 +409,13 @@ _paint_page (cairo_paginated_surface_t *surface) if (unlikely (analysis->status)) return _cairo_surface_set_error (surface->target, analysis->status); - surface->backend->set_paginated_mode (surface->target, + status = surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_ANALYZE); + if (unlikely (status)) + goto FAIL; + status = _cairo_recording_surface_replay_and_create_regions (surface->recording_surface, - analysis); + NULL, analysis, FALSE); if (status) goto FAIL; @@ -400,8 +461,10 @@ _paint_page (cairo_paginated_surface_t *surface) } if (has_supported) { - surface->backend->set_paginated_mode (surface->target, - CAIRO_PAGINATED_MODE_RENDER); + status = surface->backend->set_paginated_mode (surface->target, + CAIRO_PAGINATED_MODE_RENDER); + if (unlikely (status)) + goto FAIL; status = _cairo_recording_surface_replay_region (surface->recording_surface, NULL, @@ -416,8 +479,10 @@ _paint_page (cairo_paginated_surface_t *surface) cairo_rectangle_int_t extents; cairo_bool_t is_bounded; - surface->backend->set_paginated_mode (surface->target, - CAIRO_PAGINATED_MODE_FALLBACK); + status = surface->backend->set_paginated_mode (surface->target, + CAIRO_PAGINATED_MODE_FALLBACK); + if (unlikely (status)) + goto FAIL; is_bounded = _cairo_surface_get_extents (surface->target, &extents); if (! is_bounded) { @@ -434,8 +499,10 @@ _paint_page (cairo_paginated_surface_t *surface) cairo_region_t *region; int num_rects, i; - surface->backend->set_paginated_mode (surface->target, + status = surface->backend->set_paginated_mode (surface->target, CAIRO_PAGINATED_MODE_FALLBACK); + if (unlikely (status)) + goto FAIL; region = _cairo_analysis_surface_get_unsupported (analysis); @@ -450,6 +517,13 @@ _paint_page (cairo_paginated_surface_t *surface) } } + if (surface->backend->requires_thumbnail_image) { + int width, height; + + if (surface->backend->requires_thumbnail_image (surface->target, &width, &height)) + _paint_thumbnail_image (surface, width, height); + } + FAIL: cairo_surface_destroy (analysis); @@ -659,6 +733,26 @@ _cairo_paginated_surface_get_supported_mime_types (void *abstract_surface) return NULL; } +static cairo_int_status_t +_cairo_paginated_surface_tag (void *abstract_surface, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip) +{ + cairo_paginated_surface_t *surface = abstract_surface; + + return _cairo_surface_tag (surface->recording_surface, + begin, tag_name, attributes, + source, style, + ctm, ctm_inverse, + clip); +} + static cairo_surface_t * _cairo_paginated_surface_snapshot (void *abstract_other) { @@ -713,4 +807,5 @@ static const cairo_surface_backend_t cairo_paginated_surface_backend = { _cairo_paginated_surface_has_show_text_glyphs, _cairo_paginated_surface_show_text_glyphs, _cairo_paginated_surface_get_supported_mime_types, + _cairo_paginated_surface_tag, }; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-path-bounds.c b/Build/source/libs/cairo/cairo-src/src/cairo-path-bounds.c index 9c7222426d3..ac85f27bee3 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-path-bounds.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-path-bounds.c @@ -154,6 +154,7 @@ void _cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, + cairo_bool_t is_vector, cairo_rectangle_int_t *extents) { if (path->has_extents) { @@ -161,6 +162,17 @@ _cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path, double dx, dy; _cairo_stroke_style_max_distance_from_path (style, path, ctm, &dx, &dy); + if (is_vector) + { + /* When calculating extents for vector surfaces, ensure lines thinner + * than the fixed point resolution are not optimized away. */ + double min = _cairo_fixed_to_double (CAIRO_FIXED_EPSILON*2); + if (dx < min) + dx = min; + + if (dy < min) + dy = min; + } box_extents = path->extents; box_extents.p1.x -= _cairo_fixed_from_double (dx); @@ -185,6 +197,17 @@ _cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path, { cairo_polygon_t polygon; cairo_status_t status; + cairo_stroke_style_t style; + + /* When calculating extents for vector surfaces, ensure lines thinner + * than one point are not optimized away. */ + double min_line_width = _cairo_matrix_transformed_circle_major_axis (ctm_inverse, 1.0); + if (stroke_style->line_width < min_line_width) + { + style = *stroke_style; + style.line_width = min_line_width; + stroke_style = &style; + } _cairo_polygon_init (&polygon, NULL, 0); status = _cairo_path_fixed_stroke_to_polygon (path, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-path-fixed.c b/Build/source/libs/cairo/cairo-src/src/cairo-path-fixed.c index 4bbf496f075..9e9166cbdaa 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-path-fixed.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-path-fixed.c @@ -325,7 +325,7 @@ _cairo_path_fixed_create (void) { cairo_path_fixed_t *path; - path = malloc (sizeof (cairo_path_fixed_t)); + path = _cairo_malloc (sizeof (cairo_path_fixed_t)); if (!path) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; @@ -347,7 +347,7 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path) _cairo_path_buf_destroy (this); } - VG (VALGRIND_MAKE_MEM_NOACCESS (path, sizeof (cairo_path_fixed_t))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (path, sizeof (cairo_path_fixed_t))); } void diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-path.c b/Build/source/libs/cairo/cairo-src/src/cairo-path.c index 43cd175a3c5..566e86f5a8e 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-path.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-path.c @@ -294,7 +294,7 @@ _cairo_path_create_in_error (cairo_status_t status) if (status == CAIRO_STATUS_NO_MEMORY) return (cairo_path_t*) &_cairo_path_nil; - path = malloc (sizeof (cairo_path_t)); + path = _cairo_malloc (sizeof (cairo_path_t)); if (unlikely (path == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_path_t*) &_cairo_path_nil; @@ -314,7 +314,7 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed, { cairo_path_t *path; - path = malloc (sizeof (cairo_path_t)); + path = _cairo_malloc (sizeof (cairo_path_t)); if (unlikely (path == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_path_t*) &_cairo_path_nil; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pattern-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-pattern-private.h index be8ab9fc239..26d584e686a 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-pattern-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pattern-private.h @@ -256,6 +256,11 @@ _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient, const cairo_rectangle_int_t *extents, cairo_color_t *color); +cairo_private cairo_bool_t +_cairo_pattern_is_constant_alpha (const cairo_pattern_t *abstract_pattern, + const cairo_rectangle_int_t *extents, + double *alpha); + cairo_private void _cairo_gradient_pattern_fit_to_range (const cairo_gradient_pattern_t *gradient, double max_value, @@ -296,7 +301,8 @@ _cairo_pattern_sampled_area (const cairo_pattern_t *pattern, cairo_private void _cairo_pattern_get_extents (const cairo_pattern_t *pattern, - cairo_rectangle_int_t *extents); + cairo_rectangle_int_t *extents, + cairo_bool_t is_vector); cairo_private cairo_int_status_t _cairo_pattern_get_ink_extents (const cairo_pattern_t *pattern, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pattern.c b/Build/source/libs/cairo/cairo-src/src/cairo-pattern.c index f0b879836df..fde044a4d1e 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-pattern.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pattern.c @@ -357,6 +357,7 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern, /* The reference count and user_data array are unique to the copy. */ CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0); _cairo_user_data_array_init (&pattern->user_data); + cairo_list_init (&pattern->observers); return CAIRO_STATUS_SUCCESS; } @@ -396,6 +397,7 @@ _cairo_pattern_init_static_copy (cairo_pattern_t *pattern, CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0); _cairo_user_data_array_init (&pattern->user_data); + cairo_list_init (&pattern->observers); } cairo_status_t @@ -464,19 +466,19 @@ _cairo_pattern_fini (cairo_pattern_t *pattern) #if HAVE_VALGRIND switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: - VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_solid_pattern_t)); + VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)); break; case CAIRO_PATTERN_TYPE_SURFACE: - VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_surface_pattern_t)); + VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)); break; case CAIRO_PATTERN_TYPE_LINEAR: - VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_linear_pattern_t)); + VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)); break; case CAIRO_PATTERN_TYPE_RADIAL: - VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_radial_pattern_t)); + VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t)); break; case CAIRO_PATTERN_TYPE_MESH: - VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_mesh_pattern_t)); + VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)); break; case CAIRO_PATTERN_TYPE_RASTER_SOURCE: break; @@ -496,22 +498,22 @@ _cairo_pattern_create_copy (cairo_pattern_t **pattern_out, switch (other->type) { case CAIRO_PATTERN_TYPE_SOLID: - pattern = malloc (sizeof (cairo_solid_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_solid_pattern_t)); break; case CAIRO_PATTERN_TYPE_SURFACE: - pattern = malloc (sizeof (cairo_surface_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_surface_pattern_t)); break; case CAIRO_PATTERN_TYPE_LINEAR: - pattern = malloc (sizeof (cairo_linear_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_linear_pattern_t)); break; case CAIRO_PATTERN_TYPE_RADIAL: - pattern = malloc (sizeof (cairo_radial_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_radial_pattern_t)); break; case CAIRO_PATTERN_TYPE_MESH: - pattern = malloc (sizeof (cairo_mesh_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_mesh_pattern_t)); break; case CAIRO_PATTERN_TYPE_RASTER_SOURCE: - pattern = malloc (sizeof (cairo_raster_source_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_raster_source_pattern_t)); break; default: ASSERT_NOT_REACHED; @@ -602,7 +604,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color) _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]); if (unlikely (pattern == NULL)) { /* None cached, need to create a new pattern. */ - pattern = malloc (sizeof (cairo_solid_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_solid_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *) &_cairo_pattern_nil; @@ -736,7 +738,7 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface) pattern = _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]); if (unlikely (pattern == NULL)) { - pattern = malloc (sizeof (cairo_surface_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_surface_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *)&_cairo_pattern_nil.base; @@ -788,7 +790,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1) pattern = _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]); if (unlikely (pattern == NULL)) { - pattern = malloc (sizeof (cairo_linear_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_linear_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *) &_cairo_pattern_nil.base; @@ -842,7 +844,7 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0, pattern = _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]); if (unlikely (pattern == NULL)) { - pattern = malloc (sizeof (cairo_radial_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_radial_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *) &_cairo_pattern_nil.base; @@ -1020,7 +1022,7 @@ cairo_pattern_create_mesh (void) pattern = _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_MESH]); if (unlikely (pattern == NULL)) { - pattern = malloc (sizeof (cairo_mesh_pattern_t)); + pattern = _cairo_malloc (sizeof (cairo_mesh_pattern_t)); if (unlikely (pattern == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_pattern_t *) &_cairo_pattern_nil.base; @@ -1045,8 +1047,8 @@ cairo_pattern_create_mesh (void) * @pattern from being destroyed until a matching call to * cairo_pattern_destroy() is made. * - * The number of references to a #cairo_pattern_t can be get using - * cairo_pattern_get_reference_count(). + * Use cairo_pattern_get_reference_count() to get the number of + * references to a #cairo_pattern_t. * * Return value: the referenced #cairo_pattern_t. * @@ -1071,8 +1073,8 @@ slim_hidden_def (cairo_pattern_reference); * cairo_pattern_get_type: * @pattern: a #cairo_pattern_t * - * This function returns the type a pattern. - * See #cairo_pattern_type_t for available types. + * Get the pattern's type. See #cairo_pattern_type_t for available + * types. * * Return value: The type of @pattern. * @@ -3132,6 +3134,59 @@ _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient, return TRUE; } +/** + * _cairo_pattern_is_constant_alpha: + * + * Convenience function to determine whether a pattern has constant + * alpha within the given extents. In this case the alpha argument is + * initialized to the alpha within the extents. + * + * Return value: %TRUE if the pattern has constant alpha. + **/ +cairo_bool_t +_cairo_pattern_is_constant_alpha (const cairo_pattern_t *abstract_pattern, + const cairo_rectangle_int_t *extents, + double *alpha) +{ + const cairo_pattern_union_t *pattern; + cairo_color_t color; + + if (_cairo_pattern_is_clear (abstract_pattern)) { + *alpha = 0.0; + return TRUE; + } + + if (_cairo_pattern_is_opaque (abstract_pattern, extents)) { + *alpha = 1.0; + return TRUE; + } + + pattern = (cairo_pattern_union_t *) abstract_pattern; + switch (pattern->base.type) { + case CAIRO_PATTERN_TYPE_SOLID: + *alpha = pattern->solid.color.alpha; + return TRUE; + + case CAIRO_PATTERN_TYPE_LINEAR: + case CAIRO_PATTERN_TYPE_RADIAL: + if (_cairo_gradient_pattern_is_solid (&pattern->gradient.base, extents, &color)) { + *alpha = color.alpha; + return TRUE; + } else { + return FALSE; + } + + /* TODO: need to test these as well */ + case CAIRO_PATTERN_TYPE_SURFACE: + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + case CAIRO_PATTERN_TYPE_MESH: + return FALSE; + } + + ASSERT_NOT_REACHED; + return FALSE; +} + static cairo_bool_t _mesh_is_clear (const cairo_mesh_pattern_t *mesh) { @@ -3522,13 +3577,17 @@ _cairo_pattern_sampled_area (const cairo_pattern_t *pattern, * For unbounded patterns, the @extents will be initialized with * "infinite" extents, (minimum and maximum fixed-point values). * + * When is_vector is TRUE, avoid rounding to zero widths or heights that + * are less than 1 unit. + * * XXX: Currently, bounded gradient patterns will also return * "infinite" extents, though it would be possible to optimize these * with a little more work. **/ void _cairo_pattern_get_extents (const cairo_pattern_t *pattern, - cairo_rectangle_int_t *extents) + cairo_rectangle_int_t *extents, + cairo_bool_t is_vector) { double x1, y1, x2, y2; int ix1, ix2, iy1, iy2; @@ -3731,6 +3790,8 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern, else ix2 = _cairo_lround (x2); extents->x = ix1; extents->width = ix2 - ix1; + if (is_vector && extents->width == 0 && x1 != x2) + extents->width += 1; if (!round_y) { y1 -= 0.5; @@ -3745,6 +3806,8 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern, else iy2 = _cairo_lround (y2); extents->y = iy1; extents->height = iy2 - iy1; + if (is_vector && extents->height == 0 && y1 != y2) + extents->height += 1; return; @@ -3796,7 +3859,7 @@ _cairo_pattern_get_ink_extents (const cairo_pattern_t *pattern, } } - _cairo_pattern_get_extents (pattern, extents); + _cairo_pattern_get_extents (pattern, extents, TRUE); return CAIRO_STATUS_SUCCESS; } @@ -4417,7 +4480,7 @@ cairo_mesh_pattern_get_path (cairo_pattern_t *pattern, patch = _cairo_array_index_const (&mesh->patches, patch_num); - path = malloc (sizeof (cairo_path_t)); + path = _cairo_malloc (sizeof (cairo_path_t)); if (path == NULL) return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -4607,7 +4670,36 @@ static void _cairo_debug_print_surface_pattern (FILE *file, const cairo_surface_pattern_t *pattern) { - printf (" surface type: %d\n", pattern->surface->type); + const char *s; + switch (pattern->surface->type) { + case CAIRO_SURFACE_TYPE_IMAGE: s = "image"; break; + case CAIRO_SURFACE_TYPE_PDF: s = "pdf"; break; + case CAIRO_SURFACE_TYPE_PS: s = "ps"; break; + case CAIRO_SURFACE_TYPE_XLIB: s = "xlib"; break; + case CAIRO_SURFACE_TYPE_XCB: s = "xcb"; break; + case CAIRO_SURFACE_TYPE_GLITZ: s = "glitz"; break; + case CAIRO_SURFACE_TYPE_QUARTZ: s = "quartz"; break; + case CAIRO_SURFACE_TYPE_WIN32: s = "win32"; break; + case CAIRO_SURFACE_TYPE_BEOS: s = "beos"; break; + case CAIRO_SURFACE_TYPE_DIRECTFB: s = "directfb"; break; + case CAIRO_SURFACE_TYPE_SVG: s = "svg"; break; + case CAIRO_SURFACE_TYPE_OS2: s = "os2"; break; + case CAIRO_SURFACE_TYPE_WIN32_PRINTING: s = "win32_printing"; break; + case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: s = "quartz_image"; break; + case CAIRO_SURFACE_TYPE_SCRIPT: s = "script"; break; + case CAIRO_SURFACE_TYPE_QT: s = "qt"; break; + case CAIRO_SURFACE_TYPE_RECORDING: s = "recording"; break; + case CAIRO_SURFACE_TYPE_VG: s = "vg"; break; + case CAIRO_SURFACE_TYPE_GL: s = "gl"; break; + case CAIRO_SURFACE_TYPE_DRM: s = "drm"; break; + case CAIRO_SURFACE_TYPE_TEE: s = "tee"; break; + case CAIRO_SURFACE_TYPE_XML: s = "xml"; break; + case CAIRO_SURFACE_TYPE_SKIA: s = "skia"; break; /* Deprecated */ + case CAIRO_SURFACE_TYPE_SUBSURFACE: s = "subsurface"; break; + case CAIRO_SURFACE_TYPE_COGL: s = "cogl"; break; + default: s = "invalid"; ASSERT_NOT_REACHED; break; + } + fprintf (file, " surface type: %s\n", s); } static void diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-interchange.c b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-interchange.c new file mode 100644 index 00000000000..7d8981b0927 --- /dev/null +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-interchange.c @@ -0,0 +1,1728 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2016 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 the cairo graphics library. + * + * The Initial Developer of the Original Code is Adrian Johnson. + * + * Contributor(s): + * Adrian Johnson + */ + + +/* PDF Document Interchange features: + * - metadata + * - document outline + * - tagged pdf + * - hyperlinks + * - page labels + */ + +#define _DEFAULT_SOURCE /* for localtime_r(), gmtime_r(), snprintf(), strdup() */ +#include "cairoint.h" + +#include "cairo-pdf.h" +#include "cairo-pdf-surface-private.h" + +#include "cairo-array-private.h" +#include "cairo-error-private.h" +#include "cairo-output-stream-private.h" + +#include + +#ifndef HAVE_LOCALTIME_R +#define localtime_r(T, BUF) (*(BUF) = *localtime (T)) +#endif +#ifndef HAVE_GMTIME_R +#define gmtime_r(T, BUF) (*(BUF) = *gmtime (T)) +#endif + +static void +write_rect_to_pdf_quad_points (cairo_output_stream_t *stream, + const cairo_rectangle_t *rect, + double surface_height) +{ + _cairo_output_stream_printf (stream, + "%f %f %f %f %f %f %f %f", + rect->x, + surface_height - rect->y, + rect->x + rect->width, + surface_height - rect->y, + rect->x + rect->width, + surface_height - (rect->y + rect->height), + rect->x, + surface_height - (rect->y + rect->height)); +} + +static void +write_rect_int_to_pdf_bbox (cairo_output_stream_t *stream, + const cairo_rectangle_int_t *rect, + double surface_height) +{ + _cairo_output_stream_printf (stream, + "%d %f %d %f", + rect->x, + surface_height - (rect->y + rect->height), + rect->x + rect->width, + surface_height - rect->y); +} + +static cairo_int_status_t +add_tree_node (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *parent, + const char *name, + cairo_pdf_struct_tree_node_t **new_node) +{ + cairo_pdf_struct_tree_node_t *node; + + node = _cairo_malloc (sizeof(cairo_pdf_struct_tree_node_t)); + if (unlikely (node == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + node->name = strdup (name); + node->res = _cairo_pdf_surface_new_object (surface); + if (node->res.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + node->parent = parent; + cairo_list_init (&node->children); + _cairo_array_init (&node->mcid, sizeof(struct page_mcid)); + node->annot_res.id = 0; + node->extents.valid = FALSE; + cairo_list_init (&node->extents.link); + + cairo_list_add_tail (&node->link, &parent->children); + + *new_node = node; + return CAIRO_STATUS_SUCCESS; +} + +static cairo_bool_t +is_leaf_node (cairo_pdf_struct_tree_node_t *node) +{ + return node->parent && cairo_list_is_empty (&node->children) ; +} + +static void +free_node (cairo_pdf_struct_tree_node_t *node) +{ + cairo_pdf_struct_tree_node_t *child, *next; + + if (!node) + return; + + cairo_list_foreach_entry_safe (child, next, cairo_pdf_struct_tree_node_t, + &node->children, link) + { + cairo_list_del (&child->link); + free_node (child); + } + free (node->name); + _cairo_array_fini (&node->mcid); + free (node); +} + +static cairo_status_t +add_mcid_to_node (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node, + int page, + int *mcid) +{ + struct page_mcid mcid_elem; + cairo_int_status_t status; + cairo_pdf_interchange_t *ic = &surface->interchange; + + status = _cairo_array_append (&ic->mcid_to_tree, &node); + if (unlikely (status)) + return status; + + mcid_elem.page = page; + mcid_elem.mcid = _cairo_array_num_elements (&ic->mcid_to_tree) - 1; + *mcid = mcid_elem.mcid; + return _cairo_array_append (&node->mcid, &mcid_elem); +} + +static cairo_int_status_t +add_annotation (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node, + const char *name, + const char *attributes) +{ + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_annotation_t *annot; + + annot = malloc (sizeof(cairo_pdf_annotation_t)); + if (unlikely (annot == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + status = _cairo_tag_parse_link_attributes (attributes, &annot->link_attrs); + if (unlikely (status)) { + free (annot); + return status; + } + + annot->node = node; + + status = _cairo_array_append (&ic->annots, &annot); + + return status; +} + +static void +free_annotation (cairo_pdf_annotation_t *annot) +{ + _cairo_array_fini (&annot->link_attrs.rects); + free (annot->link_attrs.dest); + free (annot->link_attrs.uri); + free (annot->link_attrs.file); + free (annot); +} + +static void +cairo_pdf_interchange_clear_annotations (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + int num_elems, i; + + num_elems = _cairo_array_num_elements (&ic->annots); + for (i = 0; i < num_elems; i++) { + cairo_pdf_annotation_t * annot; + + _cairo_array_copy_element (&ic->annots, i, &annot); + free_annotation (annot); + } + _cairo_array_truncate (&ic->annots, 0); +} + +static cairo_int_status_t +cairo_pdf_interchange_write_node_object (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node) +{ + struct page_mcid *mcid_elem; + int i, num_mcid, first_page; + cairo_pdf_resource_t *page_res; + cairo_pdf_struct_tree_node_t *child; + + _cairo_pdf_surface_update_object (surface, node->res); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Type /StructElem\n" + " /S /%s\n" + " /P %d 0 R\n", + node->res.id, + node->name, + node->parent->res.id); + + if (! cairo_list_is_empty (&node->children)) { + if (cairo_list_is_singular (&node->children) && node->annot_res.id == 0) { + child = cairo_list_first_entry (&node->children, cairo_pdf_struct_tree_node_t, link); + _cairo_output_stream_printf (surface->output, " /K %d 0 R\n", child->res.id); + } else { + _cairo_output_stream_printf (surface->output, " /K [ "); + if (node->annot_res.id != 0) { + _cairo_output_stream_printf (surface->output, + "<< /Type /OBJR /Obj %d 0 R >> ", + node->annot_res.id); + } + cairo_list_foreach_entry (child, cairo_pdf_struct_tree_node_t, + &node->children, link) + { + _cairo_output_stream_printf (surface->output, "%d 0 R ", child->res.id); + } + _cairo_output_stream_printf (surface->output, "]\n"); + } + } else { + num_mcid = _cairo_array_num_elements (&node->mcid); + if (num_mcid > 0 ) { + mcid_elem = _cairo_array_index (&node->mcid, 0); + first_page = mcid_elem->page; + page_res = _cairo_array_index (&surface->pages, first_page - 1); + _cairo_output_stream_printf (surface->output, " /Pg %d 0 R\n", page_res->id); + + if (num_mcid == 1 && node->annot_res.id == 0) { + _cairo_output_stream_printf (surface->output, " /K %d\n", mcid_elem->mcid); + } else { + _cairo_output_stream_printf (surface->output, " /K [ "); + if (node->annot_res.id != 0) { + _cairo_output_stream_printf (surface->output, + "<< /Type /OBJR /Obj %d 0 R >> ", + node->annot_res.id); + } + for (i = 0; i < num_mcid; i++) { + mcid_elem = _cairo_array_index (&node->mcid, i); + page_res = _cairo_array_index (&surface->pages, mcid_elem->page - 1); + if (mcid_elem->page == first_page) { + _cairo_output_stream_printf (surface->output, "%d ", mcid_elem->mcid); + } else { + _cairo_output_stream_printf (surface->output, + "\n << /Type /MCR /Pg %d 0 R /MCID %d >> ", + page_res->id, + mcid_elem->mcid); + } + } + _cairo_output_stream_printf (surface->output, "]\n"); + } + } + } + _cairo_output_stream_printf (surface->output, + ">>\n" + "endobj\n"); + + return _cairo_output_stream_get_status (surface->output); +} + +static void +init_named_dest_key (cairo_pdf_named_dest_t *dest) +{ + dest->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE, + dest->attrs.name, + strlen (dest->attrs.name)); +} + +static cairo_bool_t +_named_dest_equal (const void *key_a, const void *key_b) +{ + const cairo_pdf_named_dest_t *a = key_a; + const cairo_pdf_named_dest_t *b = key_b; + + return strcmp (a->attrs.name, b->attrs.name) == 0; +} + +static void +_named_dest_pluck (void *entry, void *closure) +{ + cairo_pdf_named_dest_t *dest = entry; + cairo_hash_table_t *table = closure; + + _cairo_hash_table_remove (table, &dest->base); + free (dest->attrs.name); + free (dest); +} + +static cairo_int_status_t +cairo_pdf_interchange_write_explicit_dest (cairo_pdf_surface_t *surface, + int page, + cairo_bool_t has_pos, + double x, + double y) +{ + cairo_pdf_resource_t res; + double height; + + if (page < 1 || page > (int)_cairo_array_num_elements (&surface->pages)) + return CAIRO_INT_STATUS_TAG_ERROR; + + _cairo_array_copy_element (&surface->page_heights, page - 1, &height); + _cairo_array_copy_element (&surface->pages, page - 1, &res); + if (has_pos) { + _cairo_output_stream_printf (surface->output, + " /Dest [%d 0 R /XYZ %f %f 0]\n", + res.id, + x, + height - y); + } else { + _cairo_output_stream_printf (surface->output, + " /Dest [%d 0 R /XYZ null null 0]\n", + res.id); + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_dest (cairo_pdf_surface_t *surface, + cairo_link_attrs_t *link_attrs) +{ + cairo_int_status_t status; + cairo_pdf_interchange_t *ic = &surface->interchange; + char *dest = NULL; + + if (link_attrs->dest) { + cairo_pdf_named_dest_t key; + cairo_pdf_named_dest_t *named_dest; + + /* check if this is a link to an internal named dest */ + key.attrs.name = link_attrs->dest; + init_named_dest_key (&key); + named_dest = _cairo_hash_table_lookup (ic->named_dests, &key.base); + if (named_dest && named_dest->attrs.internal) { + /* if dests exists and has internal attribute, use a direct + * reference instead of the name */ + double x = 0; + double y = 0; + + if (named_dest->extents.valid) { + x = named_dest->extents.extents.x; + y = named_dest->extents.extents.y; + } + + if (named_dest->attrs.x_valid) + x = named_dest->attrs.x; + + if (named_dest->attrs.y_valid) + y = named_dest->attrs.y; + + status = cairo_pdf_interchange_write_explicit_dest (surface, + named_dest->page, + TRUE, + x, y); + return status; + } + } + + if (link_attrs->dest) { + status = _cairo_utf8_to_pdf_string (link_attrs->dest, &dest); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->output, + " /Dest %s\n", + dest); + free (dest); + } else { + status = cairo_pdf_interchange_write_explicit_dest (surface, + link_attrs->page, + link_attrs->has_pos, + link_attrs->pos.x, + link_attrs->pos.y); + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_link_action (cairo_pdf_surface_t *surface, + cairo_link_attrs_t *link_attrs) +{ + cairo_int_status_t status; + char *dest = NULL; + + if (link_attrs->link_type == TAG_LINK_DEST) { + status = cairo_pdf_interchange_write_dest (surface, link_attrs); + if (unlikely (status)) + return status; + + } else if (link_attrs->link_type == TAG_LINK_URI) { + _cairo_output_stream_printf (surface->output, + " /A <<\n" + " /Type /Action\n" + " /S /URI\n" + " /URI (%s)\n" + " >>\n", + link_attrs->uri); + } else if (link_attrs->link_type == TAG_LINK_FILE) { + _cairo_output_stream_printf (surface->output, + " /A <<\n" + " /Type /Action\n" + " /S /GoToR\n" + " /F (%s)\n", + link_attrs->file); + if (link_attrs->dest) { + status = _cairo_utf8_to_pdf_string (link_attrs->dest, &dest); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->output, + " /D %s\n", + dest); + free (dest); + } else { + if (link_attrs->has_pos) { + _cairo_output_stream_printf (surface->output, + " /D [%d %f %f 0]\n", + link_attrs->page, + link_attrs->pos.x, + link_attrs->pos.y); + } else { + _cairo_output_stream_printf (surface->output, + " /D [%d null null 0]\n", + link_attrs->page); + } + } + _cairo_output_stream_printf (surface->output, + " >>\n"); + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_annot (cairo_pdf_surface_t *surface, + cairo_pdf_annotation_t *annot) +{ + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_struct_tree_node_t *node = annot->node; + int sp; + int i, num_rects; + double height; + + num_rects = _cairo_array_num_elements (&annot->link_attrs.rects); + if (strcmp (node->name, CAIRO_TAG_LINK) == 0 && + annot->link_attrs.link_type != TAG_LINK_EMPTY && + (node->extents.valid || num_rects > 0)) + { + status = _cairo_array_append (&ic->parent_tree, &node->res); + if (unlikely (status)) + return status; + + sp = _cairo_array_num_elements (&ic->parent_tree) - 1; + + node->annot_res = _cairo_pdf_surface_new_object (surface); + + status = _cairo_array_append (&surface->page_annots, &node->annot_res); + if (unlikely (status)) + return status; + + _cairo_pdf_surface_update_object (surface, node->annot_res); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Type /Annot\n" + " /Subtype /Link\n" + " /StructParent %d\n", + node->annot_res.id, + sp); + + height = surface->height; + if (num_rects > 0) { + cairo_rectangle_int_t bbox_rect; + + _cairo_output_stream_printf (surface->output, + " /QuadPoints [ "); + for (i = 0; i < num_rects; i++) { + cairo_rectangle_t rectf; + cairo_rectangle_int_t recti; + + _cairo_array_copy_element (&annot->link_attrs.rects, i, &rectf); + _cairo_rectangle_int_from_double (&recti, &rectf); + if (i == 0) + bbox_rect = recti; + else + _cairo_rectangle_union (&bbox_rect, &recti); + + write_rect_to_pdf_quad_points (surface->output, &rectf, height); + _cairo_output_stream_printf (surface->output, " "); + } + _cairo_output_stream_printf (surface->output, + "]\n" + " /Rect [ "); + write_rect_int_to_pdf_bbox (surface->output, &bbox_rect, height); + _cairo_output_stream_printf (surface->output, " ]\n"); + } else { + _cairo_output_stream_printf (surface->output, + " /Rect [ "); + write_rect_int_to_pdf_bbox (surface->output, &node->extents.extents, height); + _cairo_output_stream_printf (surface->output, " ]\n"); + } + + status = cairo_pdf_interchange_write_link_action (surface, &annot->link_attrs); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->output, + " /BS << /W 0 >>" + ">>\n" + "endobj\n"); + + status = _cairo_output_stream_get_status (surface->output); + } + + return status; +} + +static cairo_int_status_t +cairo_pdf_interchange_walk_struct_tree (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node, + cairo_int_status_t (*func) (cairo_pdf_surface_t *surface, + cairo_pdf_struct_tree_node_t *node)) +{ + cairo_int_status_t status; + cairo_pdf_struct_tree_node_t *child; + + if (node->parent) { + status = func (surface, node); + if (unlikely (status)) + return status; + } + + cairo_list_foreach_entry (child, cairo_pdf_struct_tree_node_t, + &node->children, link) + { + status = cairo_pdf_interchange_walk_struct_tree (surface, child, func); + if (unlikely (status)) + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_struct_tree (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_struct_tree_node_t *child; + + if (cairo_list_is_empty (&ic->struct_root->children)) + return CAIRO_STATUS_SUCCESS; + + surface->struct_tree_root = _cairo_pdf_surface_new_object (surface); + ic->struct_root->res = surface->struct_tree_root; + + cairo_pdf_interchange_walk_struct_tree (surface, ic->struct_root, cairo_pdf_interchange_write_node_object); + + child = cairo_list_first_entry (&ic->struct_root->children, cairo_pdf_struct_tree_node_t, link); + _cairo_pdf_surface_update_object (surface, surface->struct_tree_root); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Type /StructTreeRoot\n" + " /ParentTree %d 0 R\n", + surface->struct_tree_root.id, + ic->parent_tree_res.id); + + if (cairo_list_is_singular (&ic->struct_root->children)) { + child = cairo_list_first_entry (&ic->struct_root->children, cairo_pdf_struct_tree_node_t, link); + _cairo_output_stream_printf (surface->output, " /K [ %d 0 R ]\n", child->res.id); + } else { + _cairo_output_stream_printf (surface->output, " /K [ "); + + cairo_list_foreach_entry (child, cairo_pdf_struct_tree_node_t, + &ic->struct_root->children, link) + { + _cairo_output_stream_printf (surface->output, "%d 0 R ", child->res.id); + } + _cairo_output_stream_printf (surface->output, "]\n"); + } + + _cairo_output_stream_printf (surface->output, + ">>\n" + "endobj\n"); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_page_annots (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + int num_elems, i; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + num_elems = _cairo_array_num_elements (&ic->annots); + for (i = 0; i < num_elems; i++) { + cairo_pdf_annotation_t * annot; + + _cairo_array_copy_element (&ic->annots, i, &annot); + status = cairo_pdf_interchange_write_annot (surface, annot); + if (unlikely (status)) + return status; + } + + return status; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_page_parent_elems (cairo_pdf_surface_t *surface) +{ + int num_elems, i; + cairo_pdf_struct_tree_node_t *node; + cairo_pdf_resource_t res; + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + surface->page_parent_tree = -1; + num_elems = _cairo_array_num_elements (&ic->mcid_to_tree); + if (num_elems > 0) { + res = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "[\n", + res.id); + for (i = 0; i < num_elems; i++) { + _cairo_array_copy_element (&ic->mcid_to_tree, i, &node); + _cairo_output_stream_printf (surface->output, " %d 0 R\n", node->res.id); + } + _cairo_output_stream_printf (surface->output, + "]\n" + "endobj\n"); + status = _cairo_array_append (&ic->parent_tree, &res); + surface->page_parent_tree = _cairo_array_num_elements (&ic->parent_tree) - 1; + } + + return status; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_parent_tree (cairo_pdf_surface_t *surface) +{ + int num_elems, i; + cairo_pdf_resource_t *res; + cairo_pdf_interchange_t *ic = &surface->interchange; + + num_elems = _cairo_array_num_elements (&ic->parent_tree); + if (num_elems > 0) { + ic->parent_tree_res = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Nums [\n", + ic->parent_tree_res.id); + for (i = 0; i < num_elems; i++) { + res = _cairo_array_index (&ic->parent_tree, i); + if (res->id) { + _cairo_output_stream_printf (surface->output, + " %d %d 0 R\n", + i, + res->id); + } + } + _cairo_output_stream_printf (surface->output, + " ]\n" + ">>\n" + "endobj\n"); + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_outline (cairo_pdf_surface_t *surface) +{ + int num_elems, i; + cairo_pdf_outline_entry_t *outline; + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status; + char *name = NULL; + + num_elems = _cairo_array_num_elements (&ic->outline); + if (num_elems < 2) + return CAIRO_INT_STATUS_SUCCESS; + + _cairo_array_copy_element (&ic->outline, 0, &outline); + outline->res = _cairo_pdf_surface_new_object (surface); + surface->outlines_dict_res = outline->res; + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Type /Outlines\n" + " /First %d 0 R\n" + " /Last %d 0 R\n" + " /Count %d\n" + ">>\n" + "endobj\n", + outline->res.id, + outline->first_child->res.id, + outline->last_child->res.id, + outline->count); + + for (i = 1; i < num_elems; i++) { + _cairo_array_copy_element (&ic->outline, i, &outline); + _cairo_pdf_surface_update_object (surface, outline->res); + + status = _cairo_utf8_to_pdf_string (outline->name, &name); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Title %s\n" + " /Parent %d 0 R\n", + outline->res.id, + name, + outline->parent->res.id); + free (name); + + if (outline->prev) { + _cairo_output_stream_printf (surface->output, + " /Prev %d 0 R\n", + outline->prev->res.id); + } + + if (outline->next) { + _cairo_output_stream_printf (surface->output, + " /Next %d 0 R\n", + outline->next->res.id); + } + + if (outline->first_child) { + _cairo_output_stream_printf (surface->output, + " /First %d 0 R\n" + " /Last %d 0 R\n" + " /Count %d\n", + outline->first_child->res.id, + outline->last_child->res.id, + outline->count); + } + + if (outline->flags) { + int flags = 0; + if (outline->flags & CAIRO_PDF_OUTLINE_FLAG_ITALIC) + flags |= 1; + if (outline->flags & CAIRO_PDF_OUTLINE_FLAG_BOLD) + flags |= 2; + _cairo_output_stream_printf (surface->output, + " /F %d\n", + flags); + } + + status = cairo_pdf_interchange_write_link_action (surface, &outline->link_attrs); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->output, + ">>\n" + "endobj\n"); + } + + return status; +} + +/* + * Split a page label into a text prefix and numeric suffix. Leading '0's are + * included in the prefix. eg + * "3" => NULL, 3 + * "cover" => "cover", 0 + * "A-2" => "A-", 2 + * "A-002" => "A-00", 2 + */ +static char * +split_label (const char* label, int *num) +{ + int len, i; + + *num = 0; + len = strlen (label); + if (len == 0) + return NULL; + + i = len; + while (i > 0 && _cairo_isdigit (label[i-1])) + i--; + + while (i < len && label[i] == '0') + i++; + + if (i < len) + sscanf (label + i, "%d", num); + + if (i > 0) { + char *s; + s = _cairo_malloc (i + 1); + if (!s) + return NULL; + + memcpy (s, label, i); + s[i] = 0; + return s; + } + + return NULL; +} + +/* strcmp that handles NULL arguments */ +static cairo_bool_t +strcmp_null (const char *s1, const char *s2) +{ + if (s1 && s2) + return strcmp (s1, s2) == 0; + + if (!s1 && !s2) + return TRUE; + + return FALSE; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_page_labels (cairo_pdf_surface_t *surface) +{ + int num_elems, i; + char *label; + char *prefix; + char *prev_prefix; + int num, prev_num; + cairo_int_status_t status; + cairo_bool_t has_labels; + + /* Check if any labels defined */ + num_elems = _cairo_array_num_elements (&surface->page_labels); + has_labels = FALSE; + for (i = 0; i < num_elems; i++) { + _cairo_array_copy_element (&surface->page_labels, i, &label); + if (label) { + has_labels = TRUE; + break; + } + } + + if (!has_labels) + return CAIRO_STATUS_SUCCESS; + + surface->page_labels_res = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Nums [\n", + surface->page_labels_res.id); + prefix = NULL; + prev_prefix = NULL; + num = 0; + prev_num = 0; + for (i = 0; i < num_elems; i++) { + _cairo_array_copy_element (&surface->page_labels, i, &label); + if (label) { + prefix = split_label (label, &num); + } else { + prefix = NULL; + num = i + 1; + } + + if (!strcmp_null (prefix, prev_prefix) || num != prev_num + 1) { + _cairo_output_stream_printf (surface->output, " %d << ", i); + + if (num) + _cairo_output_stream_printf (surface->output, "/S /D /St %d ", num); + + if (prefix) { + char *s; + status = _cairo_utf8_to_pdf_string (prefix, &s); + if (unlikely (status)) + return status; + + _cairo_output_stream_printf (surface->output, "/P %s ", s); + free (s); + } + + _cairo_output_stream_printf (surface->output, ">>\n"); + } + free (prev_prefix); + prev_prefix = prefix; + prefix = NULL; + prev_num = num; + } + free (prefix); + free (prev_prefix); + _cairo_output_stream_printf (surface->output, + " ]\n" + ">>\n" + "endobj\n"); + + return CAIRO_STATUS_SUCCESS; +} + +static void +_collect_dest (void *entry, void *closure) +{ + cairo_pdf_named_dest_t *dest = entry; + cairo_pdf_surface_t *surface = closure; + cairo_pdf_interchange_t *ic = &surface->interchange; + + ic->sorted_dests[ic->num_dests++] = dest; +} + +static int +_dest_compare (const void *a, const void *b) +{ + const cairo_pdf_named_dest_t * const *dest_a = a; + const cairo_pdf_named_dest_t * const *dest_b = b; + + return strcmp ((*dest_a)->attrs.name, (*dest_b)->attrs.name); +} + +static cairo_int_status_t +_cairo_pdf_interchange_write_document_dests (cairo_pdf_surface_t *surface) +{ + int i; + cairo_pdf_interchange_t *ic = &surface->interchange; + + if (ic->num_dests == 0) { + ic->dests_res.id = 0; + return CAIRO_STATUS_SUCCESS; + } + + ic->sorted_dests = calloc (ic->num_dests, sizeof (cairo_pdf_named_dest_t *)); + if (unlikely (ic->sorted_dests == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + ic->num_dests = 0; + _cairo_hash_table_foreach (ic->named_dests, _collect_dest, surface); + qsort (ic->sorted_dests, ic->num_dests, sizeof (cairo_pdf_named_dest_t *), _dest_compare); + + ic->dests_res = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Names [\n", + ic->dests_res.id); + for (i = 0; i < ic->num_dests; i++) { + cairo_pdf_named_dest_t *dest = ic->sorted_dests[i]; + cairo_pdf_resource_t page_res; + double x = 0; + double y = 0; + double height; + + if (dest->attrs.internal) + continue; + + if (dest->extents.valid) { + x = dest->extents.extents.x; + y = dest->extents.extents.y; + } + + if (dest->attrs.x_valid) + x = dest->attrs.x; + + if (dest->attrs.y_valid) + y = dest->attrs.y; + + _cairo_array_copy_element (&surface->pages, dest->page - 1, &page_res); + _cairo_array_copy_element (&surface->page_heights, dest->page - 1, &height); + _cairo_output_stream_printf (surface->output, + " (%s) [%d 0 R /XYZ %f %f 0]\n", + dest->attrs.name, + page_res.id, + x, + height - y); + } + _cairo_output_stream_printf (surface->output, + " ]\n" + ">>\n" + "endobj\n"); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_names_dict (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status; + + status = _cairo_pdf_interchange_write_document_dests (surface); + if (unlikely (status)) + return status; + + surface->names_dict_res.id = 0; + if (ic->dests_res.id != 0) { + surface->names_dict_res = _cairo_pdf_surface_new_object (surface); + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Dests %d 0 R >>\n" + "endobj\n", + surface->names_dict_res.id, + ic->dests_res.id); + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +cairo_pdf_interchange_write_docinfo (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + + surface->docinfo_res = _cairo_pdf_surface_new_object (surface); + if (surface->docinfo_res.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + _cairo_output_stream_printf (surface->output, + "%d 0 obj\n" + "<< /Producer (cairo %s (https://cairographics.org))\n", + surface->docinfo_res.id, + cairo_version_string ()); + + if (ic->docinfo.title) + _cairo_output_stream_printf (surface->output, " /Title %s\n", ic->docinfo.title); + + if (ic->docinfo.author) + _cairo_output_stream_printf (surface->output, " /Author %s\n", ic->docinfo.author); + + if (ic->docinfo.subject) + _cairo_output_stream_printf (surface->output, " /Subject %s\n", ic->docinfo.subject); + + if (ic->docinfo.keywords) + _cairo_output_stream_printf (surface->output, " /Keywords %s\n", ic->docinfo.keywords); + + if (ic->docinfo.creator) + _cairo_output_stream_printf (surface->output, " /Creator %s\n", ic->docinfo.creator); + + if (ic->docinfo.create_date) + _cairo_output_stream_printf (surface->output, " /CreationDate %s\n", ic->docinfo.create_date); + + if (ic->docinfo.mod_date) + _cairo_output_stream_printf (surface->output, " /ModDate %s\n", ic->docinfo.mod_date); + + _cairo_output_stream_printf (surface->output, + ">>\n" + "endobj\n"); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +_cairo_pdf_interchange_begin_structure_tag (cairo_pdf_surface_t *surface, + cairo_tag_type_t tag_type, + const char *name, + const char *attributes) +{ + int page_num, mcid; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_pdf_interchange_t *ic = &surface->interchange; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + status = add_tree_node (surface, ic->current_node, name, &ic->current_node); + if (unlikely (status)) + return status; + + _cairo_tag_stack_set_top_data (&ic->analysis_tag_stack, ic->current_node); + + if (tag_type & TAG_TYPE_LINK) { + status = add_annotation (surface, ic->current_node, name, attributes); + if (unlikely (status)) + return status; + + cairo_list_add_tail (&ic->current_node->extents.link, &ic->extents_list); + } + + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { + ic->current_node = _cairo_tag_stack_top_elem (&ic->render_tag_stack)->data; + assert (ic->current_node != NULL); + if (is_leaf_node (ic->current_node)) { + page_num = _cairo_array_num_elements (&surface->pages); + add_mcid_to_node (surface, ic->current_node, page_num, &mcid); + status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, name, mcid); + } + } + + return status; +} + +static cairo_int_status_t +_cairo_pdf_interchange_begin_dest_tag (cairo_pdf_surface_t *surface, + cairo_tag_type_t tag_type, + const char *name, + const char *attributes) +{ + cairo_pdf_named_dest_t *dest; + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + dest = calloc (1, sizeof (cairo_pdf_named_dest_t)); + if (unlikely (dest == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + status = _cairo_tag_parse_dest_attributes (attributes, &dest->attrs); + if (unlikely (status)) + return status; + + dest->page = _cairo_array_num_elements (&surface->pages); + init_named_dest_key (dest); + status = _cairo_hash_table_insert (ic->named_dests, &dest->base); + if (unlikely (status)) + return status; + + _cairo_tag_stack_set_top_data (&ic->analysis_tag_stack, dest); + cairo_list_add_tail (&dest->extents.link, &ic->extents_list); + ic->num_dests++; + } + + return status; +} + +cairo_int_status_t +_cairo_pdf_interchange_tag_begin (cairo_pdf_surface_t *surface, + const char *name, + const char *attributes) +{ + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_tag_type_t tag_type; + cairo_pdf_interchange_t *ic = &surface->interchange; + void *ptr; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + status = _cairo_tag_stack_push (&ic->analysis_tag_stack, name, attributes); + + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { + status = _cairo_tag_stack_push (&ic->render_tag_stack, name, attributes); + _cairo_array_copy_element (&ic->push_data, ic->push_data_index++, &ptr); + _cairo_tag_stack_set_top_data (&ic->render_tag_stack, ptr); + } + + if (unlikely (status)) + return status; + + tag_type = _cairo_tag_get_type (name); + if (tag_type & TAG_TYPE_STRUCTURE) { + status = _cairo_pdf_interchange_begin_structure_tag (surface, tag_type, name, attributes); + if (unlikely (status)) + return status; + } + + if (tag_type & TAG_TYPE_DEST) { + status = _cairo_pdf_interchange_begin_dest_tag (surface, tag_type, name, attributes); + if (unlikely (status)) + return status; + } + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + ptr = _cairo_tag_stack_top_elem (&ic->analysis_tag_stack)->data; + status = _cairo_array_append (&ic->push_data, &ptr); + } + + return status; +} + +static cairo_int_status_t +_cairo_pdf_interchange_end_structure_tag (cairo_pdf_surface_t *surface, + cairo_tag_type_t tag_type, + cairo_tag_stack_elem_t *elem) +{ + const cairo_pdf_struct_tree_node_t *node; + struct tag_extents *tag, *next; + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + assert (elem->data != NULL); + node = elem->data; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + if (tag_type & TAG_TYPE_LINK) { + cairo_list_foreach_entry_safe (tag, next, struct tag_extents, + &ic->extents_list, link) { + if (tag == &node->extents) { + cairo_list_del (&tag->link); + break; + } + } + } + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { + if (is_leaf_node (ic->current_node)) { + status = _cairo_pdf_operators_tag_end (&surface->pdf_operators); + if (unlikely (status)) + return status; + } + } + + ic->current_node = ic->current_node->parent; + assert (ic->current_node != NULL); + + return status; +} + +static cairo_int_status_t +_cairo_pdf_interchange_end_dest_tag (cairo_pdf_surface_t *surface, + cairo_tag_type_t tag_type, + cairo_tag_stack_elem_t *elem) +{ + struct tag_extents *tag, *next; + cairo_pdf_named_dest_t *dest; + cairo_pdf_interchange_t *ic = &surface->interchange; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + assert (elem->data != NULL); + dest = (cairo_pdf_named_dest_t *) elem->data; + cairo_list_foreach_entry_safe (tag, next, struct tag_extents, + &ic->extents_list, link) { + if (tag == &dest->extents) { + cairo_list_del (&tag->link); + break; + } + } + } + + return CAIRO_STATUS_SUCCESS; +} + +cairo_int_status_t +_cairo_pdf_interchange_tag_end (cairo_pdf_surface_t *surface, + const char *name) +{ + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_tag_type_t tag_type; + cairo_tag_stack_elem_t *elem; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) + status = _cairo_tag_stack_pop (&ic->analysis_tag_stack, name, &elem); + else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) + status = _cairo_tag_stack_pop (&ic->render_tag_stack, name, &elem); + + if (unlikely (status)) + return status; + + tag_type = _cairo_tag_get_type (name); + if (tag_type & TAG_TYPE_STRUCTURE) { + status = _cairo_pdf_interchange_end_structure_tag (surface, tag_type, elem); + if (unlikely (status)) + goto cleanup; + } + + if (tag_type & TAG_TYPE_DEST) { + status = _cairo_pdf_interchange_end_dest_tag (surface, tag_type, elem); + if (unlikely (status)) + goto cleanup; + } + + cleanup: + _cairo_tag_stack_free_elem (elem); + + return status; +} + +cairo_int_status_t +_cairo_pdf_interchange_add_operation_extents (cairo_pdf_surface_t *surface, + const cairo_rectangle_int_t *extents) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + struct tag_extents *tag; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + cairo_list_foreach_entry (tag, struct tag_extents, &ic->extents_list, link) { + if (tag->valid) { + _cairo_rectangle_union (&tag->extents, extents); + } else { + tag->extents = *extents; + tag->valid = TRUE; + } + } + } + + return CAIRO_STATUS_SUCCESS; +} + +cairo_int_status_t +_cairo_pdf_interchange_begin_page_content (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + int page_num, mcid; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { + _cairo_array_truncate (&ic->mcid_to_tree, 0); + _cairo_array_truncate (&ic->push_data, 0); + ic->begin_page_node = ic->current_node; + } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { + ic->push_data_index = 0; + ic->current_node = ic->begin_page_node; + if (ic->end_page_node && is_leaf_node (ic->end_page_node)) { + page_num = _cairo_array_num_elements (&surface->pages); + add_mcid_to_node (surface, ic->end_page_node, page_num, &mcid); + status = _cairo_pdf_operators_tag_begin (&surface->pdf_operators, + ic->end_page_node->name, + mcid); + } + } + + return status; +} + +cairo_int_status_t +_cairo_pdf_interchange_end_page_content (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { + ic->end_page_node = ic->current_node; + if (is_leaf_node (ic->current_node)) + status = _cairo_pdf_operators_tag_end (&surface->pdf_operators); + } + + return status; +} + +cairo_int_status_t +_cairo_pdf_interchange_write_page_objects (cairo_pdf_surface_t *surface) +{ + cairo_int_status_t status; + + status = cairo_pdf_interchange_write_page_annots (surface); + if (unlikely (status)) + return status; + + cairo_pdf_interchange_clear_annotations (surface); + + return cairo_pdf_interchange_write_page_parent_elems (surface); +} + +cairo_int_status_t +_cairo_pdf_interchange_write_document_objects (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_tag_stack_structure_type_t tag_type; + + tag_type = _cairo_tag_stack_get_structure_type (&ic->analysis_tag_stack); + if (tag_type == TAG_TREE_TYPE_TAGGED || tag_type == TAG_TREE_TYPE_STRUCTURE) { + + status = cairo_pdf_interchange_write_parent_tree (surface); + if (unlikely (status)) + return status; + + status = cairo_pdf_interchange_write_struct_tree (surface); + if (unlikely (status)) + return status; + + if (tag_type == TAG_TREE_TYPE_TAGGED) + surface->tagged = TRUE; + } + + status = cairo_pdf_interchange_write_outline (surface); + if (unlikely (status)) + return status; + + status = cairo_pdf_interchange_write_page_labels (surface); + if (unlikely (status)) + return status; + + status = cairo_pdf_interchange_write_names_dict (surface); + if (unlikely (status)) + return status; + + status = cairo_pdf_interchange_write_docinfo (surface); + + return status; +} + +static void +_cairo_pdf_interchange_set_create_date (cairo_pdf_surface_t *surface) +{ + time_t utc, local, offset; + struct tm tm_local, tm_utc; + char buf[50]; + int buf_size; + char *p; + cairo_pdf_interchange_t *ic = &surface->interchange; + + utc = time (NULL); + localtime_r (&utc, &tm_local); + strftime (buf, sizeof(buf), "(D:%Y%m%d%H%M%S", &tm_local); + + /* strftime "%z" is non standard and does not work on windows (it prints zone name, not offset). + * Calculate time zone offset by comparing local and utc time_t values for the same time. + */ + gmtime_r (&utc, &tm_utc); + tm_utc.tm_isdst = tm_local.tm_isdst; + local = mktime (&tm_utc); + offset = difftime (utc, local); + + if (offset == 0) { + strcat (buf, "Z"); + } else { + if (offset > 0) { + strcat (buf, "+"); + } else { + strcat (buf, "-"); + offset = -offset; + } + p = buf + strlen (buf); + buf_size = sizeof (buf) - strlen (buf); + snprintf (p, buf_size, "%02d'%02d", (int)(offset/3600), (int)(offset%3600)/60); + } + strcat (buf, ")"); + ic->docinfo.create_date = strdup (buf); +} + +cairo_int_status_t +_cairo_pdf_interchange_init (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_outline_entry_t *outline_root; + cairo_int_status_t status; + + _cairo_tag_stack_init (&ic->analysis_tag_stack); + _cairo_tag_stack_init (&ic->render_tag_stack); + _cairo_array_init (&ic->push_data, sizeof(void *)); + ic->struct_root = calloc (1, sizeof(cairo_pdf_struct_tree_node_t)); + if (unlikely (ic->struct_root == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + cairo_list_init (&ic->struct_root->children); + _cairo_array_init (&ic->struct_root->mcid, sizeof(struct page_mcid)); + ic->current_node = ic->struct_root; + ic->begin_page_node = NULL; + ic->end_page_node = NULL; + _cairo_array_init (&ic->parent_tree, sizeof(cairo_pdf_resource_t)); + _cairo_array_init (&ic->mcid_to_tree, sizeof(cairo_pdf_struct_tree_node_t *)); + _cairo_array_init (&ic->annots, sizeof(cairo_pdf_annotation_t *)); + ic->parent_tree_res.id = 0; + cairo_list_init (&ic->extents_list); + ic->named_dests = _cairo_hash_table_create (_named_dest_equal); + if (unlikely (ic->named_dests == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + ic->num_dests = 0; + ic->sorted_dests = NULL; + ic->dests_res.id = 0; + + _cairo_array_init (&ic->outline, sizeof(cairo_pdf_outline_entry_t *)); + outline_root = calloc (1, sizeof(cairo_pdf_outline_entry_t)); + if (unlikely (outline_root == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + memset (&ic->docinfo, 0, sizeof (ic->docinfo)); + _cairo_pdf_interchange_set_create_date (surface); + status = _cairo_array_append (&ic->outline, &outline_root); + + return status; +} + +static void +_cairo_pdf_interchange_free_outlines (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + int num_elems, i; + + num_elems = _cairo_array_num_elements (&ic->outline); + for (i = 0; i < num_elems; i++) { + cairo_pdf_outline_entry_t *outline; + + _cairo_array_copy_element (&ic->outline, i, &outline); + free (outline->name); + free (outline->link_attrs.dest); + free (outline->link_attrs.uri); + free (outline->link_attrs.file); + free (outline); + } + _cairo_array_fini (&ic->outline); +} + +cairo_int_status_t +_cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + + _cairo_tag_stack_fini (&ic->analysis_tag_stack); + _cairo_tag_stack_fini (&ic->render_tag_stack); + _cairo_array_fini (&ic->push_data); + free_node (ic->struct_root); + _cairo_array_fini (&ic->mcid_to_tree); + cairo_pdf_interchange_clear_annotations (surface); + _cairo_array_fini (&ic->annots); + _cairo_array_fini (&ic->parent_tree); + _cairo_hash_table_foreach (ic->named_dests, _named_dest_pluck, ic->named_dests); + _cairo_hash_table_destroy (ic->named_dests); + free (ic->sorted_dests); + _cairo_pdf_interchange_free_outlines (surface); + free (ic->docinfo.title); + free (ic->docinfo.author); + free (ic->docinfo.subject); + free (ic->docinfo.keywords); + free (ic->docinfo.creator); + free (ic->docinfo.create_date); + free (ic->docinfo.mod_date); + + return CAIRO_STATUS_SUCCESS; +} + +cairo_int_status_t +_cairo_pdf_interchange_add_outline (cairo_pdf_surface_t *surface, + int parent_id, + const char *name, + const char *link_attribs, + cairo_pdf_outline_flags_t flags, + int *id) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_pdf_outline_entry_t *outline; + cairo_pdf_outline_entry_t *parent; + cairo_int_status_t status; + + if (parent_id < 0 || parent_id >= (int)_cairo_array_num_elements (&ic->outline)) + return CAIRO_STATUS_SUCCESS; + + outline = _cairo_malloc (sizeof(cairo_pdf_outline_entry_t)); + if (unlikely (outline == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + status = _cairo_tag_parse_link_attributes (link_attribs, &outline->link_attrs); + if (unlikely (status)) { + free (outline); + return status; + } + + outline->res = _cairo_pdf_surface_new_object (surface); + if (outline->res.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + outline->name = strdup (name); + outline->flags = flags; + outline->count = 0; + + _cairo_array_copy_element (&ic->outline, parent_id, &parent); + + outline->parent = parent; + outline->first_child = NULL; + outline->last_child = NULL; + outline->next = NULL; + if (parent->last_child) { + parent->last_child->next = outline; + outline->prev = parent->last_child; + parent->last_child = outline; + } else { + parent->first_child = outline; + parent->last_child = outline; + outline->prev = NULL; + } + + *id = _cairo_array_num_elements (&ic->outline); + status = _cairo_array_append (&ic->outline, &outline); + if (unlikely (status)) + return status; + + /* Update Count */ + outline = outline->parent; + while (outline) { + if (outline->flags & CAIRO_PDF_OUTLINE_FLAG_OPEN) { + outline->count++; + } else { + outline->count--; + break; + } + outline = outline->parent; + } + + return CAIRO_STATUS_SUCCESS; +} + +/* + * Date must be in the following format: + * + * YYYY-MM-DDThh:mm:ss[Z+-]hh:mm + * + * Only the year is required. If a field is included all preceding + * fields must be included. + */ +static char * +iso8601_to_pdf_date_string (const char *iso) +{ + char buf[40]; + const char *p; + int i; + + /* Check that utf8 contains only the characters "0123456789-T:Z+" */ + p = iso; + while (*p) { + if (!_cairo_isdigit (*p) && *p != '-' && *p != 'T' && + *p != ':' && *p != 'Z' && *p != '+') + return NULL; + p++; + } + + p = iso; + strcpy (buf, "("); + + /* YYYY (required) */ + if (strlen (p) < 4) + return NULL; + + strncat (buf, p, 4); + p += 4; + + /* -MM, -DD, Thh, :mm, :ss */ + for (i = 0; i < 5; i++) { + if (strlen (p) < 3) + goto finish; + + strncat (buf, p + 1, 2); + p += 3; + } + + /* Z, +, - */ + if (strlen (p) < 1) + goto finish; + strncat (buf, p, 1); + p += 1; + + /* hh */ + if (strlen (p) < 2) + goto finish; + + strncat (buf, p, 2); + strcat (buf, "'"); + p += 2; + + /* :mm */ + if (strlen (p) < 3) + goto finish; + + strncat (buf, p + 1, 3); + + finish: + strcat (buf, ")"); + return strdup (buf); +} + +cairo_int_status_t +_cairo_pdf_interchange_set_metadata (cairo_pdf_surface_t *surface, + cairo_pdf_metadata_t metadata, + const char *utf8) +{ + cairo_pdf_interchange_t *ic = &surface->interchange; + cairo_status_t status; + char *s = NULL; + + if (utf8) { + if (metadata == CAIRO_PDF_METADATA_CREATE_DATE || + metadata == CAIRO_PDF_METADATA_MOD_DATE) { + s = iso8601_to_pdf_date_string (utf8); + } else { + status = _cairo_utf8_to_pdf_string (utf8, &s); + if (unlikely (status)) + return status; + } + } + + switch (metadata) { + case CAIRO_PDF_METADATA_TITLE: + free (ic->docinfo.title); + ic->docinfo.title = s; + break; + case CAIRO_PDF_METADATA_AUTHOR: + free (ic->docinfo.author); + ic->docinfo.author = s; + break; + case CAIRO_PDF_METADATA_SUBJECT: + free (ic->docinfo.subject); + ic->docinfo.subject = s; + break; + case CAIRO_PDF_METADATA_KEYWORDS: + free (ic->docinfo.keywords); + ic->docinfo.keywords = s; + break; + case CAIRO_PDF_METADATA_CREATOR: + free (ic->docinfo.creator); + ic->docinfo.creator = s; + break; + case CAIRO_PDF_METADATA_CREATE_DATE: + free (ic->docinfo.create_date); + ic->docinfo.create_date = s; + break; + case CAIRO_PDF_METADATA_MOD_DATE: + free (ic->docinfo.mod_date); + ic->docinfo.mod_date = s; + break; + } + + return CAIRO_STATUS_SUCCESS; +} diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-operators-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-operators-private.h index 4314a042e81..ed8be7f96e0 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-operators-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-operators-private.h @@ -173,4 +173,12 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font); +cairo_private cairo_int_status_t +_cairo_pdf_operators_tag_begin (cairo_pdf_operators_t *pdf_operators, + const char *tag_name, + int mcid); + +cairo_private cairo_int_status_t +_cairo_pdf_operators_tag_end (cairo_pdf_operators_t *pdf_operators); + #endif /* CAIRO_PDF_OPERATORS_H */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-operators.c b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-operators.c index c509ad00ee1..491ef8ca22f 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-operators.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-operators.c @@ -140,7 +140,7 @@ _cairo_pdf_operators_flush (cairo_pdf_operators_t *pdf_operators) * assumptions will be made about the state. The next time a * particular graphics state is required (eg line width) the state * operator is always emitted and then remembered for subsequent - * operatations. + * operations. * * This should be called when starting a new stream or after emitting * the 'Q' operator (where pdf-operators functions were called inside @@ -359,7 +359,7 @@ _word_wrap_stream_create (cairo_output_stream_t *output, cairo_bool_t ps, int ma if (output->status) return _cairo_output_stream_create_in_error (output->status); - stream = malloc (sizeof (word_wrap_stream_t)); + stream = _cairo_malloc (sizeof (word_wrap_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; @@ -1493,9 +1493,6 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, cairo_matrix_init_scale (&invert_y_axis, 1, -1); text_matrix = scaled_font->scale; - /* Invert y axis in font space */ - cairo_matrix_multiply (&text_matrix, &text_matrix, &invert_y_axis); - /* Invert y axis in device space */ cairo_matrix_multiply (&text_matrix, &invert_y_axis, &text_matrix); @@ -1558,4 +1555,41 @@ _cairo_pdf_operators_show_text_glyphs (cairo_pdf_operators_t *pdf_operators, return _cairo_output_stream_get_status (pdf_operators->stream); } +cairo_int_status_t +_cairo_pdf_operators_tag_begin (cairo_pdf_operators_t *pdf_operators, + const char *tag_name, + int mcid) +{ + cairo_status_t status; + + if (pdf_operators->in_text_object) { + status = _cairo_pdf_operators_end_text (pdf_operators); + if (unlikely (status)) + return status; + } + + _cairo_output_stream_printf (pdf_operators->stream, + "/%s << /MCID %d >> BDC\n", + tag_name, + mcid); + + return _cairo_output_stream_get_status (pdf_operators->stream); +} + +cairo_int_status_t +_cairo_pdf_operators_tag_end (cairo_pdf_operators_t *pdf_operators) +{ + cairo_status_t status; + + if (pdf_operators->in_text_object) { + status = _cairo_pdf_operators_end_text (pdf_operators); + if (unlikely (status)) + return status; + } + + _cairo_output_stream_printf (pdf_operators->stream, "EMC\n"); + + return _cairo_output_stream_get_status (pdf_operators->stream); +} + #endif /* CAIRO_HAS_PDF_OPERATORS */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-shading.c b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-shading.c index 646e2cd4902..b114b3104ba 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-shading.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-shading.c @@ -170,7 +170,7 @@ _cairo_pdf_shading_generate_data (cairo_pdf_shading_t *shading, * 4 colors. Each color is stored in 2 bytes * num_color_components. */ shading->data_length = num_patches * (1 + 16 * 2 * 4 + 4 * 2 * num_color_components); - shading->data = malloc (shading->data_length); + shading->data = _cairo_malloc (shading->data_length); if (unlikely (shading->data == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-surface-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-surface-private.h index 618ca4ede9f..3793332ce8c 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-surface-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-surface-private.h @@ -48,6 +48,8 @@ #include "cairo-surface-clipper-private.h" #include "cairo-pdf-operators-private.h" #include "cairo-path-fixed-private.h" +#include "cairo-tag-attributes-private.h" +#include "cairo-tag-stack-private.h" typedef struct _cairo_pdf_resource { unsigned int id; @@ -74,11 +76,19 @@ typedef struct _cairo_pdf_source_surface_entry { cairo_bool_t interpolate; cairo_bool_t stencil_mask; cairo_bool_t smask; + cairo_bool_t need_transp_group; cairo_pdf_resource_t surface_res; cairo_pdf_resource_t smask_res; - int width; - int height; + + /* True if surface will be emitted as an Image XObject. */ + cairo_bool_t emit_image; + + /* Extents of the source surface. */ + cairo_bool_t bounded; cairo_rectangle_int_t extents; + + /* Union of source extents required for all operations using this source */ + cairo_rectangle_int_t required_extents; } cairo_pdf_source_surface_entry_t; typedef struct _cairo_pdf_source_surface { @@ -97,6 +107,17 @@ typedef struct _cairo_pdf_pattern { cairo_pdf_resource_t gstate_res; cairo_operator_t operator; cairo_bool_t is_shading; + + /* PDF pattern space is the pattern matrix concatenated with the + * initial space of the parent object. If the parent object is the + * page, the initial space does not include the Y-axis flipping + * matrix emitted at the start of the page content stream. If the + * parent object is not the page content stream, the initial space + * will have a flipped Y-axis. The inverted_y_axis flag is true + * when the initial space of the parent object that is drawing + * this pattern has a flipped Y-axis. + */ + cairo_bool_t inverted_y_axis; } cairo_pdf_pattern_t; typedef enum _cairo_pdf_operation { @@ -138,6 +159,91 @@ typedef struct _cairo_pdf_jbig2_global { cairo_bool_t emitted; } cairo_pdf_jbig2_global_t; +/* cairo-pdf-interchange.c types */ + +struct page_mcid { + int page; + int mcid; +}; + +struct tag_extents { + cairo_rectangle_int_t extents; + cairo_bool_t valid; + cairo_list_t link; +}; + +typedef struct _cairo_pdf_struct_tree_node { + char *name; + cairo_pdf_resource_t res; + struct _cairo_pdf_struct_tree_node *parent; + cairo_list_t children; + cairo_array_t mcid; /* array of struct page_mcid */ + cairo_pdf_resource_t annot_res; /* 0 if no annot */ + struct tag_extents extents; + cairo_list_t link; +} cairo_pdf_struct_tree_node_t; + +typedef struct _cairo_pdf_annotation { + cairo_pdf_struct_tree_node_t *node; /* node containing the annotation */ + cairo_link_attrs_t link_attrs; +} cairo_pdf_annotation_t; + +typedef struct _cairo_pdf_named_dest { + cairo_hash_entry_t base; + struct tag_extents extents; + cairo_dest_attrs_t attrs; + int page; +} cairo_pdf_named_dest_t; + +typedef struct _cairo_pdf_outline_entry { + char *name; + cairo_link_attrs_t link_attrs; + cairo_pdf_outline_flags_t flags; + cairo_pdf_resource_t res; + struct _cairo_pdf_outline_entry *parent; + struct _cairo_pdf_outline_entry *first_child; + struct _cairo_pdf_outline_entry *last_child; + struct _cairo_pdf_outline_entry *next; + struct _cairo_pdf_outline_entry *prev; + int count; +} cairo_pdf_outline_entry_t; + +struct docinfo { + char *title; + char *author; + char *subject; + char *keywords; + char *creator; + char *create_date; + char *mod_date; +}; + +typedef struct _cairo_pdf_interchange { + cairo_tag_stack_t analysis_tag_stack; + cairo_tag_stack_t render_tag_stack; + cairo_array_t push_data; /* records analysis_tag_stack data field for each push */ + int push_data_index; + cairo_pdf_struct_tree_node_t *struct_root; + cairo_pdf_struct_tree_node_t *current_node; + cairo_pdf_struct_tree_node_t *begin_page_node; + cairo_pdf_struct_tree_node_t *end_page_node; + cairo_array_t parent_tree; /* parent tree resources */ + cairo_array_t mcid_to_tree; /* mcid to tree node mapping for current page */ + cairo_array_t annots; /* array of pointers to cairo_pdf_annotation_t */ + cairo_pdf_resource_t parent_tree_res; + cairo_list_t extents_list; + cairo_hash_table_t *named_dests; + int num_dests; + cairo_pdf_named_dest_t **sorted_dests; + cairo_pdf_resource_t dests_res; + int annot_page; + cairo_array_t outline; /* array of pointers to cairo_pdf_outline_entry_t; */ + struct docinfo docinfo; + +} cairo_pdf_interchange_t; + +/* pdf surface data */ + typedef struct _cairo_pdf_surface cairo_pdf_surface_t; struct _cairo_pdf_surface { @@ -149,7 +255,10 @@ struct _cairo_pdf_surface { double width; double height; + cairo_rectangle_int_t surface_extents; + cairo_bool_t surface_bounded; cairo_matrix_t cairo_to_pdf; + cairo_bool_t in_xobject; cairo_array_t objects; cairo_array_t pages; @@ -157,16 +266,19 @@ struct _cairo_pdf_surface { cairo_array_t alpha_linear_functions; cairo_array_t page_patterns; cairo_array_t page_surfaces; + cairo_array_t doc_surfaces; cairo_hash_table_t *all_surfaces; cairo_array_t smask_groups; cairo_array_t knockout_group; cairo_array_t jbig2_global; + cairo_array_t page_heights; cairo_scaled_font_subsets_t *font_subsets; cairo_array_t fonts; cairo_pdf_resource_t next_available_resource; cairo_pdf_resource_t pages_resource; + cairo_pdf_resource_t struct_tree_root; cairo_pdf_version_t pdf_version; cairo_bool_t compress_content; @@ -212,7 +324,76 @@ struct _cairo_pdf_surface { double current_color_blue; double current_color_alpha; + cairo_pdf_interchange_t interchange; + int page_parent_tree; /* -1 if not used */ + cairo_array_t page_annots; + cairo_bool_t tagged; + char *current_page_label; + cairo_array_t page_labels; + cairo_pdf_resource_t outlines_dict_res; + cairo_pdf_resource_t names_dict_res; + cairo_pdf_resource_t docinfo_res; + cairo_pdf_resource_t page_labels_res; + + int thumbnail_width; + int thumbnail_height; + cairo_image_surface_t *thumbnail_image; + cairo_surface_t *paginated_surface; }; +cairo_private cairo_pdf_resource_t +_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface); + +cairo_private void +_cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface, + cairo_pdf_resource_t resource); + +cairo_private cairo_int_status_t +_cairo_utf8_to_pdf_string (const char *utf8, char **str_out); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_init (cairo_pdf_surface_t *surface); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_fini (cairo_pdf_surface_t *surface); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_begin_page_content (cairo_pdf_surface_t *surface); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_end_page_content (cairo_pdf_surface_t *surface); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_tag_begin (cairo_pdf_surface_t *surface, + const char *name, + const char *attributes); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_tag_end (cairo_pdf_surface_t *surface, + const char *name); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_add_operation_extents (cairo_pdf_surface_t *surface, + const cairo_rectangle_int_t *extents); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_write_page_objects (cairo_pdf_surface_t *surface); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_write_document_objects (cairo_pdf_surface_t *surface); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_add_outline (cairo_pdf_surface_t *surface, + int parent_id, + const char *name, + const char *dest, + cairo_pdf_outline_flags_t flags, + int *id); + +cairo_private cairo_int_status_t +_cairo_pdf_interchange_set_metadata (cairo_pdf_surface_t *surface, + cairo_pdf_metadata_t metadata, + const char *utf8); + #endif /* CAIRO_PDF_SURFACE_PRIVATE_H */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-surface.c index fd7dc7d5606..7eb61aa1e05 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-pdf-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pdf-surface.c @@ -63,18 +63,8 @@ #include "cairo-surface-subsurface-private.h" #include "cairo-type3-glyph-surface-private.h" -#include #include -/* Issues: - * - * - We embed an image in the stream each time it's composited. We - * could add generation counters to surfaces and remember the stream - * ID for a particular generation for a particular surface. - * - * - Backend specific meta data. - */ - /* * Page Structure of the Generated PDF: * @@ -134,19 +124,62 @@ * The following mime types are supported: %CAIRO_MIME_TYPE_JPEG, * %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_UNIQUE_ID, * %CAIRO_MIME_TYPE_JBIG2, %CAIRO_MIME_TYPE_JBIG2_GLOBAL, - * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID. + * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID, + * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS. * + * # JBIG2 Images # * JBIG2 data in PDF must be in the embedded format as described in * ISO/IEC 11544. Image specific JBIG2 data must be in * %CAIRO_MIME_TYPE_JBIG2. Any global segments in the JBIG2 data * (segments with page association field set to 0) must be in * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data may be shared by * multiple images. All images sharing the same global data must set - * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID to a unique identifer. At least + * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID to a unique identifier. At least * one of the images must provide the global data using * %CAIRO_MIME_TYPE_JBIG2_GLOBAL. The global data will only be - * embedded once but shared by all JBIG2 images with the same + * embedded once and shared by all JBIG2 images with the same * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID. + * + * # CCITT Fax Images # {#ccitt} + * The %CAIRO_MIME_TYPE_CCITT_FAX mime data requires a number of decoding + * parameters These parameters are specified using %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS. + * + * %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS mime data must contain a string of the form + * "param1=value1 param2=value2 ...". + * + * @Columns: [required] An integer specifying the width of the image in pixels. + * + * @Rows: [required] An integer specifying the height of the image in scan lines. + * + * @K: [optional] An integer identifying the encoding scheme used. < 0 + * is 2 dimensional Group 4, = 0 is Group3 1 dimensional, > 0 is mixed 1 + * and 2 dimensional encoding. Default is 0. + * + * @EndOfLine: [optional] If true end-of-line bit patterns are present. Default is false. + * + * @EncodedByteAlign: [optional] If true the end of line is padded + * with 0 bits so the next line begins on a byte boundary. Default is false. + * + * @EndOfBlock: [optional] If true the data contains an end-of-block pattern. Default is true. + * + * @BlackIs1: [optional] If true 1 bits are black pixels. Default is false. + * + * @DamagedRowsBeforeError: [optional] An integer specifying the + * number of damages rows tolerated before an error occurs. Default is 0. + * + * Boolean values may be "true" or "false", or 1 or 0. + * + * These parameters are the same as the CCITTFaxDecode parameters in the + * [PostScript Language Reference](https://www.adobe.com/products/postscript/pdfs/PLRM.pdf) + * and [Portable Document Format (PDF)](https://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf). + * Refer to these documents for further details. + * + * An example %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS string is: + * + * + * "Columns=10230 Rows=40000 K=1 EndOfLine=true EncodedByteAlign=1 BlackIs1=false" + * + * **/ static cairo_bool_t @@ -184,6 +217,8 @@ static const char *_cairo_pdf_supported_mime_types[] = CAIRO_MIME_TYPE_JBIG2, CAIRO_MIME_TYPE_JBIG2_GLOBAL, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID, + CAIRO_MIME_TYPE_CCITT_FAX, + CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, NULL }; @@ -209,9 +244,6 @@ typedef struct _cairo_pdf_alpha_linear_function { double alpha2; } cairo_pdf_alpha_linear_function_t; -static cairo_pdf_resource_t -_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface); - static void _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface); @@ -235,21 +267,28 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface); +static cairo_int_status_t +_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface, + cairo_pdf_source_surface_t *source, + cairo_bool_t test, + cairo_bool_t *is_image); + static cairo_int_status_t _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface); static void _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface); -static cairo_pdf_resource_t -_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface); - static cairo_pdf_resource_t _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface); static long _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface); +static cairo_int_status_t +_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface, + cairo_bool_t finish); + static cairo_int_status_t _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface); @@ -262,7 +301,7 @@ _cairo_pdf_source_surface_equal (const void *key_a, const void *key_b); static const cairo_surface_backend_t cairo_pdf_surface_backend; static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend; -static cairo_pdf_resource_t +cairo_pdf_resource_t _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface) { cairo_pdf_resource_t resource; @@ -283,7 +322,7 @@ _cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface) return resource; } -static void +void _cairo_pdf_surface_update_object (cairo_pdf_surface_t *surface, cairo_pdf_resource_t resource) { @@ -300,9 +339,10 @@ _cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface, { surface->width = width; surface->height = height; - cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height); - _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, - &surface->cairo_to_pdf); + surface->surface_extents.x = 0; + surface->surface_extents.y = 0; + surface->surface_extents.width = ceil (surface->width); + surface->surface_extents.height = ceil (surface->height); } static cairo_bool_t @@ -357,7 +397,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, cairo_pdf_surface_t *surface; cairo_status_t status, status_ignored; - surface = malloc (sizeof (cairo_pdf_surface_t)); + surface = _cairo_malloc (sizeof (cairo_pdf_surface_t)); if (unlikely (surface == NULL)) { /* destroy stream on behalf of caller */ status = _cairo_output_stream_destroy (output); @@ -367,12 +407,19 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _cairo_surface_init (&surface->base, &cairo_pdf_surface_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + TRUE); /* is_vector */ surface->output = output; surface->width = width; surface->height = height; - cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, -1, 0, height); + cairo_matrix_init (&surface->cairo_to_pdf, 1, 0, 0, 1, 0, 0); + surface->in_xobject = FALSE; + surface->surface_extents.x = 0; + surface->surface_extents.y = 0; + surface->surface_extents.width = ceil (surface->width); + surface->surface_extents.height = ceil (surface->height); + surface->surface_bounded = TRUE; _cairo_array_init (&surface->objects, sizeof (cairo_pdf_object_t)); _cairo_array_init (&surface->pages, sizeof (cairo_pdf_resource_t)); @@ -384,7 +431,9 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, _cairo_array_init (&surface->page_patterns, sizeof (cairo_pdf_pattern_t)); _cairo_array_init (&surface->page_surfaces, sizeof (cairo_pdf_source_surface_t)); + _cairo_array_init (&surface->doc_surfaces, sizeof (cairo_pdf_source_surface_t)); _cairo_array_init (&surface->jbig2_global, sizeof (cairo_pdf_jbig2_global_t)); + _cairo_array_init (&surface->page_heights, sizeof (double)); surface->all_surfaces = _cairo_hash_table_create (_cairo_pdf_source_surface_equal); if (unlikely (surface->all_surfaces == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -408,6 +457,7 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, goto BAIL2; } + surface->struct_tree_root.id = 0; surface->pdf_version = CAIRO_PDF_VERSION_1_5; surface->compress_content = TRUE; surface->pdf_stream.active = FALSE; @@ -437,6 +487,26 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output, surface); _cairo_pdf_operators_enable_actual_text(&surface->pdf_operators, TRUE); + status = _cairo_pdf_interchange_init (surface); + if (unlikely (status)) + goto BAIL2; + + surface->page_parent_tree = -1; + _cairo_array_init (&surface->page_annots, sizeof (cairo_pdf_resource_t)); + surface->tagged = FALSE; + surface->current_page_label = NULL; + _cairo_array_init (&surface->page_labels, sizeof (char *)); + surface->outlines_dict_res.id = 0; + surface->names_dict_res.id = 0; + surface->docinfo_res.id = 0; + surface->page_labels_res.id = 0; + surface->thumbnail_width = 0; + surface->thumbnail_height = 0; + surface->thumbnail_image = NULL; + + if (getenv ("CAIRO_DEBUG_PDF") != NULL) + surface->compress_content = FALSE; + surface->paginated_surface = _cairo_paginated_surface_create ( &surface->base, CAIRO_CONTENT_COLOR_ALPHA, @@ -705,6 +775,143 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface, status = _cairo_surface_set_error (surface, status); } +/** + * CAIRO_PDF_OUTLINE_ROOT: + * + * The root outline item in cairo_pdf_surface_add_outline(). + * + * Since: 1.16 + **/ + +/** + * cairo_pdf_surface_add_outline: + * @surface: a PDF #cairo_surface_t + * @parent_id: the id of the parent item or %CAIRO_PDF_OUTLINE_ROOT if this is a top level item. + * @utf8: the name of the outline + * @link_attribs: the link attributes specifying where this outline links to + * @flags: outline item flags + * + * Add an item to the document outline hierarchy with the name @utf8 + * that links to the location specified by @link_attribs. Link + * attributes have the same keys and values as the [Link Tag][link], + * excluding the "rect" attribute. The item will be a child of the + * item with id @parent_id. Use %CAIRO_PDF_OUTLINE_ROOT as the parent + * id of top level items. + * + * Return value: the id for the added item. + * + * Since: 1.16 + **/ +int +cairo_pdf_surface_add_outline (cairo_surface_t *surface, + int parent_id, + const char *utf8, + const char *link_attribs, + cairo_pdf_outline_flags_t flags) +{ + cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */ + cairo_status_t status; + int id = 0; + + if (! _extract_pdf_surface (surface, &pdf_surface)) + return 0; + + status = _cairo_pdf_interchange_add_outline (pdf_surface, + parent_id, + utf8, + link_attribs, + flags, + &id); + if (status) + status = _cairo_surface_set_error (surface, status); + + return id; +} + +/** + * cairo_pdf_surface_set_metadata: + * @surface: a PDF #cairo_surface_t + * @metadata: The metadata item to set. + * @utf8: metadata value + * + * Set document metadata. The %CAIRO_PDF_METADATA_CREATE_DATE and + * %CAIRO_PDF_METADATA_MOD_DATE values must be in ISO-8601 format: + * YYYY-MM-DDThh:mm:ss. An optional timezone of the form "[+/-]hh:mm" + * or "Z" for UTC time can be appended. All other metadata values can be any UTF-8 + * string. + * + * For example: + * + * cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_TITLE, "My Document"); + * cairo_pdf_surface_set_metadata (surface, CAIRO_PDF_METADATA_CREATE_DATE, "2015-12-31T23:59+02:00"); + * + * + * Since: 1.16 + **/ +void +cairo_pdf_surface_set_metadata (cairo_surface_t *surface, + cairo_pdf_metadata_t metadata, + const char *utf8) +{ + cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */ + cairo_status_t status; + + if (! _extract_pdf_surface (surface, &pdf_surface)) + return; + + status = _cairo_pdf_interchange_set_metadata (pdf_surface, metadata, utf8); + if (status) + status = _cairo_surface_set_error (surface, status); +} + +/** + * cairo_pdf_surface_set_page_label: + * @surface: a PDF #cairo_surface_t + * @utf8: The page label. + * + * Set page label for the current page. + * + * Since: 1.16 + **/ +void +cairo_pdf_surface_set_page_label (cairo_surface_t *surface, + const char *utf8) +{ + cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */ + + if (! _extract_pdf_surface (surface, &pdf_surface)) + return; + + free (pdf_surface->current_page_label); + pdf_surface->current_page_label = utf8 ? strdup (utf8) : NULL; +} + +/** + * cairo_pdf_surface_set_thumbnail_size: + * @surface: a PDF #cairo_surface_t + * @width: Thumbnail width. + * @height: Thumbnail height + * + * Set the thumbnail image size for the current and all subsequent + * pages. Setting a width or height of 0 disables thumbnails for the + * current and subsequent pages. + * + * Since: 1.16 + **/ +void +cairo_pdf_surface_set_thumbnail_size (cairo_surface_t *surface, + int width, + int height) +{ + cairo_pdf_surface_t *pdf_surface = NULL; /* hide compiler warning */ + + if (! _extract_pdf_surface (surface, &pdf_surface)) + return; + + pdf_surface->thumbnail_width = width; + pdf_surface->thumbnail_height = height; +} + static void _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface) { @@ -734,6 +941,10 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface) } _cairo_array_truncate (&surface->smask_groups, 0); _cairo_array_truncate (&surface->knockout_group, 0); + _cairo_array_truncate (&surface->page_annots, 0); + + cairo_surface_destroy (&surface->thumbnail_image->base); + surface->thumbnail_image = NULL; } static void @@ -1080,7 +1291,6 @@ _cairo_pdf_surface_create_smask_group (cairo_pdf_surface_t *surface, group->extents.width = surface->width; group->extents.height = surface->height; } - group->extents = *extents; return group; } @@ -1196,186 +1406,105 @@ _cairo_pdf_surface_release_source_image_from_pattern (cairo_pdf_surface_t } static cairo_int_status_t -_get_jbig2_image_info (cairo_surface_t *source, - cairo_image_info_t *info, - const unsigned char **mime_data, - unsigned long *mime_data_length) -{ - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2, - mime_data, mime_data_length); - if (*mime_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_image_info_get_jbig2_info (info, *mime_data, *mime_data_length); -} - -static cairo_int_status_t -_get_jpx_image_info (cairo_surface_t *source, - cairo_image_info_t *info, - const unsigned char **mime_data, - unsigned long *mime_data_length) -{ - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JP2, - mime_data, mime_data_length); - if (*mime_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_image_info_get_jpx_info (info, *mime_data, *mime_data_length); -} - -static cairo_int_status_t -_get_jpeg_image_info (cairo_surface_t *source, - cairo_image_info_t *info, - const unsigned char **mime_data, - unsigned long *mime_data_length) -{ - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG, - mime_data, mime_data_length); - if (*mime_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return _cairo_image_info_get_jpeg_info (info, *mime_data, *mime_data_length); -} - -static cairo_int_status_t -_get_source_surface_size (cairo_surface_t *source, - int *width, - int *height, - cairo_rectangle_int_t *extents) +_get_source_surface_extents (cairo_surface_t *source, + cairo_rectangle_int_t *extents, + cairo_bool_t *bounded, + cairo_bool_t *subsurface) { cairo_int_status_t status; - cairo_image_info_t info; - const unsigned char *mime_data; - unsigned long mime_data_length; + *bounded = TRUE; + *subsurface = FALSE; if (source->type == CAIRO_SURFACE_TYPE_RECORDING) { + cairo_surface_t *free_me = NULL; + + if (_cairo_surface_is_snapshot (source)) + free_me = source = _cairo_surface_snapshot_get_target (source); + if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { - cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source; + cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source; - *extents = sub->extents; - *width = extents->width; - *height = extents->height; + *extents = sub->extents; + *subsurface = TRUE; } else { - cairo_surface_t *free_me = NULL; - cairo_rectangle_int_t surf_extents; cairo_box_t box; - cairo_bool_t bounded; - - if (_cairo_surface_is_snapshot (source)) - free_me = source = _cairo_surface_snapshot_get_target (source); - status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)source, - &box, NULL); - if (unlikely (status)) { - cairo_surface_destroy (free_me); - return status; + *bounded = _cairo_surface_get_extents (source, extents); + if (! *bounded) { + status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)source, + &box, NULL); + if (unlikely (status)) { + cairo_surface_destroy (free_me); + return status; + } + _cairo_box_round_to_rectangle (&box, extents); } - - bounded = _cairo_surface_get_extents (source, &surf_extents); - cairo_surface_destroy (free_me); - - *width = surf_extents.width; - *height = surf_extents.height; - - _cairo_box_round_to_rectangle (&box, extents); } - - return CAIRO_STATUS_SUCCESS; - } - - extents->x = 0; - extents->y = 0; - - status = _get_jbig2_image_info (source, &info, &mime_data, &mime_data_length); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) { - *width = info.width; - *height = info.height; - extents->width = info.width; - extents->height = info.height; - return status; - } - - status = _get_jpx_image_info (source, &info, &mime_data, &mime_data_length); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) { - *width = info.width; - *height = info.height; - extents->width = info.width; - extents->height = info.height; - return status; - } - - status = _get_jpeg_image_info (source, &info, &mime_data, &mime_data_length); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) { - *width = info.width; - *height = info.height; - extents->width = info.width; - extents->height = info.height; - return status; + cairo_surface_destroy (free_me); + } else { + *bounded = _cairo_surface_get_extents (source, extents); } - if (! _cairo_surface_get_extents (source, extents)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - *width = extents->width; - *height = extents->height; - return CAIRO_STATUS_SUCCESS; } /** * _cairo_pdf_surface_add_source_surface: - * @surface: the pdf surface - * @source_surface: A #cairo_surface_t to use as the source surface - * @source_pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source - * @op: the operator used to composite this source - * @filter: filter type of the source pattern - * @stencil_mask: if true, the surface will be written to the PDF as an /ImageMask - * @smask: if true, only the alpha channel will be written (images only) - * @extents: extents of the operation that is using this source - * @smask_res: if not NULL, the image written will specify this resource as the smask for the image (images only) - * @surface_res: return PDF resource number of the surface - * @width: returns width of surface - * @height: returns height of surface - * @x_offset: x offset of surface - * @t_offset: y offset of surface - * @source_extents: returns extents of source (either ink extents or extents needed to cover @extents) + * @surface: [in] the pdf surface + * @source_surface: [in] A #cairo_surface_t to use as the source surface + * @source_pattern: [in] A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source + * @op: [in] the operator used to composite this source + * @filter: [in] filter type of the source pattern + * @stencil_mask: [in] if true, the surface will be written to the PDF as an /ImageMask + * @smask: [in] if true, only the alpha channel will be written (images only) + * @need_transp_group: [in] if true and an XObject is used, make it a Transparency group + * @extents: [in] extents of the operation that is using this source + * @smask_res: [in] if not NULL, the image written will specify this resource as the smask for + * the image (images only) + * @pdf_source: [out] return pdf_source_surface entry in hash table + * @x_offset: [out] if not NULL return x offset of surface + * @y_offset: [out] if not NULL return y offset of surface + * @source_extents: [out] if not NULL return operation extents in source space * * Add surface or raster_source pattern to list of surfaces to be * written to the PDF file when the current page is finished. Returns - * a PDF resource to reference the image. A hash table of all images - * in the PDF files (keyed by CAIRO_MIME_TYPE_UNIQUE_ID or surface - * unique_id) to ensure surfaces with the same id are only written - * once to the PDF file. + * a PDF resource to reference the surface. A hash table of all + * surfaces in the PDF file (keyed by CAIRO_MIME_TYPE_UNIQUE_ID or + * surface unique_id) is used to ensure surfaces with the same id are + * only written once to the PDF file. * * Only one of @source_pattern or @source_surface is to be * specified. Set the other to NULL. **/ static cairo_int_status_t -_cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, - cairo_surface_t *source_surface, - const cairo_pattern_t *source_pattern, - cairo_operator_t op, - cairo_filter_t filter, - cairo_bool_t stencil_mask, - cairo_bool_t smask, - const cairo_rectangle_int_t *extents, - cairo_pdf_resource_t *smask_res, - cairo_pdf_resource_t *surface_res, - int *width, - int *height, - double *x_offset, - double *y_offset, - cairo_rectangle_int_t *source_extents) +_cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, + cairo_surface_t *source_surface, + const cairo_pattern_t *source_pattern, + cairo_operator_t op, + cairo_filter_t filter, + cairo_bool_t stencil_mask, + cairo_bool_t smask, + cairo_bool_t need_transp_group, + const cairo_rectangle_int_t *extents, + cairo_pdf_resource_t *smask_res, + cairo_pdf_source_surface_entry_t **pdf_source, + double *x_offset, + double *y_offset, + cairo_rectangle_int_t *source_extents) { cairo_pdf_source_surface_t src_surface; cairo_pdf_source_surface_entry_t surface_key; cairo_pdf_source_surface_entry_t *surface_entry; - cairo_int_status_t status; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_bool_t interpolate; unsigned char *unique_id = NULL; unsigned long unique_id_length = 0; cairo_image_surface_t *image; void *image_extra; + cairo_box_t box; + cairo_rectangle_int_t op_extents; + double x, y; + cairo_bool_t subsurface; switch (filter) { default: @@ -1391,8 +1520,8 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, break; } - *x_offset = 0; - *y_offset = 0; + x = 0; + y = 0; if (source_pattern) { if (source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) { status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source_pattern, @@ -1400,12 +1529,27 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, if (unlikely (status)) return status; source_surface = &image->base; - cairo_surface_get_device_offset (source_surface, x_offset, y_offset); + cairo_surface_get_device_offset (source_surface, &x, &y); } else { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) source_pattern; source_surface = surface_pattern->surface; } } + if (x_offset) + *x_offset = x; + if (y_offset) + *y_offset = y; + + /* transform operation extents to pattern space */ + op_extents = *extents; + if (source_pattern) + { + _cairo_box_from_rectangle (&box, extents); + _cairo_matrix_transform_bounding_box_fixed (&source_pattern->matrix, &box, NULL); + _cairo_box_round_to_rectangle (&box, &op_extents); + } + if (source_extents) + *source_extents = op_extents; surface_key.id = source_surface->unique_id; surface_key.interpolate = interpolate; @@ -1415,61 +1559,76 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface, _cairo_pdf_source_surface_init_key (&surface_key); surface_entry = _cairo_hash_table_lookup (surface->all_surfaces, &surface_key.base); if (surface_entry) { - *surface_res = surface_entry->surface_res; - *width = surface_entry->width; - *height = surface_entry->height; - *source_extents = surface_entry->extents; - status = CAIRO_STATUS_SUCCESS; - } else { - status = _get_source_surface_size (source_surface, - width, - height, - source_extents); - if (unlikely(status)) - goto release_source; + if (pdf_source) + *pdf_source = surface_entry; - if (surface_key.unique_id && surface_key.unique_id_length > 0) { - unique_id = _cairo_malloc (surface_key.unique_id_length); - if (unique_id == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto release_source; - } + if (source_pattern && source_pattern->extend != CAIRO_EXTEND_NONE) + _cairo_unbounded_rectangle_init (&op_extents); - unique_id_length = surface_key.unique_id_length; - memcpy (unique_id, surface_key.unique_id, unique_id_length); - } else { - unique_id = NULL; - unique_id_length = 0; - } + _cairo_rectangle_intersect (&op_extents, &surface_entry->extents); + _cairo_rectangle_union (&surface_entry->required_extents, &op_extents); + status = CAIRO_STATUS_SUCCESS; } -release_source: - if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) - _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra); - - if (status || surface_entry) + if (status || surface_entry) { + if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) + _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra); return status; + } - surface_entry = malloc (sizeof (cairo_pdf_source_surface_entry_t)); + if (surface_key.unique_id && surface_key.unique_id_length > 0) { + unique_id = _cairo_malloc (surface_key.unique_id_length); + if (unique_id == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto fail1; + } + + unique_id_length = surface_key.unique_id_length; + memcpy (unique_id, surface_key.unique_id, unique_id_length); + } else { + unique_id = NULL; + unique_id_length = 0; + } + + surface_entry = _cairo_malloc (sizeof (cairo_pdf_source_surface_entry_t)); if (surface_entry == NULL) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail1; } + if (pdf_source) + *pdf_source = surface_entry; surface_entry->id = surface_key.id; surface_entry->operator = op; surface_entry->interpolate = interpolate; surface_entry->stencil_mask = stencil_mask; surface_entry->smask = smask; + surface_entry->need_transp_group = need_transp_group; surface_entry->unique_id_length = unique_id_length; surface_entry->unique_id = unique_id; - surface_entry->width = *width; - surface_entry->height = *height; - surface_entry->extents = *source_extents; if (smask_res) surface_entry->smask_res = *smask_res; else surface_entry->smask_res.id = 0; + + status = _get_source_surface_extents (source_surface, + &surface_entry->extents, + &surface_entry->bounded, + &subsurface); + if (unlikely (status)) + goto fail2; + + if (subsurface) { + *x_offset = -surface_entry->extents.x; + *y_offset = -surface_entry->extents.y; + } + + if (source_pattern && source_pattern->extend != CAIRO_EXTEND_NONE) + _cairo_unbounded_rectangle_init (&op_extents); + + _cairo_rectangle_intersect (&op_extents, &surface_entry->extents); + surface_entry->required_extents = op_extents; + _cairo_pdf_source_surface_init_key (surface_entry); src_surface.hash_entry = surface_entry; @@ -1492,18 +1651,30 @@ release_source: goto fail3; } - status = _cairo_array_append (&surface->page_surfaces, &src_surface); + /* Test if surface will be emitted as image or recording */ + status = _cairo_pdf_surface_emit_surface (surface, &src_surface, TRUE, &surface_entry->emit_image); if (unlikely (status)) goto fail3; + if (surface_entry->bounded) { + status = _cairo_array_append (&surface->page_surfaces, &src_surface); + if (unlikely (status)) + goto fail3; + } else { + status = _cairo_array_append (&surface->doc_surfaces, &src_surface); + if (unlikely (status)) + goto fail3; + } + status = _cairo_hash_table_insert (surface->all_surfaces, &surface_entry->base); if (unlikely(status)) goto fail3; - *surface_res = surface_entry->surface_res; + if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) + _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra); - return status; + return CAIRO_STATUS_SUCCESS; fail3: if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) @@ -1515,7 +1686,11 @@ fail2: free (surface_entry); fail1: - free (unique_id); + if (unique_id) + free (unique_id); + + if (source_pattern && source_pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) + _cairo_pdf_surface_release_source_image_from_pattern (surface, source_pattern, image, image_extra); return status; } @@ -1584,6 +1759,10 @@ _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface, *pattern_res = pdf_pattern.pattern_res; *gstate_res = pdf_pattern.gstate_res; + /* If the pattern requires a gstate it will be drawn from within + * an XObject. The initial space of each XObject has an inverted + * Y-axis. */ + pdf_pattern.inverted_y_axis = pdf_pattern.gstate_res.id ? TRUE : surface->in_xobject; status = _cairo_array_append (&surface->page_patterns, &pdf_pattern); if (unlikely (status)) { @@ -1594,16 +1773,15 @@ _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface, return CAIRO_INT_STATUS_SUCCESS; } -/* Get BBox in PDF coordinates from extents in cairo coordinates */ +/* Get BBox from extents */ static void -_get_bbox_from_extents (double surface_height, - const cairo_rectangle_int_t *extents, - cairo_box_double_t *bbox) +_get_bbox_from_extents (const cairo_rectangle_int_t *extents, + cairo_box_double_t *bbox) { bbox->p1.x = extents->x; - bbox->p1.y = surface_height - (extents->y + extents->height); + bbox->p1.y = extents->y; bbox->p2.x = extents->x + extents->width; - bbox->p2.y = surface_height - extents->y; + bbox->p2.y = extents->y + extents->height; } static cairo_int_status_t @@ -1705,6 +1883,7 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface, surface->output = output; _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->output); } + _cairo_pdf_operators_reset (&surface->pdf_operators); return _cairo_output_stream_get_status (surface->output); } @@ -1965,6 +2144,9 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface, resource, surface->compress_content, NULL); + _cairo_output_stream_printf (surface->output, + "1 0 0 -1 0 %f cm\n", + surface->height); } if (unlikely (status)) return status; @@ -1972,6 +2154,7 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface, surface->content = surface->pdf_stream.self; _cairo_output_stream_printf (surface->output, "q\n"); + _cairo_pdf_operators_reset (&surface->pdf_operators); return _cairo_output_stream_get_status (surface->output); } @@ -2021,10 +2204,16 @@ _cairo_pdf_surface_finish (void *abstract_surface) { cairo_pdf_surface_t *surface = abstract_surface; long offset; - cairo_pdf_resource_t info, catalog; + cairo_pdf_resource_t catalog; cairo_status_t status, status2; int size, i; cairo_pdf_jbig2_global_t *global; + char *label; + + _cairo_pdf_surface_clear (surface); + + /* Emit unbounded surfaces */ + _cairo_pdf_surface_write_patterns_and_smask_groups (surface, TRUE); status = surface->base.status; if (status == CAIRO_STATUS_SUCCESS) @@ -2032,9 +2221,9 @@ _cairo_pdf_surface_finish (void *abstract_surface) _cairo_pdf_surface_write_pages (surface); - info = _cairo_pdf_surface_write_info (surface); - if (info.id == 0 && status == CAIRO_STATUS_SUCCESS) - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + status = _cairo_pdf_interchange_write_document_objects (surface); + if (unlikely (status)) + return status; catalog = _cairo_pdf_surface_write_catalog (surface); if (catalog.id == 0 && status == CAIRO_STATUS_SUCCESS) @@ -2050,7 +2239,7 @@ _cairo_pdf_surface_finish (void *abstract_surface) ">>\n", surface->next_available_resource.id, catalog.id, - info.id); + surface->docinfo_res.id); _cairo_output_stream_printf (surface->output, "startxref\n" @@ -2090,7 +2279,6 @@ _cairo_pdf_surface_finish (void *abstract_surface) if (status == CAIRO_STATUS_SUCCESS) status = status2; - _cairo_pdf_surface_clear (surface); _cairo_pdf_group_resources_fini (&surface->resources); _cairo_array_fini (&surface->objects); @@ -2099,6 +2287,7 @@ _cairo_pdf_surface_finish (void *abstract_surface) _cairo_array_fini (&surface->alpha_linear_functions); _cairo_array_fini (&surface->page_patterns); _cairo_array_fini (&surface->page_surfaces); + _cairo_array_fini (&surface->doc_surfaces); _cairo_hash_table_foreach (surface->all_surfaces, _cairo_pdf_source_surface_entry_pluck, surface->all_surfaces); @@ -2106,6 +2295,7 @@ _cairo_pdf_surface_finish (void *abstract_surface) _cairo_array_fini (&surface->smask_groups); _cairo_array_fini (&surface->fonts); _cairo_array_fini (&surface->knockout_group); + _cairo_array_fini (&surface->page_annots); if (surface->font_subsets) { _cairo_scaled_font_subsets_destroy (surface->font_subsets); @@ -2120,18 +2310,26 @@ _cairo_pdf_surface_finish (void *abstract_surface) return _cairo_error (CAIRO_STATUS_JBIG2_GLOBAL_MISSING); } _cairo_array_fini (&surface->jbig2_global); + _cairo_array_fini (&surface->page_heights); - _cairo_array_truncate (&surface->page_surfaces, 0); + size = _cairo_array_num_elements (&surface->page_labels); + for (i = 0; i < size; i++) { + _cairo_array_copy_element (&surface->page_labels, i, &label); + free (label); + } + _cairo_array_fini (&surface->page_labels); _cairo_surface_clipper_reset (&surface->clipper); - return status; + return _cairo_pdf_interchange_fini (surface); } static cairo_int_status_t _cairo_pdf_surface_start_page (void *abstract_surface) { cairo_pdf_surface_t *surface = abstract_surface; + cairo_pdf_resource_t page; + cairo_int_status_t status; /* Document header */ if (! surface->header_emitted) { @@ -2155,6 +2353,15 @@ _cairo_pdf_surface_start_page (void *abstract_surface) } _cairo_pdf_group_resources_clear (&surface->resources); + surface->in_xobject = FALSE; + + page = _cairo_pdf_surface_new_object (surface); + if (page.id == 0) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + status = _cairo_array_append (&surface->pages, &page); + if (unlikely (status)) + return status; return CAIRO_STATUS_SUCCESS; } @@ -2168,6 +2375,7 @@ _cairo_pdf_surface_has_fallback_images (void *abstract_surface, cairo_box_double_t bbox; surface->has_fallback_images = has_fallbacks; + surface->in_xobject = has_fallbacks; bbox.p1.x = 0; bbox.p1.y = 0; bbox.p2.x = surface->width; @@ -2185,22 +2393,47 @@ _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface) return TRUE; } +static cairo_bool_t +_cairo_pdf_surface_requires_thumbnail_image (void *abstract_surface, + int *width, + int *height) +{ + cairo_pdf_surface_t *surface = abstract_surface; + + if (surface->thumbnail_width > 0 && surface->thumbnail_height > 0) { + *width = surface->thumbnail_width; + *height = surface->thumbnail_height; + return TRUE; + } + + return FALSE; +} + +static cairo_int_status_t +_cairo_pdf_surface_set_thumbnail_image (void *abstract_surface, + cairo_image_surface_t *image) +{ + cairo_pdf_surface_t *surface = abstract_surface; + + surface->thumbnail_image = (cairo_image_surface_t *)cairo_surface_reference(&image->base); + + return CAIRO_STATUS_SUCCESS; +} + static cairo_int_status_t _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surface, const cairo_pattern_t *source, const cairo_rectangle_int_t *extents, - cairo_pdf_resource_t *surface_res, - int *width, - int *height, + cairo_pdf_source_surface_entry_t **pdf_source, double *x_offset, - double *y_offset) + double *y_offset, + cairo_rectangle_int_t *source_extents) { cairo_image_surface_t *image; cairo_surface_t *pad_image; void *image_extra; cairo_int_status_t status; int w, h; - cairo_rectangle_int_t extents2; cairo_box_t box; cairo_rectangle_int_t rect; cairo_surface_pattern_t pad_pattern; @@ -2247,18 +2480,17 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa status = _cairo_pdf_surface_add_source_surface (surface, pad_image, NULL, - FALSE, + CAIRO_OPERATOR_OVER, /* not used for images */ source->filter, - FALSE, - FALSE, + FALSE, /* stencil mask */ + FALSE, /* smask */ + FALSE, /* need_transp_group */ extents, - NULL, - surface_res, - width, - height, + NULL, /* smask_res */ + pdf_source, x_offset, y_offset, - &extents2); + source_extents); if (unlikely (status)) goto BAIL; @@ -2642,7 +2874,7 @@ _cairo_pdf_surface_lookup_jbig2_global (cairo_pdf_surface_t *surface, } } - global.id = malloc(global_id_length); + global.id = _cairo_malloc (global_id_length); if (unlikely (global.id == NULL)) { return _cairo_error (CAIRO_STATUS_NO_MEMORY); } @@ -2668,7 +2900,8 @@ _cairo_pdf_surface_lookup_jbig2_global (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t *surface, cairo_surface_t *source, - cairo_pdf_source_surface_entry_t *surface_entry) + cairo_pdf_source_surface_entry_t *surface_entry, + cairo_bool_t test) { cairo_int_status_t status; const unsigned char *mime_data; @@ -2691,6 +2924,10 @@ _cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t *surface, if (status) return status; + /* At this point we know emitting jbig2 will succeed. */ + if (test) + return CAIRO_STATUS_SUCCESS; + cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID, &global_id, &global_id_length); if (global_id && global_id_length > 0) { @@ -2776,7 +3013,8 @@ _cairo_pdf_surface_emit_jbig2_image (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface, cairo_surface_t *source, - cairo_pdf_source_surface_entry_t *surface_entry) + cairo_pdf_source_surface_entry_t *surface_entry, + cairo_bool_t test) { cairo_int_status_t status; const unsigned char *mime_data; @@ -2807,6 +3045,10 @@ _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface, else smask_buf[0] = 0; + /* At this point we know emitting jpx will succeed. */ + if (test) + return CAIRO_STATUS_SUCCESS; + if (surface_entry->stencil_mask) { status = _cairo_pdf_surface_open_stream (surface, &surface_entry->surface_res, @@ -2851,7 +3093,8 @@ _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface, cairo_surface_t *source, - cairo_pdf_source_surface_entry_t *surface_entry) + cairo_pdf_source_surface_entry_t *surface_entry, + cairo_bool_t test) { cairo_int_status_t status; const unsigned char *mime_data; @@ -2891,6 +3134,10 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; } + /* At this point we know emitting jpeg will succeed. */ + if (test) + return CAIRO_STATUS_SUCCESS; + if (surface_entry->smask_res.id) snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id); else @@ -2942,45 +3189,113 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface, } static cairo_int_status_t -_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface, - cairo_pdf_source_surface_t *source) +_cairo_pdf_surface_emit_ccitt_image (cairo_pdf_surface_t *surface, + cairo_surface_t *source, + cairo_pdf_source_surface_entry_t *surface_entry, + cairo_bool_t test) { - cairo_image_surface_t *image; - void *image_extra; - cairo_int_status_t status; + cairo_status_t status; + const unsigned char *ccitt_data; + unsigned long ccitt_data_len; + const unsigned char *ccitt_params_string; + unsigned long ccitt_params_string_len; + char *params, *p, *end; + cairo_ccitt_params_t ccitt_params; + char buf[300]; + + cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_CCITT_FAX, + &ccitt_data, &ccitt_data_len); + if (unlikely (source->status)) + return source->status; + if (ccitt_data == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { - status = _cairo_pdf_surface_emit_jbig2_image (surface, source->surface, source->hash_entry); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; + cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, + &ccitt_params_string, &ccitt_params_string_len); + if (unlikely (source->status)) + return source->status; + if (ccitt_params_string == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; - status = _cairo_pdf_surface_emit_jpx_image (surface, source->surface, source->hash_entry); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; + /* ensure params_string is null terminated */ + params = malloc (ccitt_params_string_len + 1); + memcpy (params, ccitt_params_string, ccitt_params_string_len); + params[ccitt_params_string_len] = 0; + status = _cairo_tag_parse_ccitt_params (params, &ccitt_params); + if (unlikely(status)) + return source->status; - status = _cairo_pdf_surface_emit_jpeg_image (surface, source->surface, source->hash_entry); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; + free (params); + + /* At this point we know emitting jbig2 will succeed. */ + if (test) + return CAIRO_STATUS_SUCCESS; + + p = buf; + *p = 0; + end = buf + sizeof(buf) - 1; + p += snprintf (p, end - p, "/Columns %d /Rows %d /K %d", + ccitt_params.columns, + ccitt_params.rows, + ccitt_params.k); + if (ccitt_params.end_of_line) + p += snprintf (p, end - p, " /EndOfLine true"); + + if (ccitt_params.encoded_byte_align) + p += snprintf (p, end - p, " /EncodedByteAlign true"); + + if (!ccitt_params.end_of_block) + p += snprintf (p, end - p, " /EndOfBlock false"); + + if (ccitt_params.black_is_1) + p += snprintf (p, end - p, " /BlackIs1 true"); + + if (ccitt_params.damaged_rows_before_error > 0) { + p += snprintf (p, end - p, " /DamagedRowsBeforeError %d", + ccitt_params.damaged_rows_before_error); } - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { - status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra); + if (surface_entry->stencil_mask) { + status = _cairo_pdf_surface_open_stream (surface, + &surface_entry->surface_res, + FALSE, + " /Type /XObject\n" + " /Subtype /Image\n" + " /ImageMask true\n" + " /Width %d\n" + " /Height %d\n" + " /Interpolate %s\n" + " /BitsPerComponent 1\n" + " /Decode [1 0]\n" + " /Filter /CCITTFaxDecode\n" + " /DecodeParms << %s >> ", + ccitt_params.columns, + ccitt_params.rows, + surface_entry->interpolate ? "true" : "false", + buf); } else { - status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source->raster_pattern, - &image, &image_extra); + status = _cairo_pdf_surface_open_stream (surface, + &surface_entry->surface_res, + FALSE, + " /Type /XObject\n" + " /Subtype /Image\n" + " /Width %d\n" + " /Height %d\n" + " /ColorSpace /DeviceGray\n" + " /BitsPerComponent 1\n" + " /Interpolate %s\n" + " /Filter /CCITTFaxDecode\n" + " /DecodeParms << %s >> ", + ccitt_params.columns, + ccitt_params.rows, + surface_entry->interpolate ? "true" : "false", + buf); } if (unlikely (status)) return status; - status = _cairo_pdf_surface_emit_image (surface, - image, - source->hash_entry); - - if (source->type == CAIRO_PATTERN_TYPE_SURFACE) - _cairo_surface_release_source_image (source->surface, image, image_extra); - else - _cairo_pdf_surface_release_source_image_from_pattern (surface, source->raster_pattern, - image, image_extra); + _cairo_output_stream_write (surface->output, ccitt_data, ccitt_data_len); + status = _cairo_pdf_surface_close_stream (surface); return status; } @@ -2989,50 +3304,58 @@ static cairo_int_status_t _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface, cairo_pdf_source_surface_t *pdf_source) { - double old_width, old_height; + cairo_rectangle_int_t old_surface_extents; + cairo_bool_t old_surface_bounded; cairo_paginated_mode_t old_paginated_mode; cairo_surface_clipper_t old_clipper; + cairo_bool_t old_in_xobject; cairo_box_double_t bbox; cairo_int_status_t status; int alpha = 0; cairo_surface_t *free_me = NULL; cairo_surface_t *source; const cairo_rectangle_int_t *extents; - int width; - int height; cairo_bool_t is_subsurface; cairo_bool_t transparency_group; cairo_recording_surface_t *recording; assert (pdf_source->type == CAIRO_PATTERN_TYPE_SURFACE); - extents = &pdf_source->hash_entry->extents; - width = pdf_source->hash_entry->width; - height = pdf_source->hash_entry->height; + + if (pdf_source->hash_entry->bounded) { + extents = &pdf_source->hash_entry->extents; + } else { + extents = &pdf_source->hash_entry->required_extents; + } + is_subsurface = FALSE; source = pdf_source->surface; - if (_cairo_surface_is_snapshot (source)) { + if (_cairo_surface_is_snapshot (source)) free_me = source = _cairo_surface_snapshot_get_target (source); - } else if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { + + if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source; source = sub->target; extents = &sub->extents; - width = extents->width; - height = extents->height; is_subsurface = TRUE; } assert (source->type == CAIRO_SURFACE_TYPE_RECORDING); recording = (cairo_recording_surface_t *) source; - old_width = surface->width; - old_height = surface->height; + old_in_xobject = surface->in_xobject; + old_surface_extents = surface->surface_extents; + old_surface_bounded = surface->surface_bounded; old_paginated_mode = surface->paginated_mode; old_clipper = surface->clipper; + surface->surface_extents = *extents; _cairo_surface_clipper_init (&surface->clipper, _cairo_pdf_surface_clipper_intersect_clip_path); - _cairo_pdf_surface_set_size_internal (surface, width, height); + _cairo_pdf_operators_reset (&surface->pdf_operators); + surface->in_xobject = TRUE; + surface->surface_extents = *extents; + surface->surface_bounded = TRUE; /* Patterns are emitted after fallback images. The paginated mode * needs to be set to _RENDER while the recording surface is replayed @@ -3040,17 +3363,24 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface, */ surface->paginated_mode = CAIRO_PAGINATED_MODE_RENDER; _cairo_pdf_group_resources_clear (&surface->resources); - _get_bbox_from_extents (height, extents, &bbox); + _get_bbox_from_extents (extents, &bbox); /* We can optimize away the transparency group allowing the viewer - * to replay the group in place when all operators are OVER and the - * recording contains only opaque and/or clear alpha. + * to replay the group in place when: + * - ca/CA when painting this groups is 1.0 (need_transp_group is FALSE), + * - all operators are OVER, and + * - the recording contains only opaque and/or clear alpha. */ - transparency_group = !(pdf_source->hash_entry->operator == CAIRO_OPERATOR_OVER && + transparency_group = pdf_source->hash_entry->need_transp_group || + !(pdf_source->hash_entry->operator == CAIRO_OPERATOR_OVER && _cairo_recording_surface_has_only_bilevel_alpha (recording) && _cairo_recording_surface_has_only_op_over (recording)); - status = _cairo_pdf_surface_open_content_stream (surface, &bbox, &pdf_source->hash_entry->surface_res, - TRUE, transparency_group); + + status = _cairo_pdf_surface_open_content_stream (surface, + &bbox, + &pdf_source->hash_entry->surface_res, + TRUE, + transparency_group); if (unlikely (status)) goto err; @@ -3060,10 +3390,12 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface, goto err; _cairo_output_stream_printf (surface->output, - "q /a%d gs 0 0 0 rg 0 0 %f %f re f Q\n", + "q /a%d gs 0 0 0 rg %d %d %d %d re f Q\n", alpha, - surface->width, - surface->height); + extents->x, + extents->y, + extents->width, + extents->height); } status = _cairo_recording_surface_replay_region (source, @@ -3078,25 +3410,118 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface, _cairo_surface_clipper_reset (&surface->clipper); surface->clipper = old_clipper; - _cairo_pdf_surface_set_size_internal (surface, - old_width, - old_height); + _cairo_pdf_operators_reset (&surface->pdf_operators); + surface->in_xobject = old_in_xobject; surface->paginated_mode = old_paginated_mode; + surface->surface_extents = old_surface_extents; + surface->surface_bounded = old_surface_bounded; err: cairo_surface_destroy (free_me); return status; } +/** + * _cairo_pdf_surface_emit_surface: + * @surface: [in] the pdf surface + * @source: [in] #cairo_pdf_source_surface_t containing the surface to write + * @test: [in] if true, test what type of surface will be emitted. + * @is_image: [out] if @test is true, returns TRUE if the surface will be emitted + * as an Image XObject. + * + * If @test is FALSE, emit @src_surface as an XObject. + * If @test is TRUE, don't emit anything. Set @is_image based on the output that would be emitted. + **/ static cairo_int_status_t _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface, - cairo_pdf_source_surface_t *src_surface) + cairo_pdf_source_surface_t *source, + cairo_bool_t test, + cairo_bool_t *is_image) { - if (src_surface->type == CAIRO_PATTERN_TYPE_SURFACE && - src_surface->surface->type == CAIRO_SURFACE_TYPE_RECORDING) - return _cairo_pdf_surface_emit_recording_surface (surface, src_surface); + cairo_image_surface_t *image; + void *image_extra; + cairo_int_status_t status; + + /* Try all the supported mime types and recording type, falling through + * each option if unsupported */ + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + status = _cairo_pdf_surface_emit_jbig2_image (surface, + source->surface, + source->hash_entry, + test); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) { + *is_image = TRUE; + return status; + } + + status = _cairo_pdf_surface_emit_jpx_image (surface, + source->surface, + source->hash_entry, + test); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) { + *is_image = TRUE; + return status; + } + + status = _cairo_pdf_surface_emit_jpeg_image (surface, + source->surface, + source->hash_entry, + test); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) { + *is_image = TRUE; + return status; + } + + status = _cairo_pdf_surface_emit_ccitt_image (surface, + source->surface, + source->hash_entry, + test); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) { + *is_image = TRUE; + return status; + } + + if (source->surface->type == CAIRO_SURFACE_TYPE_RECORDING) { + if (test) { + *is_image = FALSE; + return CAIRO_INT_STATUS_SUCCESS; + } else { + return _cairo_pdf_surface_emit_recording_surface (surface, source); + } + } + } + + /* The only option left is to emit as an image surface */ + + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + status = _cairo_surface_acquire_source_image (source->surface, &image, &image_extra); + } else { + status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, + source->raster_pattern, + &image, + &image_extra); + } + if (unlikely (status)) + return status; + + if (test) { + *is_image = TRUE; + } else { + status = _cairo_pdf_surface_emit_image (surface, + image, + source->hash_entry); + } + + if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { + _cairo_surface_release_source_image (source->surface, image, image_extra); + } else { + _cairo_pdf_surface_release_source_image_from_pattern (surface, + source->raster_pattern, + image, + image_extra); + } - return _cairo_pdf_surface_emit_image_surface (surface, src_surface); + return status; } static cairo_int_status_t @@ -3105,51 +3530,54 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, { cairo_pattern_t *pattern = pdf_pattern->pattern; cairo_int_status_t status; - cairo_pdf_resource_t pattern_resource = {0}; cairo_matrix_t cairo_p2d, pdf_p2d; cairo_extend_t extend = cairo_pattern_get_extend (pattern); double xstep, ystep; cairo_rectangle_int_t pattern_extents; - int pattern_width = 0; /* squelch bogus compiler warning */ - int pattern_height = 0; /* squelch bogus compiler warning */ double x_offset; double y_offset; - char draw_surface[200]; - cairo_box_double_t bbox; + char draw_surface[50]; + char draw_surface2[200]; + cairo_box_double_t bbox; + cairo_matrix_t mat; + cairo_pdf_source_surface_entry_t *pdf_source; + cairo_rectangle_int_t op_extents; + assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE); if (pattern->extend == CAIRO_EXTEND_PAD) { status = _cairo_pdf_surface_add_padded_image_surface (surface, pattern, &pdf_pattern->extents, - &pattern_resource, - &pattern_width, - &pattern_height, + &pdf_source, &x_offset, - &y_offset); - pattern_extents.x = 0; - pattern_extents.y = 0; - pattern_extents.width = pattern_width; - pattern_extents.height = pattern_height; + &y_offset, + &op_extents); } else { status = _cairo_pdf_surface_add_source_surface (surface, NULL, pattern, pdf_pattern->operator, pattern->filter, - FALSE, - FALSE, + FALSE, /* stencil mask */ + FALSE, /* smask */ + FALSE, /* need_transp_group */ &pdf_pattern->extents, - NULL, - &pattern_resource, - &pattern_width, - &pattern_height, + NULL, /* smask_res */ + &pdf_source, &x_offset, &y_offset, - &pattern_extents); + &op_extents); } if (unlikely (status)) return status; + pattern_extents = pdf_source->extents; + if (!pdf_source->bounded) + { + extend = CAIRO_EXTEND_NONE; + _cairo_rectangle_intersect (&pattern_extents, &op_extents); + } + switch (extend) { case CAIRO_EXTEND_PAD: case CAIRO_EXTEND_NONE: @@ -3167,7 +3595,8 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, * repeat visibly. */ double x1 = 0.0, y1 = 0.0; - double x2 = surface->width, y2 = surface->height; + double x2 = surface->surface_extents.width; + double y2 = surface->surface_extents.height; _cairo_matrix_transform_bounding_box (&pattern->matrix, &x1, &y1, &x2, &y2, NULL); @@ -3177,23 +3606,23 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, * required an answer that's large enough, we don't really * care if it's not as tight as possible.*/ xstep = ystep = ceil ((x2 - x1) + (y2 - y1) + - pattern_width + pattern_height); + pattern_extents.width + pattern_extents.height); } break; case CAIRO_EXTEND_REPEAT: - xstep = pattern_width; - ystep = pattern_height; + xstep = pattern_extents.width; + ystep = pattern_extents.height; break; + case CAIRO_EXTEND_REFLECT: - pattern_extents.x = 0; - pattern_extents.y = 0; - pattern_extents.width = pattern_width*2; - pattern_extents.height = pattern_height*2; - xstep = pattern_width*2; - ystep = pattern_height*2; + pattern_extents.width *= 2; + pattern_extents.height *= 2; + xstep = pattern_extents.width; + ystep = pattern_extents.height; break; - /* All the rest (if any) should have been analyzed away, so this - * case should be unreachable. */ + + /* All the rest (if any) should have been analyzed away, so this + * case should be unreachable. */ default: ASSERT_NOT_REACHED; xstep = 0; @@ -3232,12 +3661,19 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_INT_STATUS_SUCCESS); - cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &surface->cairo_to_pdf); - cairo_matrix_translate (&pdf_p2d, -x_offset, -y_offset); - cairo_matrix_translate (&pdf_p2d, 0.0, pattern_height); - cairo_matrix_scale (&pdf_p2d, 1.0, -1.0); + if (pdf_pattern->inverted_y_axis) + cairo_matrix_init (&mat, 1, 0, 0, 1, 0, 0); + else + cairo_matrix_init (&mat, 1, 0, 0, -1, 0, surface->height); + + cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &mat); + cairo_matrix_translate (&pdf_p2d, x_offset, y_offset); + if (pdf_source->emit_image) { + cairo_matrix_translate (&pdf_p2d, 0.0, pdf_source->extents.height); + cairo_matrix_scale (&pdf_p2d, 1.0, -1.0); + } - _get_bbox_from_extents (pattern_height, &pattern_extents, &bbox); + _get_bbox_from_extents (&pattern_extents, &bbox); _cairo_pdf_surface_update_object (surface, pdf_pattern->pattern_res); status = _cairo_pdf_surface_open_stream (surface, &pdf_pattern->pattern_res, @@ -3255,40 +3691,59 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface, pdf_p2d.xx, pdf_p2d.yx, pdf_p2d.xy, pdf_p2d.yy, pdf_p2d.x0, pdf_p2d.y0, - pattern_resource.id, - pattern_resource.id); + pdf_source->surface_res.id, + pdf_source->surface_res.id); if (unlikely (status)) return status; - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE && - ((cairo_surface_pattern_t *) pattern)->surface->type == CAIRO_SURFACE_TYPE_RECORDING) { + if (pdf_source->emit_image) { snprintf(draw_surface, sizeof (draw_surface), - "/x%d Do\n", - pattern_resource.id); + "q %d 0 0 %d 0 0 cm /x%d Do Q", + pdf_source->extents.width, + pdf_source->extents.height, + pdf_source->surface_res.id); } else { snprintf(draw_surface, sizeof (draw_surface), - "q %d 0 0 %d 0 0 cm /x%d Do Q", - pattern_width, - pattern_height, - pattern_resource.id); + "/x%d Do", + pdf_source->surface_res.id); } if (extend == CAIRO_EXTEND_REFLECT) { - _cairo_output_stream_printf (surface->output, - "q 0 0 %d %d re W n %s Q\n" - "q -1 0 0 1 %d 0 cm 0 0 %d %d re W n %s Q\n" - "q 1 0 0 -1 0 %d cm 0 0 %d %d re W n %s Q\n" - "q -1 0 0 -1 %d %d cm 0 0 %d %d re W n %s Q\n", - pattern_width, pattern_height, - draw_surface, - pattern_width*2, pattern_width, pattern_height, - draw_surface, - pattern_height*2, pattern_width, pattern_height, - draw_surface, - pattern_width*2, pattern_height*2, pattern_width, pattern_height, - draw_surface); + cairo_rectangle_int_t p_extents = pdf_source->extents; + snprintf(draw_surface2, + sizeof (draw_surface2), + "%d %d %d %d re W n %s", + p_extents.x, p_extents.y, + p_extents.width, p_extents.height, + draw_surface); + + _cairo_output_stream_printf (surface->output, "q %s Q\n", draw_surface2); + + cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y); + cairo_matrix_scale (&mat, -1, 1); + cairo_matrix_translate (&mat, -2*p_extents.width, 0); + cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y); + _cairo_output_stream_printf (surface->output, "q "); + _cairo_output_stream_print_matrix (surface->output, &mat); + _cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2); + + cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y); + cairo_matrix_scale (&mat, 1, -1); + cairo_matrix_translate (&mat, 0, -2*p_extents.height); + cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y); + _cairo_output_stream_printf (surface->output, "q "); + _cairo_output_stream_print_matrix (surface->output, &mat); + _cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2); + + cairo_matrix_init_translate (&mat, p_extents.x, p_extents.y); + cairo_matrix_scale (&mat, -1, -1); + cairo_matrix_translate (&mat, -2*p_extents.width, -2*p_extents.height); + cairo_matrix_translate (&mat, -p_extents.x, -p_extents.y); + _cairo_output_stream_printf (surface->output, "q "); + _cairo_output_stream_print_matrix (surface->output, &mat); + _cairo_output_stream_printf (surface->output, " cm %s Q\n", draw_surface2); } else { _cairo_output_stream_printf (surface->output, " %s \n", @@ -3736,7 +4191,7 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface, /* When emitting a shading operator we are in cairo pattern * coordinates. _cairo_pdf_surface_paint_gradient has set the - * ctm to the pattern matrix (including the convertion from + * ctm to the pattern matrix (including the conversion from * pdf to cairo coordinates) */ _cairo_box_from_rectangle (&box, &pdf_pattern->extents); _cairo_box_to_doubles (&box, &x1, &y1, &x2, &y2); @@ -3748,7 +4203,7 @@ cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface, * coordinates. The color and alpha shading patterns painted * in the XObject below contain the cairo pattern to pdf page * matrix in the /Matrix entry of the pattern. */ - _get_bbox_from_extents (pdf_pattern->height, &pdf_pattern->extents, &box); + _get_bbox_from_extents (&pdf_pattern->extents, &box); x1 = box.p1.x; y1 = box.p1.y; x2 = box.p2.x; @@ -3913,6 +4368,7 @@ _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface, cairo_circle_double_t start, end; double domain[2]; cairo_int_status_t status; + cairo_matrix_t mat; assert (pattern->n_stops != 0); @@ -3927,7 +4383,13 @@ _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface, status = cairo_matrix_invert (&pat_to_pdf); /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_INT_STATUS_SUCCESS); - cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf); + + if (pdf_pattern->inverted_y_axis) + cairo_matrix_init (&mat, 1, 0, 0, 1, 0, 0); + else + cairo_matrix_init (&mat, 1, 0, 0, -1, 0, surface->height); + + cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &mat); if (pattern->base.extend == CAIRO_EXTEND_REPEAT || pattern->base.extend == CAIRO_EXTEND_REFLECT) @@ -4059,13 +4521,19 @@ _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface, cairo_pdf_shading_t shading; int i; cairo_pdf_resource_t res; + cairo_matrix_t mat; pat_to_pdf = pattern->matrix; status = cairo_matrix_invert (&pat_to_pdf); /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_INT_STATUS_SUCCESS); - cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf); + if (pdf_pattern->inverted_y_axis) + cairo_matrix_init (&mat, 1, 0, 0, 1, 0, 0); + else + cairo_matrix_init (&mat, 1, 0, 0, -1, 0, surface->height); + + cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &mat); status = _cairo_pdf_shading_init_color (&shading, (cairo_mesh_pattern_t *) pattern); if (unlikely (status)) @@ -4197,15 +4665,8 @@ _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface, static cairo_int_status_t _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern_t *pdf_pattern) { - double old_width, old_height; cairo_int_status_t status; - old_width = surface->width; - old_height = surface->height; - _cairo_pdf_surface_set_size_internal (surface, - pdf_pattern->width, - pdf_pattern->height); - switch (pdf_pattern->pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: ASSERT_NOT_REACHED; @@ -4232,10 +4693,6 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern break; } - _cairo_pdf_surface_set_size_internal (surface, - old_width, - old_height); - return status; } @@ -4244,17 +4701,16 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_rectangle_int_t *extents, + double alpha, cairo_pdf_resource_t *smask_res, cairo_bool_t stencil_mask) { - cairo_pdf_resource_t surface_res; - int width, height; cairo_matrix_t cairo_p2d, pdf_p2d; cairo_int_status_t status; - int alpha; - cairo_rectangle_int_t extents2; + int alpha_id; double x_offset; double y_offset; + cairo_pdf_source_surface_entry_t *pdf_source; if (source->extend == CAIRO_EXTEND_PAD && !(source->type == CAIRO_PATTERN_TYPE_SURFACE && @@ -4263,11 +4719,10 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, status = _cairo_pdf_surface_add_padded_image_surface (surface, source, extents, - &surface_res, - &width, - &height, + &pdf_source, &x_offset, - &y_offset); + &y_offset, + NULL); } else { status = _cairo_pdf_surface_add_source_surface (surface, NULL, @@ -4275,15 +4730,14 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, op, source->filter, stencil_mask, - FALSE, + FALSE, /* smask */ + alpha != 1.0, /* need_transp_group */ extents, smask_res, - &surface_res, - &width, - &height, + &pdf_source, &x_offset, &y_offset, - &extents2); + NULL); } if (unlikely (status)) return status; @@ -4296,11 +4750,20 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, pdf_p2d = surface->cairo_to_pdf; cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d); cairo_matrix_translate (&pdf_p2d, x_offset, y_offset); - cairo_matrix_translate (&pdf_p2d, 0.0, height); - cairo_matrix_scale (&pdf_p2d, 1.0, -1.0); - if (!(source->type == CAIRO_PATTERN_TYPE_SURFACE && - ((cairo_surface_pattern_t *)source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)) - { + if (pdf_source->emit_image) { + int width, height; + + if (pdf_source->bounded) { + width = pdf_source->extents.width; + height = pdf_source->extents.height; + } else { + /* We can't scale an image to an unbounded surface size so just set the size to 1 */ + width = 1; + height = 1; + } + + cairo_matrix_translate (&pdf_p2d, 0.0, height); + cairo_matrix_scale (&pdf_p2d, 1.0, -1.0); cairo_matrix_scale (&pdf_p2d, width, height); } @@ -4313,34 +4776,35 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface, _cairo_output_stream_printf (surface->output, " cm\n"); } - status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha); + status = _cairo_pdf_surface_add_alpha (surface, alpha, &alpha_id); if (unlikely (status)) return status; if (stencil_mask) { _cairo_output_stream_printf (surface->output, "/x%d Do\n", - surface_res.id); + pdf_source->surface_res.id); } else { _cairo_output_stream_printf (surface->output, "/a%d gs /x%d Do\n", - alpha, - surface_res.id); + alpha_id, + pdf_source->surface_res.id); } - return _cairo_pdf_surface_add_xobject (surface, surface_res); + return _cairo_pdf_surface_add_xobject (surface, pdf_source->surface_res); } static cairo_int_status_t _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, - const cairo_rectangle_int_t *extents) + const cairo_rectangle_int_t *extents, + double alpha) { cairo_pdf_resource_t shading_res, gstate_res; cairo_matrix_t pat_to_pdf; cairo_int_status_t status; - int alpha; + int alpha_id; status = _cairo_pdf_surface_add_pdf_shading (surface, source, op, extents, @@ -4379,13 +4843,13 @@ _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t *surface, gstate_res.id, shading_res.id); } else { - status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha); + status = _cairo_pdf_surface_add_alpha (surface, alpha, &alpha_id); if (unlikely (status)) return status; _cairo_output_stream_printf (surface->output, "/a%d gs /sh%d sh\n", - alpha, + alpha_id, shading_res.id); } @@ -4397,6 +4861,7 @@ _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_rectangle_int_t *extents, + double alpha, cairo_bool_t mask) { switch (source->type) { @@ -4406,6 +4871,7 @@ _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface, op, source, extents, + alpha, NULL, mask); case CAIRO_PATTERN_TYPE_LINEAR: @@ -4414,7 +4880,8 @@ _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface, return _cairo_pdf_surface_paint_gradient (surface, op, source, - extents); + extents, + alpha); case CAIRO_PATTERN_TYPE_SOLID: default: @@ -4593,6 +5060,20 @@ _cairo_pdf_surface_show_page (void *abstract_surface) cairo_pdf_surface_t *surface = abstract_surface; cairo_int_status_t status; + status = _cairo_array_append (&surface->page_heights, &surface->height); + if (unlikely (status)) + return status; + + status = _cairo_array_append (&surface->page_labels, &surface->current_page_label); + if (unlikely (status)) + return status; + + surface->current_page_label = NULL; + + status = _cairo_pdf_interchange_end_page_content (surface); + if (unlikely (status)) + return status; + status = _cairo_pdf_surface_close_content_stream (surface); if (unlikely (status)) return status; @@ -4614,17 +5095,10 @@ _cairo_pdf_surface_get_extents (void *abstract_surface, { cairo_pdf_surface_t *surface = abstract_surface; - rectangle->x = 0; - rectangle->y = 0; - - /* XXX: The conversion to integers here is pretty bogus, (not to - * mention the arbitrary limitation of width to a short(!). We - * may need to come up with a better interface for get_size. - */ - rectangle->width = ceil (surface->width); - rectangle->height = ceil (surface->height); + if (surface->surface_bounded) + *rectangle = surface->surface_extents; - return TRUE; + return surface->surface_bounded; } static void @@ -4639,28 +5113,6 @@ _cairo_pdf_surface_get_font_options (void *abstract_surface, _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_OFF); } -static cairo_pdf_resource_t -_cairo_pdf_surface_write_info (cairo_pdf_surface_t *surface) -{ - cairo_pdf_resource_t info; - - info = _cairo_pdf_surface_new_object (surface); - if (info.id == 0) - return info; - - _cairo_output_stream_printf (surface->output, - "%d 0 obj\n" - "<< /Creator (cairo %s (http://cairographics.org))\n" - " /Producer (cairo %s (http://cairographics.org))\n" - ">>\n" - "endobj\n", - info.id, - cairo_version_string (), - cairo_version_string ()); - - return info; -} - static void _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) { @@ -4691,8 +5143,8 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface) "endobj\n"); } -static cairo_int_status_t -_utf8_to_pdf_string (const char *utf8, char **str_out) +cairo_int_status_t +_cairo_utf8_to_pdf_string (const char *utf8, char **str_out) { int i; int len; @@ -4711,7 +5163,7 @@ _utf8_to_pdf_string (const char *utf8, char **str_out) } if (ascii) { - str = malloc (len + 3); + str = _cairo_malloc (len + 3); if (str == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -4728,7 +5180,7 @@ _utf8_to_pdf_string (const char *utf8, char **str_out) if (unlikely (status)) return status; - str = malloc (utf16_len*4 + 7); + str = _cairo_malloc (utf16_len*4 + 7); if (str == NULL) { free (utf16); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -5037,7 +5489,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface, if (subset->family_name_utf8) { char *pdf_str; - status = _utf8_to_pdf_string (subset->family_name_utf8, &pdf_str); + status = _cairo_utf8_to_pdf_string (subset->family_name_utf8, &pdf_str); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { _cairo_output_stream_printf (surface->output, " /FontFamily %s\n", @@ -5483,7 +5935,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface, if (subset.family_name_utf8) { char *pdf_str; - status = _utf8_to_pdf_string (subset.family_name_utf8, &pdf_str); + status = _cairo_utf8_to_pdf_string (subset.family_name_utf8, &pdf_str); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { _cairo_output_stream_printf (surface->output, " /FontFamily %s\n", @@ -5855,16 +6307,16 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface, "<< /Type /Font\n" " /Subtype /Type3\n" " /FontBBox [%f %f %f %f]\n" - " /FontMatrix [ 1 0 0 1 0 0 ]\n" + " /FontMatrix [ 1 0 0 -1 0 0 ]\n" " /Encoding %d 0 R\n" " /CharProcs %d 0 R\n" " /FirstChar 0\n" " /LastChar %d\n", subset_resource.id, _cairo_fixed_to_double (font_bbox.p1.x), - - _cairo_fixed_to_double (font_bbox.p2.y), + _cairo_fixed_to_double (font_bbox.p1.y), _cairo_fixed_to_double (font_bbox.p2.x), - - _cairo_fixed_to_double (font_bbox.p1.y), + _cairo_fixed_to_double (font_bbox.p2.y), encoding.id, char_procs.id, font_subset->num_glyphs - 1); @@ -5988,12 +6440,42 @@ _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface) _cairo_output_stream_printf (surface->output, "%d 0 obj\n" "<< /Type /Catalog\n" - " /Pages %d 0 R\n" - ">>\n" - "endobj\n", + " /Pages %d 0 R\n", catalog.id, surface->pages_resource.id); + if (surface->struct_tree_root.id != 0) { + _cairo_output_stream_printf (surface->output, + " /StructTreeRoot %d 0 R\n", + surface->struct_tree_root.id); + if (surface->tagged) { + _cairo_output_stream_printf (surface->output, + " /MarkInfo << /Marked true >>\n"); + } + } + + if (surface->outlines_dict_res.id != 0) { + _cairo_output_stream_printf (surface->output, + " /Outlines %d 0 R\n", + surface->outlines_dict_res.id); + } + + if (surface->page_labels_res.id != 0) { + _cairo_output_stream_printf (surface->output, + " /PageLabels %d 0 R\n", + surface->page_labels_res.id); + } + + if (surface->names_dict_res.id != 0) { + _cairo_output_stream_printf (surface->output, + " /Names %d 0 R\n", + surface->names_dict_res.id); + } + + _cairo_output_stream_printf (surface->output, + ">>\n" + "endobj\n"); + return catalog; } @@ -6037,7 +6519,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface, cairo_box_double_t bbox; /* Create mask group */ - _get_bbox_from_extents (group->height, &group->extents, &bbox); + _get_bbox_from_extents (&group->extents, &bbox); status = _cairo_pdf_surface_open_group (surface, &bbox, NULL); if (unlikely (status)) return status; @@ -6048,7 +6530,8 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface, CAIRO_OPERATOR_OVER, group->mask, &group->extents, - FALSE); + 1.0, /* alpha */ + FALSE); /* mask */ if (unlikely (status)) return status; @@ -6124,7 +6607,8 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface, CAIRO_OPERATOR_OVER, group->source, &group->extents, - FALSE); + 1.0, /* alpha */ + FALSE); /* mask */ if (unlikely (status)) return status; @@ -6224,14 +6708,20 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface, cairo_pdf_smask_group_t *group) { double old_width, old_height; + cairo_bool_t old_in_xobject; cairo_int_status_t status; cairo_box_double_t bbox; + cairo_rectangle_int_t old_surface_extents; old_width = surface->width; old_height = surface->height; + old_surface_extents = surface->surface_extents; + old_in_xobject = surface->in_xobject; + surface->in_xobject = TRUE; _cairo_pdf_surface_set_size_internal (surface, group->width, group->height); + _cairo_pdf_operators_reset (&surface->pdf_operators); /* _mask is a special case that requires two groups - source * and mask as well as a smask and gstate dictionary */ if (group->operation == PDF_MASK) { @@ -6239,7 +6729,7 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface, goto RESTORE_SIZE; } - _get_bbox_from_extents (group->height, &group->extents, &bbox); + _get_bbox_from_extents (&group->extents, &bbox); status = _cairo_pdf_surface_open_group (surface, &bbox, &group->group_res); if (unlikely (status)) return status; @@ -6291,21 +6781,26 @@ _cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface, status = _cairo_pdf_surface_close_group (surface, NULL); RESTORE_SIZE: + surface->in_xobject = old_in_xobject; _cairo_pdf_surface_set_size_internal (surface, old_width, old_height); + surface->surface_extents = old_surface_extents; + _cairo_pdf_operators_reset (&surface->pdf_operators); return status; } static cairo_int_status_t -_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface) +_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface, + cairo_bool_t finish) { cairo_pdf_pattern_t pattern; cairo_pdf_smask_group_t *group; cairo_pdf_source_surface_t src_surface; - unsigned int pattern_index, group_index, surface_index; + unsigned int pattern_index, group_index, surface_index, doc_surface_index; cairo_int_status_t status; + cairo_bool_t is_image; /* Writing out PDF_MASK groups will cause additional smask groups * to be appended to surface->smask_groups. Additional patterns @@ -6317,9 +6812,11 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface pattern_index = 0; group_index = 0; surface_index = 0; + doc_surface_index = 0; while ((pattern_index < _cairo_array_num_elements (&surface->page_patterns)) || (group_index < _cairo_array_num_elements (&surface->smask_groups)) || - (surface_index < _cairo_array_num_elements (&surface->page_surfaces))) + (surface_index < _cairo_array_num_elements (&surface->page_surfaces)) || + (finish && (doc_surface_index < _cairo_array_num_elements (&surface->doc_surfaces)))) { for (; group_index < _cairo_array_num_elements (&surface->smask_groups); group_index++) { _cairo_array_copy_element (&surface->smask_groups, group_index, &group); @@ -6337,10 +6834,19 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface for (; surface_index < _cairo_array_num_elements (&surface->page_surfaces); surface_index++) { _cairo_array_copy_element (&surface->page_surfaces, surface_index, &src_surface); - status = _cairo_pdf_surface_emit_surface (surface, &src_surface); + status = _cairo_pdf_surface_emit_surface (surface, &src_surface, FALSE, &is_image); if (unlikely (status)) return status; } + + if (finish) { + for (; doc_surface_index < _cairo_array_num_elements (&surface->doc_surfaces); doc_surface_index++) { + _cairo_array_copy_element (&surface->doc_surfaces, doc_surface_index, &src_surface); + status = _cairo_pdf_surface_emit_surface (surface, &src_surface, FALSE, &is_image); + if (unlikely (status)) + return status; + } + } } return CAIRO_STATUS_SUCCESS; @@ -6349,9 +6855,14 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface static cairo_int_status_t _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) { - cairo_pdf_resource_t page, knockout, res; + cairo_pdf_resource_t knockout, res, thumbnail_res; + cairo_pdf_resource_t *page; cairo_int_status_t status; - unsigned int i, len; + unsigned int i, len, page_num, num_annots; + + status = _cairo_pdf_interchange_write_page_objects (surface); + if (unlikely (status)) + return status; _cairo_pdf_group_resources_clear (&surface->resources); if (surface->has_fallback_images) { @@ -6362,7 +6873,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) extents.y = 0; extents.width = ceil (surface->width); extents.height = ceil (surface->height); - _get_bbox_from_extents (surface->height, &extents, &bbox); + _get_bbox_from_extents (&extents, &bbox); status = _cairo_pdf_surface_open_knockout_group (surface, &bbox); if (unlikely (status)) return status; @@ -6405,13 +6916,22 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) return status; } - page = _cairo_pdf_surface_new_object (surface); - if (page.id == 0) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + thumbnail_res.id = 0; + if (surface->thumbnail_image) { + cairo_pdf_source_surface_entry_t entry; + + memset (&entry, 0, sizeof (entry)); + thumbnail_res = _cairo_pdf_surface_new_object (surface); + entry.surface_res = thumbnail_res; + _cairo_pdf_surface_emit_image (surface, surface->thumbnail_image, &entry); + } + page_num = _cairo_array_num_elements (&surface->pages); + page = _cairo_array_index (&surface->pages, page_num - 1); + _cairo_pdf_surface_update_object (surface, *page); _cairo_output_stream_printf (surface->output, "%d 0 obj\n" - "<< /Type /Page\n" + "<< /Type /Page %% %d\n" " /Parent %d 0 R\n" " /MediaBox [ 0 0 %f %f ]\n" " /Contents %d 0 R\n" @@ -6421,21 +6941,45 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) " /I true\n" " /CS /DeviceRGB\n" " >>\n" - " /Resources %d 0 R\n" - ">>\n" - "endobj\n", - page.id, + " /Resources %d 0 R\n", + page->id, + page_num, surface->pages_resource.id, surface->width, surface->height, surface->content.id, surface->content_resources.id); - status = _cairo_array_append (&surface->pages, &page); - if (unlikely (status)) - return status; + if (surface->page_parent_tree >= 0) { + _cairo_output_stream_printf (surface->output, + " /StructParents %d\n", + surface->page_parent_tree); + } + + num_annots = _cairo_array_num_elements (&surface->page_annots); + if (num_annots > 0) { + _cairo_output_stream_printf (surface->output, + " /Annots [ "); + for (i = 0; i < num_annots; i++) { + _cairo_array_copy_element (&surface->page_annots, i, &res); + _cairo_output_stream_printf (surface->output, + "%d 0 R ", + res.id); + } + _cairo_output_stream_printf (surface->output, "]\n"); + } - status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface); + if (thumbnail_res.id) { + _cairo_output_stream_printf (surface->output, + " /Thumb %d 0 R\n", + thumbnail_res.id); + } + + _cairo_output_stream_printf (surface->output, + ">>\n" + "endobj\n"); + + status = _cairo_pdf_surface_write_patterns_and_smask_groups (surface, FALSE); if (unlikely (status)) return status; @@ -6444,7 +6988,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface) static cairo_int_status_t _cairo_pdf_surface_analyze_surface_pattern_transparency (cairo_pdf_surface_t *surface, - cairo_surface_pattern_t *pattern) + cairo_surface_pattern_t *pattern) { cairo_image_surface_t *image; void *image_extra; @@ -6677,7 +7221,11 @@ _cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface) bbox.p1.y = 0; bbox.p2.x = surface->width; bbox.p2.y = surface->height; - return _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE, TRUE); + status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE, TRUE); + if (unlikely (status)) + return status; + + return _cairo_pdf_interchange_begin_page_content (surface); } /* If source is an opaque image and mask is an image and both images @@ -6694,7 +7242,6 @@ _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface, cairo_image_surface_t *image; void *image_extra; cairo_image_transparency_t transparency; - cairo_pdf_resource_t smask_res; int src_width, src_height; int mask_width, mask_height; double src_x_offset, src_y_offset; @@ -6703,8 +7250,8 @@ _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface, double mask_x1, mask_y1, mask_x2, mask_y2; cairo_matrix_t p2u; double src_radius, mask_radius, e; - cairo_rectangle_int_t extents2; cairo_bool_t need_smask; + cairo_pdf_source_surface_entry_t *pdf_source; /* Check that source and mask are images */ @@ -6823,16 +7370,15 @@ _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface, mask, op, source->filter, - FALSE, - TRUE, + FALSE, /* stencil mask */ + TRUE, /* smask */ + FALSE, /* need_transp_group */ extents, + NULL, /* smask_res */ + &pdf_source, NULL, - &smask_res, - &mask_width, - &mask_height, - &mask_x_offset, - &mask_y_offset, - &extents2); + NULL, + NULL); if (unlikely (status)) return status; } @@ -6843,7 +7389,8 @@ _cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface, _cairo_output_stream_printf (surface->output, "q\n"); status = _cairo_pdf_surface_paint_surface_pattern (surface, op, source, extents, - need_smask ? &smask_res : NULL, + 1.0, /* alpha */ + need_smask ? &pdf_source->surface_res : NULL, FALSE); if (unlikely (status)) return status; @@ -6906,7 +7453,7 @@ _cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface, return status; _cairo_output_stream_printf (surface->output, "q\n"); - status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask, extents, NULL, TRUE); + status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask, extents, 1.0, NULL, TRUE); if (unlikely (status)) return status; @@ -6956,11 +7503,15 @@ _cairo_pdf_surface_paint (void *abstract_surface, if (unlikely (status)) return status; + status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded); + if (unlikely (status)) + return status; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded); goto cleanup; } else if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) { - status = _cairo_pdf_surface_start_fallback (surface); + status = _cairo_pdf_surface_start_fallback (surface); if (unlikely (status)) goto cleanup; } @@ -6985,7 +7536,8 @@ _cairo_pdf_surface_paint (void *abstract_surface, op, source, &extents.bounded, - FALSE); + 1.0, /* alpha */ + FALSE); /* mask */ if (unlikely (status)) goto cleanup; @@ -7041,8 +7593,11 @@ _cairo_pdf_surface_paint (void *abstract_surface, goto cleanup; _cairo_output_stream_printf (surface->output, - "0 0 %f %f re f\n", - surface->width, surface->height); + "%d %d %d %d re f\n", + surface->surface_extents.x, + surface->surface_extents.y, + surface->surface_extents.width, + surface->surface_extents.height); status = _cairo_pdf_surface_unselect_pattern (surface); if (unlikely (status)) @@ -7070,6 +7625,7 @@ _cairo_pdf_surface_mask (void *abstract_surface, cairo_int_status_t status; cairo_rectangle_int_t r; cairo_box_t box; + double alpha; status = _cairo_composite_rectangles_init_for_mask (&extents, &surface->base, @@ -7077,6 +7633,10 @@ _cairo_pdf_surface_mask (void *abstract_surface, if (unlikely (status)) return status; + status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded); + if (unlikely (status)) + return status; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { cairo_int_status_t source_status, mask_status; @@ -7146,6 +7706,26 @@ _cairo_pdf_surface_mask (void *abstract_surface, if (status != CAIRO_INT_STATUS_UNSUPPORTED) goto cleanup; + /* Check if we can set ca/CA instead of an smask. We could handle + * other source patterns as well but for now this is the easiest, + * and most common, case to handle. */ + if (_cairo_pattern_is_constant_alpha (mask, &extents.bounded, &alpha) && + _can_paint_pattern (source)) { + _cairo_output_stream_printf (surface->output, "q\n"); + status = _cairo_pdf_surface_paint_pattern (surface, + op, + source, + &extents.bounded, + alpha, + FALSE); /* mask */ + if (unlikely (status)) + goto cleanup; + + _cairo_output_stream_printf (surface->output, "Q\n"); + _cairo_composite_rectangles_fini (&extents); + return _cairo_output_stream_get_status (surface->output); + } + group = _cairo_pdf_surface_create_smask_group (surface, &extents.bounded); if (unlikely (group == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -7246,6 +7826,10 @@ _cairo_pdf_surface_stroke (void *abstract_surface, goto cleanup; } + status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded); + if (unlikely (status)) + goto cleanup; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded); goto cleanup; @@ -7380,6 +7964,10 @@ _cairo_pdf_surface_fill (void *abstract_surface, goto cleanup; } + status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded); + if (unlikely (status)) + goto cleanup; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded); goto cleanup; @@ -7415,7 +8003,8 @@ _cairo_pdf_surface_fill (void *abstract_surface, op, source, &extents.bounded, - FALSE); + 1.0, /* alpha */ + FALSE); /* mask */ if (unlikely (status)) goto cleanup; @@ -7598,6 +8187,10 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface, goto cleanup; } + status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded); + if (unlikely (status)) + goto cleanup; + fill_pattern_res.id = 0; gstate_res.id = 0; status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source, @@ -7693,6 +8286,10 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface, if (unlikely (status)) return status; + status = _cairo_pdf_interchange_add_operation_extents (surface, &extents.bounded); + if (unlikely (status)) + return status; + if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded); goto cleanup; @@ -7732,7 +8329,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface, group->source_res = pattern_res; if (utf8_len) { - group->utf8 = malloc (utf8_len); + group->utf8 = _cairo_malloc (utf8_len); if (unlikely (group->utf8 == NULL)) { _cairo_pdf_smask_group_destroy (group); status = _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -7830,13 +8427,48 @@ _cairo_pdf_surface_get_supported_mime_types (void *abstract_surface) return _cairo_pdf_supported_mime_types; } -static void +static cairo_int_status_t +_cairo_pdf_surface_tag (void *abstract_surface, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip) +{ + cairo_pdf_surface_t *surface = abstract_surface; + cairo_int_status_t status = 0; + + if (begin) + status = _cairo_pdf_interchange_tag_begin (surface, tag_name, attributes); + else + status = _cairo_pdf_interchange_tag_end (surface, tag_name); + + return status; +} + +static cairo_int_status_t _cairo_pdf_surface_set_paginated_mode (void *abstract_surface, cairo_paginated_mode_t paginated_mode) { cairo_pdf_surface_t *surface = abstract_surface; + cairo_int_status_t status; surface->paginated_mode = paginated_mode; + status = _cairo_pdf_interchange_begin_page_content (surface); + if (unlikely (status)) + return status; + + if (paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { + surface->surface_extents.x = 0; + surface->surface_extents.y = 0; + surface->surface_extents.width = ceil (surface->width); + surface->surface_extents.height = ceil (surface->height); + } + + return CAIRO_INT_STATUS_SUCCESS; } static const cairo_surface_backend_t cairo_pdf_surface_backend = { @@ -7874,6 +8506,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = { _cairo_pdf_surface_has_show_text_glyphs, _cairo_pdf_surface_show_text_glyphs, _cairo_pdf_surface_get_supported_mime_types, + _cairo_pdf_surface_tag, }; static const cairo_paginated_surface_backend_t @@ -7883,4 +8516,6 @@ cairo_pdf_surface_paginated_backend = { NULL, /* set_bounding_box */ _cairo_pdf_surface_has_fallback_images, _cairo_pdf_surface_supports_fine_grained_fallbacks, + _cairo_pdf_surface_requires_thumbnail_image, + _cairo_pdf_surface_set_thumbnail_image, }; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pdf.h b/Build/source/libs/cairo/cairo-src/src/cairo-pdf.h index 1bc8524f2b1..5be0b3f1bea 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-pdf.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pdf.h @@ -85,6 +85,73 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface, double width_in_points, double height_in_points); +/** + * cairo_pdf_outline_flags_t: + * @CAIRO_PDF_OUTLINE_FLAG_OPEN: The outline item defaults to open in the PDF viewer (Since 1.16) + * @CAIRO_PDF_OUTLINE_FLAG_BOLD: The outline item is displayed by the viewer in bold text (Since 1.16) + * @CAIRO_PDF_OUTLINE_FLAG_ITALIC: The outline item is displayed by the viewer in italic text (Since 1.16) + * + * #cairo_pdf_outline_flags_t is used by the + * cairo_pdf_surface_add_outline() function specify the attributes of + * an outline item. These flags may be bitwise-or'd to produce any + * combination of flags. + * + * Since: 1.16 + **/ +typedef enum _cairo_pdf_outline_flags { + CAIRO_PDF_OUTLINE_FLAG_OPEN = 0x1, + CAIRO_PDF_OUTLINE_FLAG_BOLD = 0x2, + CAIRO_PDF_OUTLINE_FLAG_ITALIC = 0x4, +} cairo_pdf_outline_flags_t; + +#define CAIRO_PDF_OUTLINE_ROOT 0 + +cairo_public int +cairo_pdf_surface_add_outline (cairo_surface_t *surface, + int parent_id, + const char *utf8, + const char *link_attribs, + cairo_pdf_outline_flags_t flags); + +/** + * cairo_pdf_metadata_t: + * @CAIRO_PDF_METADATA_TITLE: The document title (Since 1.16) + * @CAIRO_PDF_METADATA_AUTHOR: The document author (Since 1.16) + * @CAIRO_PDF_METADATA_SUBJECT: The document subject (Since 1.16) + * @CAIRO_PDF_METADATA_KEYWORDS: The document keywords (Since 1.16) + * @CAIRO_PDF_METADATA_CREATOR: The document creator (Since 1.16) + * @CAIRO_PDF_METADATA_CREATE_DATE: The document creation date (Since 1.16) + * @CAIRO_PDF_METADATA_MOD_DATE: The document modification date (Since 1.16) + * + * #cairo_pdf_metadata_t is used by the + * cairo_pdf_surface_set_metadata() function specify the metadata to set. + * + * Since: 1.16 + **/ +typedef enum _cairo_pdf_metadata { + CAIRO_PDF_METADATA_TITLE, + CAIRO_PDF_METADATA_AUTHOR, + CAIRO_PDF_METADATA_SUBJECT, + CAIRO_PDF_METADATA_KEYWORDS, + CAIRO_PDF_METADATA_CREATOR, + CAIRO_PDF_METADATA_CREATE_DATE, + CAIRO_PDF_METADATA_MOD_DATE, +} cairo_pdf_metadata_t; + +cairo_public void +cairo_pdf_surface_set_metadata (cairo_surface_t *surface, + cairo_pdf_metadata_t metadata, + const char *utf8); + +cairo_public void +cairo_pdf_surface_set_page_label (cairo_surface_t *surface, + const char *utf8); + +cairo_public void +cairo_pdf_surface_set_thumbnail_size (cairo_surface_t *surface, + int width, + int height); + CAIRO_END_DECLS #else /* CAIRO_HAS_PDF_SURFACE */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-pen.c b/Build/source/libs/cairo/cairo-src/src/cairo-pen.c index 61be0e8299d..9bf960423d0 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-pen.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-pen.c @@ -106,7 +106,7 @@ _cairo_pen_fini (cairo_pen_t *pen) free (pen->vertices); - VG (VALGRIND_MAKE_MEM_NOACCESS (pen, sizeof (cairo_pen_t))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (pen, sizeof (cairo_pen_t))); } cairo_status_t diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-png.c b/Build/source/libs/cairo/cairo-src/src/cairo-png.c index e64b14a5fc0..ab0b9d0c51e 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-png.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-png.c @@ -136,7 +136,7 @@ png_simple_error_callback (png_structp png, /* default to the most likely error */ if (*error == CAIRO_STATUS_SUCCESS) - *error = _cairo_error (CAIRO_STATUS_NO_MEMORY); + *error = _cairo_error (CAIRO_STATUS_PNG_ERROR); #ifdef PNG_SETJMP_SUPPORTED longjmp (png_jmpbuf (png), 1); @@ -158,14 +158,6 @@ png_simple_warning_callback (png_structp png, */ } -static int -png_setjmp (png_struct *png) -{ -#ifdef PNG_SETJMP_SUPPORTED - return setjmp (png_jmpbuf (png)); -#endif - return 0; -} /* Starting with libpng-1.2.30, we must explicitly specify an output_flush_fn. * Otherwise, we will segfault if we are writing to a stream. */ @@ -237,8 +229,10 @@ write_png (cairo_surface_t *surface, goto BAIL4; } - if (png_setjmp (png)) +#ifdef PNG_SETJMP_SUPPORTED + if (setjmp (png_jmpbuf (png))) goto BAIL4; +#endif png_set_write_fn (png, closure, write_func, png_simple_output_flush_fn); @@ -345,7 +339,8 @@ stdio_write_func (png_structp png, png_bytep data, png_size_t size) /** * cairo_surface_write_to_png: * @surface: a #cairo_surface_t with pixel contents - * @filename: the name of a file to write to + * @filename: the name of a file to write to; on Windows this filename + * is encoded in UTF-8. * * Writes the contents of @surface to a new file @filename as a PNG * image. @@ -355,7 +350,8 @@ stdio_write_func (png_structp png, png_bytep data, png_size_t size) * be allocated for the operation or * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have * pixel contents, or %CAIRO_STATUS_WRITE_ERROR if an I/O error occurs - * while attempting to write the file. + * while attempting to write the file, or %CAIRO_STATUS_PNG_ERROR if libpng + * returned an error. * * Since: 1.0 **/ @@ -372,7 +368,11 @@ cairo_surface_write_to_png (cairo_surface_t *surface, if (surface->finished) return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); - fp = fopen (filename, "wb"); + status = _cairo_fopen (filename, "wb", &fp); + + if (status != CAIRO_STATUS_SUCCESS) + return _cairo_error (status); + if (fp == NULL) { switch (errno) { case ENOMEM: @@ -423,7 +423,8 @@ stream_write_func (png_structp png, png_bytep data, png_size_t size) * successfully. Otherwise, %CAIRO_STATUS_NO_MEMORY is returned if * memory could not be allocated for the operation, * %CAIRO_STATUS_SURFACE_TYPE_MISMATCH if the surface does not have - * pixel contents. + * pixel contents, or %CAIRO_STATUS_PNG_ERROR if libpng + * returned an error. * * Since: 1.0 **/ @@ -543,11 +544,11 @@ stream_read_func (png_structp png, png_bytep data, png_size_t size) static cairo_surface_t * read_png (struct png_read_closure_t *png_closure) { - cairo_surface_t *surface; + cairo_surface_t * volatile surface; png_struct *png = NULL; png_info *info; - png_byte *data = NULL; - png_byte **row_pointers = NULL; + png_byte * volatile data = NULL; + png_byte ** volatile row_pointers = NULL; png_uint_32 png_width, png_height; int depth, color_type, interlace, stride; unsigned int i; @@ -577,11 +578,12 @@ read_png (struct png_read_closure_t *png_closure) png_set_read_fn (png, png_closure, stream_read_func); status = CAIRO_STATUS_SUCCESS; - - if (png_setjmp (png)) { +#ifdef PNG_SETJMP_SUPPORTED + if (setjmp (png_jmpbuf (png))) { surface = _cairo_surface_create_in_error (status); goto BAIL; } +#endif png_read_info (png, info); @@ -676,7 +678,7 @@ read_png (struct png_read_closure_t *png_closure) } for (i = 0; i < png_height; i++) - row_pointers[i] = &data[i * stride]; + row_pointers[i] = &data[i * (ptrdiff_t)stride]; png_read_image (png, row_pointers); png_read_end (png, info); @@ -736,7 +738,8 @@ read_png (struct png_read_closure_t *png_closure) /** * cairo_image_surface_create_from_png: - * @filename: name of PNG file to load + * @filename: name of PNG file to load. On Windows this filename + * is encoded in UTF-8. * * Creates a new image surface and initializes the contents to the * given PNG file. @@ -749,6 +752,7 @@ read_png (struct png_read_closure_t *png_closure) * %CAIRO_STATUS_NO_MEMORY * %CAIRO_STATUS_FILE_NOT_FOUND * %CAIRO_STATUS_READ_ERROR + * %CAIRO_STATUS_PNG_ERROR * * Alternatively, you can allow errors to propagate through the drawing * operations and check the status on the context upon completion @@ -761,10 +765,14 @@ cairo_image_surface_create_from_png (const char *filename) { struct png_read_closure_t png_closure; cairo_surface_t *surface; + cairo_status_t status; + + status = _cairo_fopen (filename, "rb", (FILE **) &png_closure.closure); + + if (status != CAIRO_STATUS_SUCCESS) + return _cairo_surface_create_in_error (status); - png_closure.closure = fopen (filename, "rb"); if (png_closure.closure == NULL) { - cairo_status_t status; switch (errno) { case ENOMEM: status = _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -804,6 +812,7 @@ cairo_image_surface_create_from_png (const char *filename) * * %CAIRO_STATUS_NO_MEMORY * %CAIRO_STATUS_READ_ERROR + * %CAIRO_STATUS_PNG_ERROR * * Alternatively, you can allow errors to propagate through the drawing * operations and check the status on the context upon completion diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-polygon-intersect.c b/Build/source/libs/cairo/cairo-src/src/cairo-polygon-intersect.c index 8cb8fb1208b..001e55ee06a 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-polygon-intersect.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-polygon-intersect.c @@ -447,7 +447,7 @@ edges_compare_x_for_y (const cairo_bo_edge_t *a, HAVE_BX = 0x2, HAVE_BOTH = HAVE_AX | HAVE_BX } have_ax_bx = HAVE_BOTH; - int32_t ax, bx; + int32_t ax = 0, bx = 0; if (y == a->edge.line.p1.y) ax = a->edge.line.p1.x; @@ -1107,13 +1107,14 @@ edges_start_or_continue (cairo_bo_edge_t *left, int top, cairo_polygon_t *polygon) { + assert (right != NULL); assert (right->deferred.other == NULL); if (left->deferred.other == right) return; if (left->deferred.other != NULL) { - if (right != NULL && edges_colinear (left->deferred.other, right)) { + if (edges_colinear (left->deferred.other, right)) { cairo_bo_edge_t *old = left->deferred.other; /* continuation on right, extend right to cover both */ @@ -1131,7 +1132,7 @@ edges_start_or_continue (cairo_bo_edge_t *left, edges_end (left, top, polygon); } - if (right != NULL && ! edges_colinear (left, right)) { + if (! edges_colinear (left, right)) { left->deferred.top = top; left->deferred.other = right; } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-polygon-reduce.c b/Build/source/libs/cairo/cairo-src/src/cairo-polygon-reduce.c index ea457fe4edf..da6c9ab7c78 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-polygon-reduce.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-polygon-reduce.c @@ -445,7 +445,7 @@ edges_compare_x_for_y (const cairo_bo_edge_t *a, HAVE_BX = 0x2, HAVE_BOTH = HAVE_AX | HAVE_BX } have_ax_bx = HAVE_BOTH; - int32_t ax, bx; + int32_t ax = 0, bx = 0; if (y == a->edge.line.p1.y) ax = a->edge.line.p1.x; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-polygon.c b/Build/source/libs/cairo/cairo-src/src/cairo-polygon.c index b0424f6e72e..0e0b8132853 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-polygon.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-polygon.c @@ -248,7 +248,7 @@ _cairo_polygon_fini (cairo_polygon_t *polygon) if (polygon->edges != polygon->edges_embedded) free (polygon->edges); - VG (VALGRIND_MAKE_MEM_NOACCESS (polygon, sizeof (cairo_polygon_t))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (polygon, sizeof (cairo_polygon_t))); } /* make room for at least one more edge */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-ps-surface-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-ps-surface-private.h index 1d5d27d4910..e1681c8894c 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-ps-surface-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-ps-surface-private.h @@ -49,6 +49,19 @@ #include +typedef struct _cairo_ps_form { + cairo_hash_entry_t base; + unsigned char *unique_id; + unsigned long unique_id_length; + cairo_bool_t is_image; + int id; + cairo_surface_t *src_surface; + cairo_filter_t filter; + + /* Union of source extents required for all operations using this form */ + cairo_rectangle_int_t required_extents; +} cairo_ps_form_t; + typedef struct cairo_ps_surface { cairo_surface_t base; @@ -63,14 +76,15 @@ typedef struct cairo_ps_surface { cairo_output_stream_t *stream; cairo_bool_t eps; + cairo_bool_t contains_eps; cairo_content_t content; double width; double height; - cairo_rectangle_int_t page_bbox; - int bbox_x1, bbox_y1, bbox_x2, bbox_y2; + cairo_point_int_t document_bbox_p1, document_bbox_p2; /* in PS coordinates */ + cairo_rectangle_int_t surface_extents; + cairo_bool_t surface_bounded; cairo_matrix_t cairo_to_ps; - - cairo_bool_t use_string_datasource; + cairo_bool_t paint_proc; /* TRUE if surface will be used in a PaintProc */ cairo_bool_t current_pattern_is_solid_color; cairo_color_t current_color; @@ -90,6 +104,8 @@ typedef struct cairo_ps_surface { cairo_array_t dsc_setup_comments; cairo_array_t dsc_page_setup_comments; + cairo_array_t recording_surf_stack; + cairo_array_t *dsc_comment_target; cairo_ps_level_t ps_level; @@ -99,6 +115,9 @@ typedef struct cairo_ps_surface { cairo_pdf_operators_t pdf_operators; cairo_surface_t *paginated_surface; + cairo_hash_table_t *forms; + int num_forms; + long total_form_size; } cairo_ps_surface_t; #endif /* CAIRO_PS_SURFACE_PRIVATE_H */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-ps-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-ps-surface.c index 3b66b275d82..0a17b81afe3 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-ps-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-ps-surface.c @@ -77,6 +77,7 @@ #include "cairo-output-stream-private.h" #include "cairo-type3-glyph-surface-private.h" #include "cairo-image-info-private.h" +#include "cairo-tag-attributes-private.h" #include #include @@ -84,7 +85,14 @@ #include #include -#define DEBUG_PS 0 +/* Forms are emitted at the start and stored in memory so we limit the + * total size of all forms to prevent running out of memory. If this + * limit is exceeded, surfaces that would be stored in forms are + * emitted each time the surface is used. */ +#define MAX_L2_FORM_DATA (256*1024) +#define MAX_L3_FORM_DATA (2*1024*1024) /* Assume Level 3 printers have more memory */ + +/* #define DEBUG_PS 1 */ #if DEBUG_PS #define DEBUG_FALLBACK(s) \ @@ -105,11 +113,44 @@ * * The PostScript surface is used to render cairo graphics to Adobe * PostScript files and is a multi-page vector surface backend. + * + * The following mime types are supported: %CAIRO_MIME_TYPE_JPEG, + * %CAIRO_MIME_TYPE_UNIQUE_ID, + * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, + * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, + * %CAIRO_MIME_TYPE_EPS, %CAIRO_MIME_TYPE_EPS_PARAMS. + * + * Source surfaces used by the PostScript surface that have a + * %CAIRO_MIME_TYPE_UNIQUE_ID mime type will be stored in PostScript + * printer memory for the duration of the print + * job. %CAIRO_MIME_TYPE_UNIQUE_ID should only be used for small + * frequently used sources. + * + * The %CAIRO_MIME_TYPE_CCITT_FAX and %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS mime types + * are documented in [CCITT Fax Images][ccitt]. + * + * # Embedding EPS files # {#eps} + * + * Encapsulated PostScript files can be embedded in the PS output by + * setting the CAIRO_MIME_TYPE_EPS mime data on a surface to the EPS + * data and painting the surface. The EPS will be scaled and + * translated to the extents of the surface the EPS data is attached + * to. + * + * The %CAIRO_MIME_TYPE_EPS mime type requires the + * %CAIRO_MIME_TYPE_EPS_PARAMS mime data to also be provided in order + * to specify the embeddding parameters. %CAIRO_MIME_TYPE_EPS_PARAMS + * mime data must contain a string of the form "bbox=[llx lly urx + * ury]" that specifies the bounding box (in PS coordinates) of the + * EPS graphics. The parameters are: lower left x, lower left y, upper + * right x, upper right y. Normally the bbox data is identical to the + * %%%BoundingBox data in the EPS file. + * **/ /** * CAIRO_HAS_PS_SURFACE: - * + * * Defined if the PostScript surface backend is available. * This macro can be used to conditionally compile backend-specific code. * @@ -120,7 +161,30 @@ typedef enum { CAIRO_PS_COMPRESS_NONE, CAIRO_PS_COMPRESS_LZW, CAIRO_PS_COMPRESS_DEFLATE - } cairo_ps_compress_t; +} cairo_ps_compress_t; + +typedef enum { + CAIRO_EMIT_SURFACE_ANALYZE, + CAIRO_EMIT_SURFACE_EMIT, + CAIRO_EMIT_SURFACE_EMIT_FORM +} cairo_emit_surface_mode_t; + +typedef struct { + /* input params */ + cairo_surface_t *src_surface; + cairo_operator_t op; + const cairo_rectangle_int_t *src_surface_extents; + cairo_bool_t src_surface_bounded; + const cairo_rectangle_int_t *src_op_extents; /* operation extents in src space */ + cairo_filter_t filter; + cairo_bool_t stencil_mask; /* TRUE if source is to be used as a mask */ + + /* output params */ + cairo_bool_t is_image; /* returns TRUE if PS image will be emitted */ + /* FALSE if recording will be emitted */ + long approx_size; + int eod_count; +} cairo_emit_surface_params_t; static const cairo_surface_backend_t cairo_ps_surface_backend; static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backend; @@ -129,6 +193,9 @@ static cairo_bool_t _cairo_ps_surface_get_extents (void *abstract_surface, cairo_rectangle_int_t *rectangle); +static void +_cairo_ps_form_emit (void *entry, void *closure); + static const cairo_ps_level_t _cairo_ps_levels[] = { CAIRO_PS_LEVEL_2, @@ -146,6 +213,8 @@ static const char * _cairo_ps_level_strings[CAIRO_PS_LEVEL_LAST] = static const char *_cairo_ps_supported_mime_types[] = { CAIRO_MIME_TYPE_JPEG, + CAIRO_MIME_TYPE_CCITT_FAX, + CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, NULL }; @@ -183,6 +252,40 @@ typedef struct _cairo_page_media { cairo_list_t link; } cairo_page_media_t; +static void +_cairo_ps_form_init_key (cairo_ps_form_t *key) +{ + key->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE, + key->unique_id, key->unique_id_length); +} + +static cairo_bool_t +_cairo_ps_form_equal (const void *key_a, const void *key_b) +{ + const cairo_ps_form_t *a = key_a; + const cairo_ps_form_t *b = key_b; + + if (a->filter != b->filter) + return FALSE; + + if (a->unique_id_length != b->unique_id_length) + return FALSE; + + return memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0; +} + +static void +_cairo_ps_form_pluck (void *entry, void *closure) +{ + cairo_ps_form_t *surface_entry = entry; + cairo_hash_table_t *patterns = closure; + + _cairo_hash_table_remove (patterns, &surface_entry->base); + free (surface_entry->unique_id); + cairo_surface_destroy (surface_entry->src_surface); + free (surface_entry); +} + static void _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) { @@ -209,7 +312,7 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) _cairo_output_stream_printf (surface->final_stream, "%%!PS-Adobe-3.0%s\n" - "%%%%Creator: cairo %s (http://cairographics.org)\n" + "%%%%Creator: cairo %s (https://cairographics.org)\n" "%%%%CreationDate: %s" "%%%%Pages: %d\n", eps_header, @@ -259,10 +362,10 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) if (!has_bbox) { _cairo_output_stream_printf (surface->final_stream, "%%%%BoundingBox: %d %d %d %d\n", - surface->bbox_x1, - surface->bbox_y1, - surface->bbox_x2, - surface->bbox_y2); + surface->document_bbox_p1.x, + surface->document_bbox_p1.y, + surface->document_bbox_p2.x, + surface->document_bbox_p2.y); } _cairo_output_stream_printf (surface->final_stream, @@ -273,7 +376,6 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) if (surface->eps) { _cairo_output_stream_printf (surface->final_stream, - "save\n" "50 dict begin\n"); } else { _cairo_output_stream_printf (surface->final_stream, @@ -309,9 +411,6 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) "/W* { eoclip } bind def\n" "/BT { } bind def\n" "/ET { } bind def\n" - "/pdfmark where { pop globaldict /?pdfmark /exec load put }\n" - " { globaldict begin /?pdfmark /pop load def /pdfmark\n" - " /cleartomark load def end } ifelse\n" "/BDC { mark 3 1 roll /BDC pdfmark } bind def\n" "/EMC { mark /EMC pdfmark } bind def\n" "/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def\n" @@ -336,6 +435,11 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) "/g { setgray } bind def\n" "/rg { setrgbcolor } bind def\n" "/d1 { setcachedevice } bind def\n" + "/cairo_data_source {\n" + " CairoDataIndex CairoData length lt\n" + " { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def }\n" + " { () } ifelse\n" + "} def\n" "/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def\n" "/cairo_image { image cairo_flush_ascii85_file } def\n" "/cairo_imagemask { imagemask cairo_flush_ascii85_file } def\n"); @@ -374,11 +478,25 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface) " } ifelse\n" "} def\n"); } + if (surface->contains_eps) { + _cairo_output_stream_printf (surface->final_stream, + "/cairo_eps_begin {\n" + " /cairo_save_state save def\n" + " /dict_count countdictstack def\n" + " /op_count count 1 sub def\n" + " userdict begin\n" + " /showpage { } def\n" + " 0 g 0 J 1 w 0 j 10 M [ ] 0 d n\n" + "} bind def\n" + "/cairo_eps_end {\n" + " count op_count sub { pop } repeat\n" + " countdictstack dict_count sub { end } repeat\n" + " cairo_save_state restore\n" + "} bind def\n"); + } _cairo_output_stream_printf (surface->final_stream, "%%%%EndProlog\n"); - _cairo_output_stream_printf (surface->final_stream, - "%%%%BeginSetup\n"); num_comments = _cairo_array_num_elements (&surface->dsc_setup_comments); if (num_comments) { @@ -673,7 +791,7 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface, _cairo_output_stream_printf (surface->final_stream, "8 dict begin\n" "/FontType 3 def\n" - "/FontMatrix [1 0 0 1 0 0] def\n" + "/FontMatrix [1 0 0 -1 0 0] def\n" "/Encoding 256 array def\n" "0 1 255 { Encoding exch /.notdef put } for\n"); @@ -836,6 +954,16 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface) surface); } + +static cairo_int_status_t +_cairo_ps_surface_emit_forms (cairo_ps_surface_t *surface) +{ + _cairo_hash_table_foreach (surface->forms, + _cairo_ps_form_emit, + surface); + return surface->base.status; +} + static cairo_status_t _cairo_ps_surface_emit_body (cairo_ps_surface_t *surface) { @@ -863,7 +991,7 @@ _cairo_ps_surface_emit_footer (cairo_ps_surface_t *surface) if (surface->eps) { _cairo_output_stream_printf (surface->final_stream, - "end restore\n"); + "end\n"); } _cairo_output_stream_printf (surface->final_stream, @@ -882,11 +1010,11 @@ _path_covers_bbox (cairo_ps_surface_t *surface, _cairo_box_round_to_rectangle (&box, &rect); /* skip trivial whole-page clips */ - if (_cairo_rectangle_intersect (&rect, &surface->page_bbox)) { - if (rect.x == surface->page_bbox.x && - rect.width == surface->page_bbox.width && - rect.y == surface->page_bbox.y && - rect.height == surface->page_bbox.height) + if (_cairo_rectangle_intersect (&rect, &surface->surface_extents)) { + if (rect.x == surface->surface_extents.x && + rect.width == surface->surface_extents.width && + rect.y == surface->surface_extents.y && + rect.height == surface->surface_extents.height) { return TRUE; } @@ -975,7 +1103,7 @@ _cairo_ps_surface_get_page_media (cairo_ps_surface_t *surface) } } - page = malloc (sizeof (cairo_page_media_t)); + page = _cairo_malloc (sizeof (cairo_page_media_t)); if (unlikely (page == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; @@ -1011,7 +1139,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, cairo_status_t status, status_ignored; cairo_ps_surface_t *surface; - surface = malloc (sizeof (cairo_ps_surface_t)); + surface = _cairo_malloc (sizeof (cairo_ps_surface_t)); if (unlikely (surface == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP; @@ -1020,7 +1148,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, _cairo_surface_init (&surface->base, &cairo_ps_surface_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + TRUE); /* is_vector */ surface->final_stream = stream; @@ -1055,17 +1184,23 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->ps_level_used = CAIRO_PS_LEVEL_2; surface->width = width; surface->height = height; - cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, height); + cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, 1, 0, 0); + surface->surface_extents.x = 0; + surface->surface_extents.y = 0; + surface->surface_extents.width = ceil (surface->width); + surface->surface_extents.height = ceil (surface->height); + surface->surface_bounded = TRUE; surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE; surface->force_fallbacks = FALSE; surface->content = CAIRO_CONTENT_COLOR_ALPHA; - surface->use_string_datasource = FALSE; surface->current_pattern_is_solid_color = FALSE; - - surface->page_bbox.x = 0; - surface->page_bbox.y = 0; - surface->page_bbox.width = width; - surface->page_bbox.height = height; + surface->document_bbox_p1.x = 0; + surface->document_bbox_p1.y = 0; + surface->document_bbox_p2.x = 0; + surface->document_bbox_p2.y = 0; + surface->total_form_size = 0; + surface->contains_eps = FALSE; + surface->paint_proc = FALSE; _cairo_surface_clipper_init (&surface->clipper, _cairo_ps_surface_clipper_intersect_clip_path); @@ -1081,6 +1216,14 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, _cairo_array_init (&surface->dsc_header_comments, sizeof (char *)); _cairo_array_init (&surface->dsc_setup_comments, sizeof (char *)); _cairo_array_init (&surface->dsc_page_setup_comments, sizeof (char *)); + _cairo_array_init (&surface->recording_surf_stack, sizeof (unsigned int)); + + surface->num_forms = 0; + surface->forms = _cairo_hash_table_create (_cairo_ps_form_equal); + if (unlikely (surface->forms == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto CLEANUP_FONT_SUBSETS; + } surface->dsc_comment_target = &surface->dsc_header_comments; @@ -1095,6 +1238,7 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, return surface->paginated_surface; } + CLEANUP_FONT_SUBSETS: _cairo_scaled_font_subsets_destroy (surface->font_subsets); CLEANUP_OUTPUT_STREAM: status_ignored = _cairo_output_stream_destroy (surface->stream); @@ -1403,7 +1547,11 @@ cairo_ps_surface_set_size (cairo_surface_t *surface, ps_surface->width = width_in_points; ps_surface->height = height_in_points; - cairo_matrix_init (&ps_surface->cairo_to_ps, 1, 0, 0, -1, 0, height_in_points); + cairo_matrix_init (&ps_surface->cairo_to_ps, 1, 0, 0, 1, 0, 0); + ps_surface->surface_extents.x = 0; + ps_surface->surface_extents.y = 0; + ps_surface->surface_extents.width = ceil (ps_surface->width); + ps_surface->surface_extents.height = ceil (ps_surface->height); _cairo_pdf_operators_set_cairo_to_pdf_matrix (&ps_surface->pdf_operators, &ps_surface->cairo_to_ps); status = _cairo_paginated_surface_set_size (ps_surface->paginated_surface, @@ -1613,10 +1761,17 @@ _cairo_ps_surface_finish (void *abstract_surface) _cairo_ps_surface_emit_header (surface); + _cairo_output_stream_printf (surface->final_stream, + "%%%%BeginSetup\n"); + status = _cairo_ps_surface_emit_font_subsets (surface); if (unlikely (status)) goto CLEANUP; + status = _cairo_ps_surface_emit_forms (surface); + if (unlikely (status)) + goto CLEANUP; + _cairo_output_stream_printf (surface->final_stream, "%%%%EndSetup\n"); @@ -1627,6 +1782,10 @@ _cairo_ps_surface_finish (void *abstract_surface) _cairo_ps_surface_emit_footer (surface); CLEANUP: + _cairo_hash_table_foreach (surface->forms, + _cairo_ps_form_pluck, + surface->forms); + _cairo_hash_table_destroy (surface->forms); _cairo_scaled_font_subsets_destroy (surface->font_subsets); status2 = _cairo_output_stream_destroy (surface->stream); @@ -1668,6 +1827,8 @@ CLEANUP: free (comments[i]); _cairo_array_fini (&surface->dsc_page_setup_comments); + _cairo_array_fini (&surface->recording_surf_stack); + _cairo_surface_clipper_reset (&surface->clipper); return status; @@ -1715,133 +1876,97 @@ color_is_gray (double red, double green, double blue) /** * _cairo_ps_surface_acquire_source_surface_from_pattern: - * @surface: the ps surface - * @pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source - * @extents: extents of the operation that is using this source - * @width: returns width of surface - * @height: returns height of surface - * @x_offset: returns x offset of surface - * @y_offset: returns y offset of surface - * @surface: returns surface of type image surface or recording surface - * @image_extra: returns image extra for image type surface + * @surface: [in] the ps surface + * @pattern: [in] A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use + * as the source + * @extents: [in] extents of the operation that is using this source + * @src_surface_extents: [out] return source surface extents + * @src_surface_bounded: [out] return TRUE if source surface is bounded + * @src_op_extents: [out] return operation extents in source space + * @source_surface: [out] returns surface of type image surface or recording surface + * @x_offset: [out] return x offset of surface + * @y_offset: [out] return y offset of surface * * Acquire source surface or raster source pattern. **/ static cairo_status_t -_cairo_ps_surface_acquire_source_surface_from_pattern (cairo_ps_surface_t *surface, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents, - int *width, - int *height, - double *x_offset, - double *y_offset, - cairo_surface_t **source_surface, - void **image_extra) +_cairo_ps_surface_acquire_source_surface_from_pattern ( + cairo_ps_surface_t *surface, + const cairo_pattern_t *pattern, + const cairo_rectangle_int_t *extents, + cairo_rectangle_int_t *src_surface_extents, + cairo_bool_t *src_surface_bounded, + cairo_rectangle_int_t *src_op_extents, + cairo_surface_t **source_surface, + double *x_offset, + double *y_offset) { - cairo_status_t status; - cairo_image_surface_t *image; + cairo_status_t status; + cairo_box_t bbox; - *x_offset = *y_offset = 0; - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SURFACE: { - cairo_surface_t *surf = ((cairo_surface_pattern_t *) pattern)->surface; + *x_offset = 0; + *y_offset = 0; + + /* get the operation extents in pattern space */ + _cairo_box_from_rectangle (&bbox, extents); + _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &bbox, NULL); + _cairo_box_round_to_rectangle (&bbox, src_op_extents); + + if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) { + cairo_surface_t *surf; + + surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, src_op_extents); + if (!surf) + return CAIRO_INT_STATUS_UNSUPPORTED; + *src_surface_bounded = _cairo_surface_get_extents (surf, src_surface_extents); + cairo_surface_get_device_offset (surf, x_offset, y_offset); + *source_surface = surf; + } else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { + cairo_surface_t *surf = NULL; + + *source_surface = ((cairo_surface_pattern_t *) pattern)->surface; + surf = *source_surface; + *src_surface_bounded = _cairo_surface_get_extents (surf, src_surface_extents); if (surf->type == CAIRO_SURFACE_TYPE_RECORDING) { + if (_cairo_surface_is_snapshot (surf)) + surf = _cairo_surface_snapshot_get_target (surf); + if (surf->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) surf; - *width = sub->extents.width; - *height = sub->extents.height; - } else { - cairo_surface_t *free_me = NULL; - cairo_recording_surface_t *recording_surface; - cairo_box_t bbox; - cairo_rectangle_int_t extents; - - recording_surface = (cairo_recording_surface_t *) surf; - if (_cairo_surface_is_snapshot (&recording_surface->base)) { - free_me = _cairo_surface_snapshot_get_target (&recording_surface->base); - recording_surface = (cairo_recording_surface_t *) free_me; - } - - status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL); - cairo_surface_destroy (free_me); - if (unlikely (status)) - return status; - - _cairo_box_round_to_rectangle (&bbox, &extents); - *width = extents.width; - *height = extents.height; + *src_surface_extents = sub->extents; + *src_surface_bounded = TRUE; + *x_offset = -sub->extents.x; + *y_offset = -sub->extents.y; } - *source_surface = surf; - return CAIRO_STATUS_SUCCESS; - } else { - status = _cairo_surface_acquire_source_image (surf, &image, image_extra); + cairo_surface_destroy (surf); + } else if (surf->type != CAIRO_SURFACE_TYPE_IMAGE) { + cairo_image_surface_t *image; + void *image_extra; + + status = _cairo_surface_acquire_source_image (surf, &image, &image_extra); if (unlikely (status)) return status; - } - } break; - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: { - cairo_surface_t *surf; - cairo_box_t box; - cairo_rectangle_int_t rect; - - /* get the operation extents in pattern space */ - _cairo_box_from_rectangle (&box, extents); - _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &box, NULL); - _cairo_box_round_to_rectangle (&box, &rect); - surf = _cairo_raster_source_pattern_acquire (pattern, &surface->base, &rect); - if (!surf) - return CAIRO_INT_STATUS_UNSUPPORTED; - assert (_cairo_surface_is_image (surf)); - image = (cairo_image_surface_t *) surf; - } break; - - case CAIRO_PATTERN_TYPE_SOLID: - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - case CAIRO_PATTERN_TYPE_MESH: - default: + *src_surface_bounded = _cairo_surface_get_extents (&image->base, src_surface_extents); + _cairo_surface_release_source_image (surf, image, image_extra); + } + } else { ASSERT_NOT_REACHED; - break; } - *width = image->width; - *height = image->height; - *source_surface = &image->base; return CAIRO_STATUS_SUCCESS; } static void _cairo_ps_surface_release_source_surface_from_pattern (cairo_ps_surface_t *surface, const cairo_pattern_t *pattern, - cairo_surface_t *source, - void *image_extra) + cairo_surface_t *source_surface) { - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SURFACE: { - cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern; - if (surf_pat->surface->type != CAIRO_SURFACE_TYPE_RECORDING) { - cairo_image_surface_t *image = (cairo_image_surface_t *) source; - _cairo_surface_release_source_image (surf_pat->surface, image, image_extra); - } - } break; - - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: - _cairo_raster_source_pattern_release (pattern, source); - break; - - case CAIRO_PATTERN_TYPE_SOLID: - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - case CAIRO_PATTERN_TYPE_MESH: - default: - - ASSERT_NOT_REACHED; - break; - } + if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) + _cairo_raster_source_pattern_release (pattern, source_surface); } /** @@ -1849,11 +1974,8 @@ _cairo_ps_surface_release_source_surface_from_pattern (cairo_ps_surface_t * @surface: the ps surface * @source: The source image * @extents: extents of the operation that is using this source - * @width: returns width of padded image - * @height: returns height of padded image - * @x_offset: returns x offset of padded image - * @y_offset: returns y offset of padded image * @image: returns the padded image or NULL if padding not required to fill @extents + * @image_extents: returns extents of padded image. These extents in are in source image space. * * Creates a padded image if the source image does not fill the extents. **/ @@ -1862,11 +1984,8 @@ _cairo_ps_surface_create_padded_image_from_image (cairo_ps_surface_t * cairo_image_surface_t *source, const cairo_matrix_t *source_matrix, const cairo_rectangle_int_t *extents, - int *width, - int *height, - double *x_offset, - double *y_offset, - cairo_image_surface_t **image) + cairo_image_surface_t **image, + cairo_rectangle_int_t *image_extents) { cairo_box_t box; cairo_rectangle_int_t rect; @@ -1888,11 +2007,9 @@ _cairo_ps_surface_create_padded_image_from_image (cairo_ps_surface_t * _cairo_fixed_integer_floor(box.p2.y) > w || _cairo_fixed_integer_floor(box.p2.y) > h) { - pad_image = - _cairo_image_surface_create_with_pixman_format (NULL, - source->pixman_format, - rect.width, rect.height, - 0); + pad_image = _cairo_image_surface_create_with_content (source->base.content, + rect.width, + rect.height); if (pad_image->status) return pad_image->status; @@ -1905,10 +2022,10 @@ _cairo_ps_surface_create_padded_image_from_image (cairo_ps_surface_t * NULL); _cairo_pattern_fini (&pad_pattern.base); *image = (cairo_image_surface_t *) pad_image; - *width = rect.width; - *height = rect.height; - *x_offset = rect.x; - *y_offset = rect.y; + image_extents->x = rect.x; + image_extents->y = rect.y; + image_extents->width = rect.width; + image_extents->height = rect.height; } else { *image = NULL; status = CAIRO_STATUS_SUCCESS; @@ -1922,27 +2039,32 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t const cairo_pattern_t *pattern, const cairo_rectangle_int_t *extents) { - int width, height; + cairo_rectangle_int_t src_surface_extents; + cairo_bool_t src_surface_bounded; + cairo_rectangle_int_t src_op_extents; + cairo_surface_t *source_surface; double x_offset, y_offset; - cairo_surface_t *source; cairo_image_surface_t *image; void *image_extra; - cairo_int_status_t status; + cairo_int_status_t status; cairo_image_transparency_t transparency; status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface, pattern, extents, - &width, - &height, + &src_surface_extents, + &src_surface_bounded, + &src_op_extents, + &source_surface, &x_offset, - &y_offset, - &source, - &image_extra); + &y_offset); + if (unlikely (status)) + return status; + + status = _cairo_surface_acquire_source_image (source_surface, &image, &image_extra); if (unlikely (status)) return status; - image = (cairo_image_surface_t *) source; if (image->base.status) return image->base.status; @@ -1969,7 +2091,8 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t ASSERT_NOT_REACHED; } - _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra); + _cairo_surface_release_source_image (source_surface, image, image_extra); + _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source_surface); return status; } @@ -2156,14 +2279,9 @@ _cairo_ps_surface_operation_supported (cairo_ps_surface_t *surface, /* The "standard" implementation limit for PostScript string sizes is * 65535 characters (see PostScript Language Reference, Appendix - * B). We go one short of that because we sometimes need two - * characters in a string to represent a single ASCII85 byte, (for the - * escape sequences "\\", "\(", and "\)") and we must not split these - * across two strings. So we'd be in trouble if we went right to the - * limit and one of these escape sequences just happened to land at - * the end. + * B). */ -#define STRING_ARRAY_MAX_STRING_SIZE (65535-1) +#define STRING_ARRAY_MAX_STRING_SIZE 65535 #define STRING_ARRAY_MAX_COLUMN 72 typedef struct _string_array_stream { @@ -2171,64 +2289,62 @@ typedef struct _string_array_stream { cairo_output_stream_t *output; int column; int string_size; + int tuple_count; cairo_bool_t use_strings; } string_array_stream_t; static cairo_status_t -_string_array_stream_write (cairo_output_stream_t *base, - const unsigned char *data, - unsigned int length) +_base85_string_wrap_stream_write (cairo_output_stream_t *base, + const unsigned char *data, + unsigned int length) { string_array_stream_t *stream = (string_array_stream_t *) base; unsigned char c; - const unsigned char backslash = '\\'; if (length == 0) return CAIRO_STATUS_SUCCESS; while (length--) { - if (stream->string_size == 0 && stream->use_strings) { - _cairo_output_stream_printf (stream->output, "("); - stream->column++; - } - - c = *data++; - if (stream->use_strings) { - switch (c) { - case '\\': - case '(': - case ')': - _cairo_output_stream_write (stream->output, &backslash, 1); - stream->column++; - stream->string_size++; - break; + if (stream->column == 0) { + if (stream->use_strings) { + _cairo_output_stream_printf (stream->output, "<~"); + stream->column = 2; + } else { + _cairo_output_stream_printf (stream->output, " "); + stream->column = 1; } } - /* Have to be careful to never split the final ~> sequence. */ - if (c == '~') { - _cairo_output_stream_write (stream->output, &c, 1); - stream->column++; - stream->string_size++; - - if (length-- == 0) - break; - c = *data++; - } + c = *data++; _cairo_output_stream_write (stream->output, &c, 1); stream->column++; - stream->string_size++; + /* Base85 encodes each 4 byte tuple with a 5 ASCII character + * tuple, except for 'z' with represents 4 zero bytes. We need + * to keep track of the string length after decoding. + */ + if (c == 'z') { + stream->string_size += 4; + stream->tuple_count = 0; + } else { + if (++stream->tuple_count == 5) { + stream->string_size += 4; + stream->tuple_count = 0; + } + } + + /* Split string at tuple boundary when there is not enough + * space for another tuple */ if (stream->use_strings && - stream->string_size >= STRING_ARRAY_MAX_STRING_SIZE) + stream->tuple_count == 0 && + stream->string_size > STRING_ARRAY_MAX_STRING_SIZE - 4) { - _cairo_output_stream_printf (stream->output, ")\n"); + _cairo_output_stream_printf (stream->output, "~>\n"); stream->string_size = 0; stream->column = 0; } if (stream->column >= STRING_ARRAY_MAX_COLUMN) { _cairo_output_stream_printf (stream->output, "\n "); - stream->string_size += 2; stream->column = 1; } } @@ -2237,78 +2353,75 @@ _string_array_stream_write (cairo_output_stream_t *base, } static cairo_status_t -_string_array_stream_close (cairo_output_stream_t *base) +_base85_string_wrap_stream_close (cairo_output_stream_t *base) { - cairo_status_t status; string_array_stream_t *stream = (string_array_stream_t *) base; - if (stream->use_strings) - _cairo_output_stream_printf (stream->output, ")\n"); - - status = _cairo_output_stream_get_status (stream->output); + if (!stream->use_strings || stream->string_size != 0) + _cairo_output_stream_printf (stream->output, "~>"); - return status; + return _cairo_output_stream_get_status (stream->output); } -/* A string_array_stream wraps an existing output stream. It takes the - * data provided to it and output one or more consecutive string - * objects, each within the standard PostScript implementation limit - * of 65k characters. - * - * The strings are each separated by a space character for easy - * inclusion within an array object, (but the array delimiters are not - * added by the string_array_stream). - * +/* A _base85_strings_stream wraps an existing output stream. It takes + * base85 encoded data and splits it into strings each limited to + * STRING_ARRAY_MAX_STRING_SIZE bytes when decoded. Each string is + * enclosed in "<~" and "~>". + * The string array stream is also careful to wrap the output within - * STRING_ARRAY_MAX_COLUMN columns (+/- 1). The stream also adds - * necessary escaping for special characters within a string, - * (specifically '\', '(', and ')'). + * STRING_ARRAY_MAX_COLUMN columns. Wrapped lines start with a space + * in case an encoded line starts with %% which could be interpreted + * as a DSC comment. */ static cairo_output_stream_t * -_string_array_stream_create (cairo_output_stream_t *output) +_base85_strings_stream_create (cairo_output_stream_t *output) { string_array_stream_t *stream; - stream = malloc (sizeof (string_array_stream_t)); + stream = _cairo_malloc (sizeof (string_array_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; } _cairo_output_stream_init (&stream->base, - _string_array_stream_write, + _base85_string_wrap_stream_write, NULL, - _string_array_stream_close); + _base85_string_wrap_stream_close); stream->output = output; stream->column = 0; stream->string_size = 0; + stream->tuple_count = 0; stream->use_strings = TRUE; return &stream->base; } -/* A base85_array_stream wraps an existing output stream. It wraps the - * output within STRING_ARRAY_MAX_COLUMN columns (+/- 1). The output - * is not enclosed in strings like string_array_stream. +/* A base85_wrap_stream wraps an existing output stream. It wraps the + * output within STRING_ARRAY_MAX_COLUMN columns. A base85 EOD "~>" is + * appended to the end. Wrapped lines start with a space in case an + * encoded line starts with %% which could be interpreted as a DSC + * comment. */ static cairo_output_stream_t * -_base85_array_stream_create (cairo_output_stream_t *output) +_base85_wrap_stream_create (cairo_output_stream_t *output) { string_array_stream_t *stream; - stream = malloc (sizeof (string_array_stream_t)); + stream = _cairo_malloc (sizeof (string_array_stream_t)); if (unlikely (stream == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_output_stream_t *) &_cairo_output_stream_nil; } _cairo_output_stream_init (&stream->base, - _string_array_stream_write, + _base85_string_wrap_stream_write, NULL, - _string_array_stream_close); + _base85_string_wrap_stream_close); stream->output = output; stream->column = 0; stream->string_size = 0; + stream->tuple_count = 0; stream->use_strings = FALSE; return &stream->base; @@ -2370,9 +2483,9 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, cairo_status_t status, status2; if (use_strings) - string_array_stream = _string_array_stream_create (surface->stream); + string_array_stream = _base85_strings_stream_create (surface->stream); else - string_array_stream = _base85_array_stream_create (surface->stream); + string_array_stream = _base85_wrap_stream_create (surface->stream); status = _cairo_output_stream_get_status (string_array_stream); if (unlikely (status)) @@ -2419,9 +2532,6 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, break; } status = _cairo_output_stream_destroy (base85_stream); - - /* Mark end of base85 data */ - _cairo_output_stream_printf (string_array_stream, "~>"); status2 = _cairo_output_stream_destroy (string_array_stream); if (status == CAIRO_STATUS_SUCCESS) status = status2; @@ -2429,12 +2539,32 @@ _cairo_ps_surface_emit_base85_string (cairo_ps_surface_t *surface, return status; } +static const char * +get_interpolate (cairo_filter_t filter) +{ + const char *interpolate; + + switch (filter) { + default: + case CAIRO_FILTER_GOOD: + case CAIRO_FILTER_BEST: + case CAIRO_FILTER_BILINEAR: + interpolate = "true"; + break; + case CAIRO_FILTER_FAST: + case CAIRO_FILTER_NEAREST: + case CAIRO_FILTER_GAUSSIAN: + interpolate = "false"; + break; + } + + return interpolate; +} + static cairo_status_t -_cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, - cairo_image_surface_t *image_surf, - cairo_operator_t op, - cairo_filter_t filter, - cairo_bool_t stencil_mask) +_cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, + cairo_emit_surface_mode_t mode, + cairo_emit_surface_params_t *params) { cairo_status_t status; unsigned char *data; @@ -2450,10 +2580,16 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, const char *interpolate; cairo_ps_compress_t compress; const char *compress_filter; + cairo_image_surface_t *image_surf; cairo_image_surface_t *image; + void *image_extra; + + if (params->src_surface->status) + return params->src_surface->status; - if (image_surf->base.status) - return image_surf->base.status; + status = _cairo_surface_acquire_source_image (params->src_surface, &image_surf, &image_extra); + if (unlikely (status)) + return status; image = image_surf; if (image->format != CAIRO_FORMAT_RGB24 && @@ -2464,16 +2600,16 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, cairo_surface_t *surf; cairo_surface_pattern_t pattern; - surf = _cairo_image_surface_create_with_content (image_surf->base.content, - image_surf->width, - image_surf->height); + surf = _cairo_image_surface_create_with_content (image->base.content, + image->width, + image->height); image = (cairo_image_surface_t *) surf; if (surf->status) { status = surf->status; goto bail0; } - _cairo_pattern_init_for_surface (&pattern, &image_surf->base); + _cairo_pattern_init_for_surface (&pattern, &image->base); status = _cairo_surface_paint (surf, CAIRO_OPERATOR_SOURCE, &pattern.base, NULL); @@ -2482,22 +2618,9 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, goto bail0; } ps_image = image; + interpolate = get_interpolate (params->filter); - switch (filter) { - default: - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_BILINEAR: - interpolate = "true"; - break; - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - case CAIRO_FILTER_GAUSSIAN: - interpolate = "false"; - break; - } - - if (stencil_mask) { + if (params->stencil_mask) { use_mask = FALSE; color = CAIRO_IMAGE_IS_MONOCHROME; transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA; @@ -2508,7 +2631,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, current image over a white (or black for CONTENT_COLOR surfaces) RGB surface to eliminate it. */ - if (op == CAIRO_OPERATOR_SOURCE || + if (params->op == CAIRO_OPERATOR_SOURCE || transparency == CAIRO_IMAGE_HAS_ALPHA || (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA && surface->ps_level == CAIRO_PS_LEVEL_2)) @@ -2550,7 +2673,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, if (use_mask) data_size += (ps_image->width + 7)/8; data_size *= ps_image->height; - data = malloc (data_size); + data = _cairo_malloc (data_size); if (unlikely (data == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto bail1; @@ -2558,7 +2681,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, i = 0; for (y = 0; y < ps_image->height; y++) { - if (stencil_mask || use_mask) { + if (params->stencil_mask || use_mask) { /* mask row */ if (ps_image->format == CAIRO_FORMAT_A1) { pixel8 = (uint8_t *) (ps_image->data + y * ps_image->stride); @@ -2599,7 +2722,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, i++; } } - if (stencil_mask) + if (params->stencil_mask) continue; /* image row*/ @@ -2664,11 +2787,11 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, surface->ps_level_used = CAIRO_PS_LEVEL_3; } - if (surface->use_string_datasource) { + if (surface->paint_proc) { /* Emit the image data as a base85-encoded string which will * be used as the data source for the image operator later. */ _cairo_output_stream_printf (surface->stream, - "/CairoImageData [\n"); + "/CairoData [\n"); status = _cairo_ps_surface_emit_base85_string (surface, data, @@ -2681,7 +2804,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, _cairo_output_stream_printf (surface->stream, "] def\n"); _cairo_output_stream_printf (surface->stream, - "/CairoImageDataIndex 0 def\n"); + "/CairoDataIndex 0 def\n"); } else { _cairo_output_stream_printf (surface->stream, "/cairo_ascii85_file currentfile /ASCII85Decode filter def\n"); @@ -2690,17 +2813,16 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, if (use_mask) { _cairo_output_stream_printf (surface->stream, "%s setcolorspace\n" - "5 dict dup begin\n" - " /ImageType 3 def\n" - " /InterleaveType 2 def\n" - " /DataDict 8 dict def\n" - " DataDict begin\n" - " /ImageType 1 def\n" - " /Width %d def\n" - " /Height %d def\n" - " /Interpolate %s def\n" - " /BitsPerComponent %d def\n" - " /Decode [ %s ] def\n", + "<<\n" + " /ImageType 3\n" + " /InterleaveType 2\n" + " /DataDict <<\n" + " /ImageType 1\n" + " /Width %d\n" + " /Height %d\n" + " /Interpolate %s\n" + " /BitsPerComponent %d\n" + " /Decode [ %s ]\n", color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray", ps_image->width, ps_image->height, @@ -2708,85 +2830,89 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface, color == CAIRO_IMAGE_IS_MONOCHROME ? 1 : 8, color == CAIRO_IMAGE_IS_COLOR ? "0 1 0 1 0 1" : "0 1"); - if (surface->use_string_datasource) { + if (surface->paint_proc) { _cairo_output_stream_printf (surface->stream, - " /DataSource {\n" - " CairoImageData CairoImageDataIndex get\n" - " /CairoImageDataIndex CairoImageDataIndex 1 add def\n" - " CairoImageDataIndex CairoImageData length 1 sub gt\n" - " { /CairoImageDataIndex 0 def } if\n" - " } /ASCII85Decode filter /%s filter def\n", + " /DataSource { cairo_data_source } /%s filter\n", compress_filter); } else { _cairo_output_stream_printf (surface->stream, - " /DataSource cairo_ascii85_file /%s filter def\n", + " /DataSource cairo_ascii85_file /%s filter\n", compress_filter); } _cairo_output_stream_printf (surface->stream, - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" - " end\n" - " /MaskDict 8 dict def\n" - " MaskDict begin\n" - " /ImageType 1 def\n" - " /Width %d def\n" - " /Height %d def\n" - " /Interpolate %s def\n" - " /BitsPerComponent 1 def\n" - " /Decode [ 1 0 ] def\n" - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" - " end\n" - "end\n" + " /ImageMatrix [ %d 0 0 %d 0 %d ]\n" + " >>\n" + " /MaskDict <<\n" + " /ImageType 1\n" + " /Width %d\n" + " /Height %d\n" + " /Interpolate %s\n" + " /BitsPerComponent 1\n" + " /Decode [ 1 0 ]\n" + " /ImageMatrix [ %d 0 0 %d 0 %d ]\n" + " >>\n" + ">>\n" "image\n", + ps_image->width, + -ps_image->height, ps_image->height, ps_image->width, ps_image->height, interpolate, + ps_image->width, + -ps_image->height, ps_image->height); } else { - if (!stencil_mask) { + const char *decode; + + if (!params->stencil_mask) { _cairo_output_stream_printf (surface->stream, "%s setcolorspace\n", color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray"); } + if (params->stencil_mask) + decode = "1 0"; + else if (color == CAIRO_IMAGE_IS_COLOR) + decode = "0 1 0 1 0 1"; + else + decode ="0 1"; + _cairo_output_stream_printf (surface->stream, - "8 dict dup begin\n" - " /ImageType 1 def\n" - " /Width %d def\n" - " /Height %d def\n" - " /Interpolate %s def\n" - " /BitsPerComponent %d def\n" - " /Decode [ %s ] def\n", + "<<\n" + " /ImageType 1\n" + " /Width %d\n" + " /Height %d\n" + " /Interpolate %s\n" + " /BitsPerComponent %d\n" + " /Decode [ %s ]\n", ps_image->width, ps_image->height, interpolate, color == CAIRO_IMAGE_IS_MONOCHROME ? 1 : 8, - stencil_mask ? "1 0" : color == CAIRO_IMAGE_IS_COLOR ? "0 1 0 1 0 1" : "0 1"); - if (surface->use_string_datasource) { + decode); + if (surface->paint_proc) { _cairo_output_stream_printf (surface->stream, - " /DataSource {\n" - " CairoImageData CairoImageDataIndex get\n" - " /CairoImageDataIndex CairoImageDataIndex 1 add def\n" - " CairoImageDataIndex CairoImageData length 1 sub gt\n" - " { /CairoImageDataIndex 0 def } if\n" - " } /ASCII85Decode filter /%s filter def\n", + " /DataSource { cairo_data_source } /%s filter\n", compress_filter); } else { _cairo_output_stream_printf (surface->stream, - " /DataSource cairo_ascii85_file /%s filter def\n", + " /DataSource cairo_ascii85_file /%s filter\n", compress_filter); } _cairo_output_stream_printf (surface->stream, - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" - "end\n" + " /ImageMatrix [ %d 0 0 %d 0 %d ]\n" + ">>\n" "%s%s\n", + ps_image->width, + -ps_image->height, ps_image->height, - surface->use_string_datasource ? "" : "cairo_", - stencil_mask ? "imagemask" : "image"); + surface->paint_proc ? "" : "cairo_", + params->stencil_mask ? "imagemask" : "image"); } - if (!surface->use_string_datasource) { + if (!surface->paint_proc) { /* Emit the image data as a base85-encoded string which will * be used as the data source for the image operator. */ status = _cairo_ps_surface_emit_base85_string (surface, @@ -2810,14 +2936,15 @@ bail0: if (image != image_surf) cairo_surface_destroy (&image->base); + _cairo_surface_release_source_image (params->src_surface, image_surf, image_extra); + return status; } -static cairo_status_t -_cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface, - cairo_surface_t *source, - int width, - int height) +static cairo_int_status_t +_cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface, + cairo_emit_surface_mode_t mode, + cairo_emit_surface_params_t *params) { cairo_status_t status; const unsigned char *mime_data; @@ -2826,10 +2953,11 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface, const char *colorspace; const char *decode; - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG, + if (unlikely (params->src_surface->status)) + return params->src_surface->status; + + cairo_surface_get_mime_data (params->src_surface, CAIRO_MIME_TYPE_JPEG, &mime_data, &mime_data_length); - if (unlikely (source->status)) - return source->status; if (mime_data == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -2854,11 +2982,18 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; } - if (surface->use_string_datasource) { + /* At this point we know emitting jpeg will succeed. */ + if (mode == CAIRO_EMIT_SURFACE_ANALYZE) { + params->is_image = TRUE; + params->approx_size = mime_data_length; + return CAIRO_STATUS_SUCCESS; + } + + if (surface->paint_proc) { /* Emit the image data as a base85-encoded string which will * be used as the data source for the image operator later. */ _cairo_output_stream_printf (surface->stream, - "/CairoImageData [\n"); + "/CairoData [\n"); status = _cairo_ps_surface_emit_base85_string (surface, mime_data, @@ -2871,7 +3006,7 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface, _cairo_output_stream_printf (surface->stream, "] def\n"); _cairo_output_stream_printf (surface->stream, - "/CairoImageDataIndex 0 def\n"); + "/CairoDataIndex 0 def\n"); } else { _cairo_output_stream_printf (surface->stream, "/cairo_ascii85_file currentfile /ASCII85Decode filter def\n"); @@ -2879,39 +3014,38 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface, _cairo_output_stream_printf (surface->stream, "%s setcolorspace\n" - "8 dict dup begin\n" - " /ImageType 1 def\n" - " /Width %d def\n" - " /Height %d def\n" - " /BitsPerComponent %d def\n" - " /Decode [ %s ] def\n", + "<<\n" + " /ImageType 1\n" + " /Width %d\n" + " /Height %d\n" + " /BitsPerComponent %d\n" + " /Interpolate %s\n" + " /Decode [ %s ]\n", colorspace, info.width, info.height, info.bits_per_component, + get_interpolate (params->filter), decode); - if (surface->use_string_datasource) { + if (surface->paint_proc) { _cairo_output_stream_printf (surface->stream, - " /DataSource {\n" - " CairoImageData CairoImageDataIndex get\n" - " /CairoImageDataIndex CairoImageDataIndex 1 add def\n" - " CairoImageDataIndex CairoImageData length 1 sub gt\n" - " { /CairoImageDataIndex 0 def } if\n" - " } /ASCII85Decode filter /DCTDecode filter def\n"); + " /DataSource { cairo_data_source } /DCTDecode filter\n"); } else { _cairo_output_stream_printf (surface->stream, - " /DataSource cairo_ascii85_file /DCTDecode filter def\n"); + " /DataSource cairo_ascii85_file /DCTDecode filter\n"); } _cairo_output_stream_printf (surface->stream, - " /ImageMatrix [ 1 0 0 -1 0 %d ] def\n" - "end\n" + " /ImageMatrix [ %d 0 0 %d 0 %d ]\n" + ">>\n" "%simage\n", + info.width, + -info.height, info.height, - surface->use_string_datasource ? "" : "cairo_"); + surface->paint_proc ? "" : "cairo_"); - if (!surface->use_string_datasource) { + if (!surface->paint_proc) { /* Emit the image data as a base85-encoded string which will * be used as the data source for the image operator. */ status = _cairo_ps_surface_emit_base85_string (surface, @@ -2924,117 +3058,309 @@ _cairo_ps_surface_emit_jpeg_image (cairo_ps_surface_t *surface, return status; } -static cairo_status_t -_cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface, - cairo_surface_t *recording_surface) +static cairo_int_status_t +_cairo_ps_surface_emit_ccitt_image (cairo_ps_surface_t *surface, + cairo_emit_surface_mode_t mode, + cairo_emit_surface_params_t *params) { - double old_width, old_height; - cairo_matrix_t old_cairo_to_ps; - cairo_content_t old_content; - cairo_rectangle_int_t old_page_bbox; - cairo_surface_t *free_me = NULL; - cairo_surface_clipper_t old_clipper; - cairo_box_t bbox; - cairo_int_status_t status; + cairo_status_t status; + const unsigned char *ccitt_data; + unsigned long ccitt_data_len; + const unsigned char *ccitt_params_data; + unsigned long ccitt_params_data_len; + char *ccitt_params_string; + cairo_ccitt_params_t ccitt_params; + + if (unlikely (params->src_surface->status)) + return params->src_surface->status; + + cairo_surface_get_mime_data (params->src_surface, CAIRO_MIME_TYPE_CCITT_FAX, + &ccitt_data, &ccitt_data_len); + if (ccitt_data == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; - old_content = surface->content; - old_width = surface->width; - old_height = surface->height; - old_page_bbox = surface->page_bbox; - old_cairo_to_ps = surface->cairo_to_ps; - old_clipper = surface->clipper; - _cairo_surface_clipper_init (&surface->clipper, - _cairo_ps_surface_clipper_intersect_clip_path); + cairo_surface_get_mime_data (params->src_surface, CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, + &ccitt_params_data, &ccitt_params_data_len); + if (ccitt_params_data == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; - if (_cairo_surface_is_snapshot (recording_surface)) - free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface); + /* ensure params_string is null terminated */ + ccitt_params_string = malloc (ccitt_params_data_len + 1); + memcpy (ccitt_params_string, ccitt_params_data, ccitt_params_data_len); + ccitt_params_string[ccitt_params_data_len] = 0; + status = _cairo_tag_parse_ccitt_params (ccitt_params_string, &ccitt_params); + if (unlikely(status)) + return status; - status = - _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface, - &bbox, - NULL); - if (unlikely (status)) - goto err; + free (ccitt_params_string); -#if DEBUG_PS - _cairo_output_stream_printf (surface->stream, - "%% _cairo_ps_surface_emit_recording_surface (%f, %f), (%f, %f)\n", - _cairo_fixed_to_double (bbox.p1.x), - _cairo_fixed_to_double (bbox.p1.y), - _cairo_fixed_to_double (bbox.p2.x), - _cairo_fixed_to_double (bbox.p2.y)); -#endif + if (ccitt_params.columns <= 0 || ccitt_params.rows <= 0) + return CAIRO_INT_STATUS_UNSUPPORTED; - surface->width = _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x); - surface->height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y); - _cairo_box_round_to_rectangle (&bbox, &surface->page_bbox); + /* At this point we know emitting ccitt will succeed. */ + if (mode == CAIRO_EMIT_SURFACE_ANALYZE) { + params->is_image = TRUE; + params->approx_size = ccitt_data_len; + return CAIRO_STATUS_SUCCESS; + } - surface->current_pattern_is_solid_color = FALSE; - _cairo_pdf_operators_reset (&surface->pdf_operators); - cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, surface->height); - _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, - &surface->cairo_to_ps); - _cairo_output_stream_printf (surface->stream, " q\n"); + if (surface->paint_proc) { + /* Emit the image data as a base85-encoded string which will + * be used as the data source for the image operator later. */ + _cairo_output_stream_printf (surface->stream, + "/CairoData [\n"); + + status = _cairo_ps_surface_emit_base85_string (surface, + ccitt_data, + ccitt_data_len, + CAIRO_PS_COMPRESS_NONE, + TRUE); + if (unlikely (status)) + return status; - if (recording_surface->content == CAIRO_CONTENT_COLOR) { - surface->content = CAIRO_CONTENT_COLOR; _cairo_output_stream_printf (surface->stream, - " 0 g %d %d %d %d rectfill\n", - surface->page_bbox.x, - surface->page_bbox.y, - surface->page_bbox.width, - surface->page_bbox.height); + "] def\n"); + _cairo_output_stream_printf (surface->stream, + "/CairoDataIndex 0 def\n"); + } else { + _cairo_output_stream_printf (surface->stream, + "/cairo_ascii85_file currentfile /ASCII85Decode filter def\n"); } - status = _cairo_recording_surface_replay_region (recording_surface, - NULL, - &surface->base, - CAIRO_RECORDING_REGION_NATIVE); - assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - if (unlikely (status)) - goto err; + if (!params->stencil_mask) { + _cairo_output_stream_printf (surface->stream, + "/DeviceGray setcolorspace\n"); + } - status = _cairo_pdf_operators_flush (&surface->pdf_operators); - if (unlikely (status)) - goto err; + _cairo_output_stream_printf (surface->stream, + "<<\n" + " /ImageType 1\n" + " /Width %d\n" + " /Height %d\n" + " /BitsPerComponent 1\n" + " /Interpolate %s\n" + " /Decode [ 0 1 ]\n", + ccitt_params.columns, + ccitt_params.rows, + get_interpolate (params->filter)); + + if (surface->paint_proc) { + _cairo_output_stream_printf (surface->stream, + " /DataSource { cairo_data_source }\n"); + } else { + _cairo_output_stream_printf (surface->stream, + " /DataSource cairo_ascii85_file\n"); + } - _cairo_output_stream_printf (surface->stream, " Q\n"); + _cairo_output_stream_printf (surface->stream, + " << /Columns %d /Rows %d /K %d\n", + ccitt_params.columns, + ccitt_params.rows, + ccitt_params.k); - _cairo_surface_clipper_reset (&surface->clipper); - surface->clipper = old_clipper; - surface->content = old_content; - surface->width = old_width; - surface->height = old_height; - surface->page_bbox = old_page_bbox; - surface->current_pattern_is_solid_color = FALSE; - _cairo_pdf_operators_reset (&surface->pdf_operators); - surface->cairo_to_ps = old_cairo_to_ps; + if (ccitt_params.end_of_line) + _cairo_output_stream_printf (surface->stream, " /EndOfLine true\n"); - _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, - &surface->cairo_to_ps); + if (ccitt_params.encoded_byte_align) + _cairo_output_stream_printf (surface->stream, " /EncodedByteAlign true\n"); + + if (!ccitt_params.end_of_block) + _cairo_output_stream_printf (surface->stream, " /EndOfBlock false\n"); + + if (ccitt_params.black_is_1) + _cairo_output_stream_printf (surface->stream, " /BlackIs1 true\n"); + + if (ccitt_params.damaged_rows_before_error > 0) { + _cairo_output_stream_printf (surface->stream, + " /DamagedRowsBeforeError %d\n", + ccitt_params.damaged_rows_before_error); + } + + _cairo_output_stream_printf (surface->stream, + " >> /CCITTFaxDecode filter\n"); + + _cairo_output_stream_printf (surface->stream, + " /ImageMatrix [ %d 0 0 %d 0 %d ]\n" + ">>\n" + "%s%s\n", + ccitt_params.columns, + -ccitt_params.rows, + ccitt_params.rows, + surface->paint_proc ? "" : "cairo_", + params->stencil_mask ? "imagemask" : "image"); + + if (!surface->paint_proc) { + /* Emit the image data as a base85-encoded string which will + * be used as the data source for the image operator. */ + status = _cairo_ps_surface_emit_base85_string (surface, + ccitt_data, + ccitt_data_len, + CAIRO_PS_COMPRESS_NONE, + FALSE); + } -err: - cairo_surface_destroy (free_me); return status; } -static cairo_int_status_t -_cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface, - cairo_surface_t *recording_surface, - const cairo_rectangle_int_t *extents) +/* The '|' character is not used in PS (including ASCII85). We can + * speed up the search by first searching for the first char before + * comparing strings. + */ +#define SUBFILE_FILTER_EOD "|EOD|" + +/* Count number of non overlapping occurrences of SUBFILE_FILTER_EOD in data. */ +static int +count_eod_strings (const unsigned char *data, unsigned long data_len) +{ + const unsigned char *p = data; + const unsigned char *end; + int first_char, len, count; + const char *eod_str = SUBFILE_FILTER_EOD; + + first_char = eod_str[0]; + len = strlen (eod_str); + p = data; + end = data + data_len - len + 1; + count = 0; + while (p < end) { + p = memchr (p, first_char, end - p); + if (!p) + break; + + if (memcmp (p, eod_str, len) == 0) { + count++; + p += len; + } + } + + return count; +} + +static cairo_status_t +_cairo_ps_surface_emit_eps (cairo_ps_surface_t *surface, + cairo_emit_surface_mode_t mode, + cairo_emit_surface_params_t *params) +{ + cairo_status_t status; + const unsigned char *eps_data = NULL; + unsigned long eps_data_len; + const unsigned char *eps_params_string = NULL; + unsigned long eps_params_string_len; + char *params_string = NULL; + cairo_eps_params_t eps_params; + cairo_matrix_t mat; + double eps_width, eps_height; + + if (unlikely (params->src_surface->status)) + return params->src_surface->status; + + /* We only embed EPS with level 3 as we may use ReusableStreamDecode and we + * don't know what level the EPS file requires. */ + if (surface->ps_level == CAIRO_PS_LEVEL_2) + return CAIRO_INT_STATUS_UNSUPPORTED; + + cairo_surface_get_mime_data (params->src_surface, CAIRO_MIME_TYPE_EPS, + &eps_data, &eps_data_len); + if (eps_data == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + + cairo_surface_get_mime_data (params->src_surface, CAIRO_MIME_TYPE_EPS_PARAMS, + &eps_params_string, &eps_params_string_len); + if (eps_params_string == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + + /* ensure params_string is null terminated */ + params_string = malloc (eps_params_string_len + 1); + memcpy (params_string, eps_params_string, eps_params_string_len); + params_string[eps_params_string_len] = 0; + status = _cairo_tag_parse_eps_params (params_string, &eps_params); + if (unlikely(status)) + return status; + + /* At this point we know emitting EPS will succeed. */ + if (mode == CAIRO_EMIT_SURFACE_ANALYZE) { + params->is_image = FALSE; + params->approx_size = eps_data_len; + surface->contains_eps = TRUE; + + /* Find number of occurrences of SUBFILE_FILTER_EOD in the EPS data. + * We will need it before emitting the data if a ReusableStream is used. + */ + params->eod_count = count_eod_strings (eps_data, eps_data_len); + return CAIRO_STATUS_SUCCESS; + } + + surface->ps_level_used = CAIRO_PS_LEVEL_3; + _cairo_output_stream_printf (surface->stream, "cairo_eps_begin\n"); + + eps_width = eps_params.bbox.p2.x - eps_params.bbox.p1.x; + eps_height = eps_params.bbox.p2.y - eps_params.bbox.p1.y; + cairo_matrix_init_translate (&mat, + params->src_surface_extents->x, + params->src_surface_extents->y); + cairo_matrix_scale (&mat, + params->src_surface_extents->width/eps_width, + params->src_surface_extents->height/eps_height); + cairo_matrix_scale (&mat, 1, -1); + cairo_matrix_translate (&mat, -eps_params.bbox.p1.x, -eps_params.bbox.p2.y); + + if (! _cairo_matrix_is_identity (&mat)) { + _cairo_output_stream_printf (surface->stream, "[ "); + _cairo_output_stream_print_matrix (surface->stream, &mat); + _cairo_output_stream_printf (surface->stream, " ] concat\n"); + } + + _cairo_output_stream_printf (surface->stream, + "%f %f %f %f rectclip\n", + eps_params.bbox.p1.x, + eps_params.bbox.p1.y, + eps_width, + eps_height); + + _cairo_output_stream_write (surface->stream, eps_data, eps_data_len); + _cairo_output_stream_printf (surface->stream, "\ncairo_eps_end\n"); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface, + cairo_surface_t *recording_surface, + const cairo_rectangle_int_t *recording_extents, + cairo_bool_t subsurface) { double old_width, old_height; + cairo_rectangle_int_t old_surface_extents; + cairo_bool_t old_surface_bounded; cairo_matrix_t old_cairo_to_ps; cairo_content_t old_content; - cairo_rectangle_int_t old_page_bbox; cairo_surface_clipper_t old_clipper; - cairo_surface_t *free_me = NULL; cairo_int_status_t status; + cairo_surface_t *free_me = NULL; + unsigned int id; + int i, recording_surf_stack_size; + + /* Prevent infinite recursion if the recording_surface references a recording + * currently being emitted */ + recording_surf_stack_size = _cairo_array_num_elements (&surface->recording_surf_stack); + for (i = 0; i < recording_surf_stack_size; i++) { + _cairo_array_copy_element (&surface->recording_surf_stack, i, &id); + if (id == recording_surface->unique_id) + return CAIRO_STATUS_SUCCESS; + } + id = recording_surface->unique_id; + status = _cairo_array_append (&surface->recording_surf_stack, &id); + if (unlikely (status)) + return status; + + if (_cairo_surface_is_snapshot (recording_surface)) + free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface); old_content = surface->content; old_width = surface->width; old_height = surface->height; - old_page_bbox = surface->page_bbox; + old_surface_extents = surface->surface_extents; + old_surface_bounded = surface->surface_bounded; old_cairo_to_ps = surface->cairo_to_ps; old_clipper = surface->clipper; _cairo_surface_clipper_init (&surface->clipper, @@ -3042,46 +3368,44 @@ _cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface, #if DEBUG_PS _cairo_output_stream_printf (surface->stream, - "%% _cairo_ps_surface_emit_recording_subsurface (%d, %d), (%d, %d)\n", - extents->x, extents->y, - extents->width, extents->height); + "%% _cairo_ps_surface_emit_recording_surface" + " x: %d, y: %d, w: %d, h: %d subsurface: %d\n", + recording_extents->x, recording_extents->y, + recording_extents->width, recording_extents->height, + subsurface); #endif - surface->page_bbox.x = surface->page_bbox.y = 0; - surface->page_bbox.width = surface->width = extents->width; - surface->page_bbox.height = surface->height = extents->height; - + surface->width = recording_extents->width; + surface->height = recording_extents->height; + surface->surface_extents = *recording_extents; surface->current_pattern_is_solid_color = FALSE; _cairo_pdf_operators_reset (&surface->pdf_operators); - cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, surface->height); + cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, 1, 0, 0); _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, &surface->cairo_to_ps); _cairo_output_stream_printf (surface->stream, " q\n"); - if (_cairo_surface_is_snapshot (recording_surface)) - free_me = recording_surface = _cairo_surface_snapshot_get_target (recording_surface); - if (recording_surface->content == CAIRO_CONTENT_COLOR) { surface->content = CAIRO_CONTENT_COLOR; _cairo_output_stream_printf (surface->stream, " 0 g %d %d %d %d rectfill\n", - surface->page_bbox.x, - surface->page_bbox.y, - surface->page_bbox.width, - surface->page_bbox.height); + recording_extents->x, + recording_extents->y, + recording_extents->width, + recording_extents->height); } status = _cairo_recording_surface_replay_region (recording_surface, - extents, + subsurface ? recording_extents : NULL, &surface->base, CAIRO_RECORDING_REGION_NATIVE); assert (status != CAIRO_INT_STATUS_UNSUPPORTED); if (unlikely (status)) - goto err; + return status; status = _cairo_pdf_operators_flush (&surface->pdf_operators); if (unlikely (status)) - goto err; + return status; _cairo_output_stream_printf (surface->stream, " Q\n"); @@ -3090,16 +3414,18 @@ _cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface, surface->content = old_content; surface->width = old_width; surface->height = old_height; - surface->page_bbox = old_page_bbox; + surface->surface_extents = old_surface_extents; + surface->surface_bounded = old_surface_bounded; surface->current_pattern_is_solid_color = FALSE; _cairo_pdf_operators_reset (&surface->pdf_operators); surface->cairo_to_ps = old_cairo_to_ps; _cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators, &surface->cairo_to_ps); - -err: cairo_surface_destroy (free_me); + + _cairo_array_truncate (&surface->recording_surf_stack, recording_surf_stack_size); + return status; } @@ -3145,44 +3471,351 @@ _cairo_ps_surface_emit_solid_pattern (cairo_ps_surface_t *surface, red, green, blue); } -static cairo_status_t -_cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface, - cairo_pattern_t *source_pattern, - cairo_surface_t *source_surface, - cairo_operator_t op, - int width, - int height, - cairo_bool_t stencil_mask) +/* + * PS Forms are used for sources that have CAIRO_MIME_TYPE_UNIQUE_ID. They will be + * emitted once in the PS header and can be rendered with the 'execform' operator. + * + * This function tries adding the source the form hash table. If the source does not + * have CAIRO_MIME_TYPE_UNIQUE_ID, CAIRO_INT_STATUS_UNSUPPORTED is returned. + + * @source: [in] the source for the form + * @params: [in] source parameters + * @test: [in] if TRUE, test if form will be used (excludes size check) + * @ps_form [out] the new or exisiting entry int the hash table. + * image or recording. + */ +static cairo_int_status_t +_cairo_ps_surface_use_form (cairo_ps_surface_t *surface, + cairo_emit_surface_params_t *params, + cairo_bool_t test, + cairo_ps_form_t **ps_form) +{ + cairo_ps_form_t source_key; + cairo_ps_form_t *source_entry; + unsigned char *unique_id = NULL; + unsigned long unique_id_length = 0; + cairo_status_t status; + long max_size; + + if (params->op != CAIRO_OPERATOR_OVER || params->stencil_mask) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (params->src_surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) + return CAIRO_INT_STATUS_UNSUPPORTED; + + cairo_surface_get_mime_data (params->src_surface, CAIRO_MIME_TYPE_UNIQUE_ID, + (const unsigned char **) &source_key.unique_id, + &source_key.unique_id_length); + if (source_key.unique_id == NULL || source_key.unique_id_length == 0) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (test) + return CAIRO_STATUS_SUCCESS; + + source_key.filter = params->filter; + _cairo_ps_form_init_key (&source_key); + source_entry = _cairo_hash_table_lookup (surface->forms, &source_key.base); + if (source_entry) { + _cairo_rectangle_union (&source_entry->required_extents, params->src_op_extents); + *ps_form = source_entry; + return CAIRO_STATUS_SUCCESS; + } + + if (surface->ps_level == CAIRO_PS_LEVEL_3) + max_size = MAX_L3_FORM_DATA; + else + max_size = MAX_L3_FORM_DATA; + + /* Don't add any more Forms if we exceed the form memory limit */ + if (surface->total_form_size + params->approx_size > max_size) + return CAIRO_INT_STATUS_UNSUPPORTED; + + surface->total_form_size += params->approx_size > max_size; + unique_id = _cairo_malloc (source_key.unique_id_length); + if (unique_id == NULL) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + unique_id_length = source_key.unique_id_length; + memcpy (unique_id, source_key.unique_id, unique_id_length); + + source_entry = calloc (sizeof (cairo_ps_form_t), 1); + if (source_entry == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto fail; + } + + source_entry->unique_id_length = unique_id_length; + source_entry->unique_id = unique_id; + source_entry->id = surface->num_forms++; + source_entry->src_surface = cairo_surface_reference (params->src_surface); + source_entry->required_extents = *params->src_op_extents; + source_entry->filter = params->filter; + source_entry->is_image = params->is_image; + _cairo_ps_form_init_key (source_entry); + status = _cairo_hash_table_insert (surface->forms, &source_entry->base); + if (unlikely(status)) + goto fail; + + *ps_form = source_entry; + return CAIRO_STATUS_SUCCESS; + + fail: + free (unique_id); + free (source_entry); + return status; +} + +static cairo_int_status_t +_cairo_ps_surface_emit_form (cairo_ps_surface_t *surface, + cairo_emit_surface_params_t *params, + cairo_bool_t test) +{ + cairo_ps_form_t *ps_form = NULL; + cairo_status_t status; + + status = _cairo_ps_surface_use_form (surface, + params, + test, + &ps_form); + if (test || status) + return status; + + /* _cairo_ps_form_emit will use Level 3 if permitted by ps_level */ + if (surface->ps_level == CAIRO_PS_LEVEL_3) + surface->ps_level_used = CAIRO_PS_LEVEL_3; + + _cairo_output_stream_printf (surface->stream, + "/cairoform-%d /Form findresource execform\n", + ps_form->id); + + return CAIRO_STATUS_SUCCESS; +} + +/* Emit a surface. This function has three modes. + * + * CAIRO_EMIT_SURFACE_ANALYZE: This will determine the surface type to + * be emitted and approximate size. is_image is set to TRUE if the + * emitted surface is an image surface (including mime images). This + * is used by the caller to setup the correct CTM. approx_size is set + * to the approximate size of the emitted surface and is used as an + * input by the emit mode. + * + * CAIRO_EMIT_SURFACE_EMIT: Emits the surface will be emitted. The + * approx_size and the surface unique id values are used to determine + * if a Form should be used. If a form is used, the exec form + * operation is emitted and the surface is added to the forms hash + * table. + * + * CAIRO_EMIT_SURFACE_EMIT_FORM: Emits the form definition for the surface. + * + * Usage is: + * 1) Setup input params and call with ANALYZE. + * 2) Setup CTM for surface and call with EMIT using same params struct. + * The EMIT_FORM mode is used when emitting the form definitions. + */ +static cairo_int_status_t +_cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface, + cairo_emit_surface_mode_t mode, + cairo_emit_surface_params_t *params) { cairo_int_status_t status; + cairo_output_stream_t *old_stream = NULL; + cairo_bool_t use_form; + + /* Try emitting as a form. Returns unsupported if the surface is + * deemed unsuitable for a form. */ + use_form = FALSE; + if (mode == CAIRO_EMIT_SURFACE_ANALYZE || mode == CAIRO_EMIT_SURFACE_EMIT) { + status = _cairo_ps_surface_emit_form (surface, + params, + mode == CAIRO_EMIT_SURFACE_ANALYZE); + use_form = (status == CAIRO_INT_STATUS_SUCCESS); + if (status != CAIRO_INT_STATUS_SUCCESS && status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; - if (source_pattern->type == CAIRO_PATTERN_TYPE_SURFACE && - source_pattern->extend != CAIRO_EXTEND_PAD) - { - cairo_surface_t *surf = ((cairo_surface_pattern_t *) source_pattern)->surface; + if (mode == CAIRO_EMIT_SURFACE_EMIT && status == CAIRO_INT_STATUS_SUCCESS) + return status; + } + + status = _cairo_ps_surface_emit_eps (surface, mode, params); + if (status == CAIRO_INT_STATUS_SUCCESS) { + params->is_image = FALSE; + goto surface_emitted; + } + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + + status = _cairo_ps_surface_emit_jpeg_image (surface, mode, params); + if (status == CAIRO_INT_STATUS_SUCCESS) { + params->is_image = TRUE; + goto surface_emitted; + } + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; - status = _cairo_ps_surface_emit_jpeg_image (surface, surf, width, height); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) + status = _cairo_ps_surface_emit_ccitt_image (surface, mode, params); + if (status == CAIRO_INT_STATUS_SUCCESS) { + params->is_image = TRUE; + goto surface_emitted; + } + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + + if (mode == CAIRO_EMIT_SURFACE_ANALYZE) { + /* Find size of image or recording surface by emitting to a memory stream */ + status = _cairo_pdf_operators_flush (&surface->pdf_operators); + if (unlikely (status)) return status; + + old_stream = surface->stream; + surface->stream = _cairo_memory_stream_create (); + _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->stream); } - if (source_surface->type == CAIRO_SURFACE_TYPE_RECORDING) { - if (source_surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { - cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source_surface; - status = _cairo_ps_surface_emit_recording_subsurface (surface, sub->target, &sub->extents); + if (params->src_surface->type == CAIRO_SURFACE_TYPE_RECORDING) { + params->is_image = FALSE; + if (params->src_surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { + cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) params->src_surface; + status = _cairo_ps_surface_emit_recording_surface (surface, + sub->target, + &sub->extents, + TRUE); } else { - status = _cairo_ps_surface_emit_recording_surface (surface, source_surface); + status = _cairo_ps_surface_emit_recording_surface (surface, + params->src_surface, + params->src_op_extents, + FALSE); } } else { - cairo_image_surface_t *image = (cairo_image_surface_t *) source_surface; + params->is_image = TRUE; + status = _cairo_ps_surface_emit_image (surface, mode, params); + } + + if (mode == CAIRO_EMIT_SURFACE_ANALYZE) { + unsigned char *data; + unsigned long length; + + status = _cairo_pdf_operators_flush (&surface->pdf_operators); + if (unlikely (status)) + return status; + + status = _cairo_memory_stream_destroy (surface->stream, &data, &length); + free (data); + if (unlikely (status)) + return status; - status = _cairo_ps_surface_emit_image (surface, image, - op, source_pattern->filter, stencil_mask); + params->approx_size = length; + surface->stream = old_stream; + _cairo_pdf_operators_set_stream (&surface->pdf_operators, + surface->stream); } + surface_emitted: + return status; } +static void +_cairo_ps_form_emit (void *entry, void *closure) +{ + cairo_ps_form_t *form = entry; + cairo_ps_surface_t *surface = closure; + cairo_emit_surface_params_t params; + cairo_int_status_t status; + cairo_output_stream_t *old_stream; + + params.src_surface = form->src_surface; + params.op = CAIRO_OPERATOR_OVER; + params.src_op_extents = &form->required_extents; + params.filter = form->filter; + params.stencil_mask = FALSE; + params.is_image = form->is_image; + params.approx_size = 0; + + _cairo_output_stream_printf (surface->final_stream, + "%%%%BeginResource: form cairoform-%d\n", + form->id); + + _cairo_output_stream_printf (surface->final_stream, + "/cairo_paint_form-%d", + form->id); + if (surface->ps_level == CAIRO_PS_LEVEL_3) { + surface->paint_proc = FALSE; + _cairo_output_stream_printf (surface->final_stream, + "\n" + "currentfile\n" + "<< /Filter /SubFileDecode\n" + " /DecodeParms << /EODString (%s) /EODCount 0 >>\n" + ">> /ReusableStreamDecode filter\n", + SUBFILE_FILTER_EOD); + } else { + surface->paint_proc = TRUE; + _cairo_output_stream_printf (surface->final_stream, + " {\n"); + } + _cairo_output_stream_printf (surface->final_stream, + "5 dict begin\n"); + + old_stream = surface->stream; + surface->stream = surface->final_stream; + _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->stream); + status = _cairo_ps_surface_emit_surface (surface, + CAIRO_EMIT_SURFACE_EMIT_FORM, + ¶ms); + status = _cairo_pdf_operators_flush (&surface->pdf_operators); + surface->stream = old_stream; + _cairo_pdf_operators_set_stream (&surface->pdf_operators, surface->stream); + + _cairo_output_stream_printf (surface->final_stream, + "end\n"); + if (surface->ps_level == CAIRO_PS_LEVEL_3) { + _cairo_output_stream_printf (surface->final_stream, + "%s\n" + "def\n", + SUBFILE_FILTER_EOD); + } else { + _cairo_output_stream_printf (surface->final_stream, + "} bind def\n"); + } + + _cairo_output_stream_printf (surface->final_stream, + "\n" + "/cairoform-%d\n" + "<<\n" + " /FormType 1\n", + form->id); + + if (form->is_image) { + _cairo_output_stream_printf (surface->final_stream, + " /BBox [ 0 0 1 1 ]\n"); + } else { + _cairo_output_stream_printf (surface->final_stream, + " /BBox [ %d %d %d %d ]\n", + form->required_extents.x, + form->required_extents.y, + form->required_extents.x + form->required_extents.width, + form->required_extents.y + form->required_extents.height); + } + + _cairo_output_stream_printf (surface->final_stream, + " /Matrix [ 1 0 0 1 0 0 ]\n" + " /PaintProc { pop cairo_paint_form-%d", + form->id); + + if (surface->ps_level == CAIRO_PS_LEVEL_3) { + _cairo_output_stream_printf (surface->final_stream, + " dup 0 setfileposition cvx exec"); + } + _cairo_output_stream_printf (surface->final_stream, + " } bind\n" + ">>\n" + "/Form defineresource pop\n"); + + _cairo_output_stream_printf (surface->final_stream, + "%%%%EndResource\n"); + if (status) + surface->base.status = status; +} static void _path_fixed_init_rectangle (cairo_path_fixed_t *path, @@ -3215,19 +3848,21 @@ _path_fixed_init_rectangle (cairo_path_fixed_t *path, static cairo_status_t _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, - cairo_pattern_t *pattern, + const cairo_pattern_t *pattern, cairo_rectangle_int_t *extents, cairo_operator_t op, cairo_bool_t stencil_mask) { + cairo_rectangle_int_t src_surface_extents; + cairo_bool_t src_surface_bounded; + cairo_rectangle_int_t src_op_extents; + cairo_surface_t *source_surface; + double x_offset, y_offset; cairo_status_t status; - int width, height; cairo_matrix_t cairo_p2d, ps_p2d; cairo_path_fixed_t path; - double x_offset, y_offset; - cairo_surface_t *source; + cairo_emit_surface_params_t params; cairo_image_surface_t *image = NULL; - void *image_extra; status = _cairo_pdf_operators_flush (&surface->pdf_operators); if (unlikely (status)) @@ -3236,10 +3871,12 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface, pattern, extents, - &width, &height, - &x_offset, &y_offset, - &source, - &image_extra); + &src_surface_extents, + &src_surface_bounded, + &src_op_extents, + &source_surface, + &x_offset, + &y_offset); if (unlikely (status)) return status; @@ -3248,16 +3885,18 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, ((cairo_surface_pattern_t *)pattern)->surface->type == CAIRO_SURFACE_TYPE_IMAGE) { cairo_image_surface_t *img; - img = (cairo_image_surface_t *) source; + img = (cairo_image_surface_t *) source_surface; status = _cairo_ps_surface_create_padded_image_from_image (surface, img, &pattern->matrix, extents, - &width, &height, - &x_offset, &y_offset, - &image); + &image, + &src_surface_extents); if (unlikely (status)) goto release_source; + + x_offset = src_surface_extents.x; + y_offset = src_surface_extents.y; } _path_fixed_init_rectangle (&path, extents); @@ -3278,8 +3917,8 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, "%% Fallback Image: x=%f y=%f w=%d h=%d ", -cairo_p2d.x0/x_scale, -cairo_p2d.y0/y_scale, - (int)(width/x_scale), - (int)(height/y_scale)); + (int)(src_surface_extents.width/x_scale), + (int)(src_surface_extents.height/y_scale)); if (x_scale == y_scale) { _cairo_output_stream_printf (surface->stream, "res=%fppi ", @@ -3292,14 +3931,16 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, } _cairo_output_stream_printf (surface->stream, "size=%ld\n", - (long)width*height*3); + (long)src_surface_extents.width * src_surface_extents.height * 3); } else { if (op == CAIRO_OPERATOR_SOURCE) { _cairo_output_stream_printf (surface->stream, - "%d g 0 0 %f %f rectfill\n", + "%d g %d %d %d %d rectfill\n", surface->content == CAIRO_CONTENT_COLOR ? 0 : 1, - surface->width, - surface->height); + surface->surface_extents.x, + surface->surface_extents.y, + surface->surface_extents.width, + surface->surface_extents.height); } } @@ -3310,8 +3951,26 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, ps_p2d = surface->cairo_to_ps; cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d); cairo_matrix_translate (&ps_p2d, x_offset, y_offset); - cairo_matrix_translate (&ps_p2d, 0.0, height); - cairo_matrix_scale (&ps_p2d, 1.0, -1.0); + + params.src_surface = image ? &image->base : source_surface; + params.op = op; + params.src_surface_extents = &src_surface_extents; + params.src_surface_bounded = src_surface_bounded; + params.src_op_extents = &src_op_extents; + params.filter = pattern->filter; + params.stencil_mask = stencil_mask; + params.is_image = FALSE; + params.approx_size = 0; + + status = _cairo_ps_surface_emit_surface (surface, CAIRO_EMIT_SURFACE_ANALYZE, ¶ms); + if (unlikely (status)) + goto release_source; + + if (params.is_image) { + cairo_matrix_translate (&ps_p2d, 0.0, src_surface_extents.height); + cairo_matrix_scale (&ps_p2d, 1.0, -1.0); + cairo_matrix_scale (&ps_p2d, src_surface_extents.width, src_surface_extents.height); + } if (! _cairo_matrix_is_identity (&ps_p2d)) { _cairo_output_stream_printf (surface->stream, "[ "); @@ -3319,18 +3978,13 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface, _cairo_output_stream_printf (surface->stream, " ] concat\n"); } - status = _cairo_ps_surface_emit_surface (surface, - pattern, - image ? &image->base : source, - op, - width, height, - stencil_mask); + status = _cairo_ps_surface_emit_surface (surface, CAIRO_EMIT_SURFACE_EMIT, ¶ms); release_source: if (image) cairo_surface_destroy (&image->base); - _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra); + _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source_surface); return status; } @@ -3342,15 +3996,17 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, cairo_operator_t op) { cairo_status_t status; - int pattern_width = 0; /* squelch bogus compiler warning */ - int pattern_height = 0; /* squelch bogus compiler warning */ double xstep, ystep; + cairo_rectangle_int_t pattern_extents; + cairo_bool_t bounded; cairo_matrix_t cairo_p2d, ps_p2d; - cairo_bool_t old_use_string_datasource; + cairo_bool_t old_paint_proc; double x_offset, y_offset; - cairo_surface_t *source; + cairo_surface_t *source_surface; cairo_image_surface_t *image = NULL; - void *image_extra; + cairo_rectangle_int_t src_op_extents; + cairo_emit_surface_params_t params; + cairo_extend_t extend = cairo_pattern_get_extend (pattern); cairo_p2d = pattern->matrix; status = cairo_matrix_invert (&cairo_p2d); @@ -3360,32 +4016,38 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, status = _cairo_ps_surface_acquire_source_surface_from_pattern (surface, pattern, extents, - &pattern_width, &pattern_height, - &x_offset, &y_offset, - &source, - &image_extra); + &pattern_extents, + &bounded, + &src_op_extents, + &source_surface, + &x_offset, &y_offset); if (unlikely (status)) return status; - if (pattern->extend == CAIRO_EXTEND_PAD) { + if (extend == CAIRO_EXTEND_PAD) { cairo_image_surface_t *img; - assert (source->type == CAIRO_SURFACE_TYPE_IMAGE); - img = (cairo_image_surface_t *) source; + assert (source_surface->type == CAIRO_SURFACE_TYPE_IMAGE); + img = (cairo_image_surface_t *) source_surface; status = _cairo_ps_surface_create_padded_image_from_image (surface, img, &pattern->matrix, extents, - &pattern_width, &pattern_height, - &x_offset, &y_offset, - &image); + &image, + &pattern_extents); if (unlikely (status)) goto release_source; } if (unlikely (status)) goto release_source; - switch (pattern->extend) { + if (!bounded) + { + extend = CAIRO_EXTEND_NONE; + _cairo_rectangle_intersect (&pattern_extents, &src_op_extents); + } + + switch (extend) { case CAIRO_EXTEND_PAD: case CAIRO_EXTEND_NONE: { @@ -3402,7 +4064,8 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, * repeat visibly. */ double x1 = 0.0, y1 = 0.0; - double x2 = surface->width, y2 = surface->height; + double x2 = surface->surface_extents.width; + double y2 = surface->surface_extents.height; _cairo_matrix_transform_bounding_box (&pattern->matrix, &x1, &y1, &x2, &y2, NULL); @@ -3412,16 +4075,16 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, * required an answer that's large enough, we don't really * care if it's not as tight as possible.*/ xstep = ystep = ceil ((x2 - x1) + (y2 - y1) + - pattern_width + pattern_height); + pattern_extents.width + pattern_extents.height); break; } case CAIRO_EXTEND_REPEAT: - xstep = pattern_width; - ystep = pattern_height; + xstep = pattern_extents.width; + ystep = pattern_extents.height; break; case CAIRO_EXTEND_REFLECT: - xstep = pattern_width*2; - ystep = pattern_height*2; + xstep = pattern_extents.width*2; + ystep = pattern_extents.height*2; break; /* All the rest (if any) should have been analyzed away, so these * cases should be unreachable. */ @@ -3432,27 +4095,49 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, } _cairo_output_stream_printf (surface->stream, - "/CairoPattern {\n"); + "/CairoPattern {\n" + "q %d %d %d %d rectclip\n", + pattern_extents.x, pattern_extents.y, + pattern_extents.width, pattern_extents.height); + + if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) + src_op_extents = pattern_extents; + + old_paint_proc = surface->paint_proc; + surface->paint_proc = TRUE; + params.src_surface = image ? &image->base : source_surface; + params.op = op; + params.src_surface_extents = &pattern_extents; + params.src_surface_bounded = bounded; + params.src_op_extents = &src_op_extents; + params.filter = pattern->filter; + params.stencil_mask = FALSE; + params.is_image = FALSE; + params.approx_size = 0; + status = _cairo_ps_surface_emit_surface (surface, CAIRO_EMIT_SURFACE_ANALYZE, ¶ms); + if (unlikely (status)) + goto release_source; + + if (params.is_image) { + _cairo_output_stream_printf (surface->stream, + "[ %d 0 0 %d 0 0 ] concat\n", + pattern_extents.width, pattern_extents.height); + } - old_use_string_datasource = surface->use_string_datasource; - surface->use_string_datasource = TRUE; if (op == CAIRO_OPERATOR_SOURCE) { _cairo_output_stream_printf (surface->stream, - "%d g 0 0 %f %f rectfill\n", + "%d g %d %d %f %f rectfill\n", surface->content == CAIRO_CONTENT_COLOR ? 0 : 1, + pattern_extents.x, pattern_extents.y, xstep, ystep); } - status = _cairo_ps_surface_emit_surface (surface, - pattern, - image ? &image->base : source, - op, - pattern_width, pattern_height, FALSE); + + status = _cairo_ps_surface_emit_surface (surface, CAIRO_EMIT_SURFACE_EMIT, ¶ms); if (unlikely (status)) goto release_source; - surface->use_string_datasource = old_use_string_datasource; _cairo_output_stream_printf (surface->stream, - "} bind def\n"); + " Q } bind def\n"); _cairo_output_stream_printf (surface->stream, "<< /PatternType 1\n" @@ -3462,20 +4147,43 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, " /XStep %f /YStep %f\n", xstep, ystep); - if (pattern->extend == CAIRO_EXTEND_REFLECT) { + if (extend == CAIRO_EXTEND_REFLECT) { + cairo_matrix_t mat; + _cairo_output_stream_printf (surface->stream, - " /BBox [0 0 %d %d]\n" + " /BBox [%d %d %d %d]\n" " /PaintProc {\n" - " pop CairoPattern\n" - " [-1 0 0 1 %d 0] concat CairoPattern\n" - " [ 1 0 0 -1 0 %d] concat CairoPattern\n" - " [-1 0 0 1 %d 0] concat CairoPattern\n" - " CairoPattern\n" - " } bind\n", - pattern_width*2, pattern_height*2, - pattern_width*2, - pattern_height*2, - pattern_width*2); + " pop CairoPattern\n", + pattern_extents.x, + pattern_extents.y, + pattern_extents.x + pattern_extents.width*2, + pattern_extents.y + pattern_extents.height*2); + + cairo_matrix_init_translate (&mat, pattern_extents.x, pattern_extents.y); + cairo_matrix_scale (&mat, -1, 1); + cairo_matrix_translate (&mat, -2*pattern_extents.width, 0); + cairo_matrix_translate (&mat, -pattern_extents.x, -pattern_extents.y); + _cairo_output_stream_printf (surface->stream, " q ["); + _cairo_output_stream_print_matrix (surface->stream, &mat); + _cairo_output_stream_printf (surface->stream, "] concat CairoPattern Q\n"); + + cairo_matrix_init_translate (&mat, pattern_extents.x, pattern_extents.y); + cairo_matrix_scale (&mat, 1, -1); + cairo_matrix_translate (&mat, 0, -2*pattern_extents.height); + cairo_matrix_translate (&mat, -pattern_extents.x, -pattern_extents.y); + _cairo_output_stream_printf (surface->stream, " q ["); + _cairo_output_stream_print_matrix (surface->stream, &mat); + _cairo_output_stream_printf (surface->stream, "] concat CairoPattern Q\n"); + + cairo_matrix_init_translate (&mat, pattern_extents.x, pattern_extents.y); + cairo_matrix_scale (&mat, -1, -1); + cairo_matrix_translate (&mat, -2*pattern_extents.width, -2*pattern_extents.height); + cairo_matrix_translate (&mat, -pattern_extents.x, -pattern_extents.y); + _cairo_output_stream_printf (surface->stream, " q ["); + _cairo_output_stream_print_matrix (surface->stream, &mat); + _cairo_output_stream_printf (surface->stream, "] concat CairoPattern Q\n"); + + _cairo_output_stream_printf (surface->stream, " } bind\n"); } else { if (op == CAIRO_OPERATOR_SOURCE) { _cairo_output_stream_printf (surface->stream, @@ -3483,8 +4191,11 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, xstep, ystep); } else { _cairo_output_stream_printf (surface->stream, - " /BBox [0 0 %d %d]\n", - pattern_width, pattern_height); + " /BBox [%d %d %d %d]\n", + pattern_extents.x, + pattern_extents.y, + pattern_extents.x + pattern_extents.width, + pattern_extents.y + pattern_extents.height); } _cairo_output_stream_printf (surface->stream, " /PaintProc { pop CairoPattern }\n"); @@ -3499,11 +4210,13 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, assert (status == CAIRO_STATUS_SUCCESS); cairo_matrix_init_identity (&ps_p2d); - cairo_matrix_translate (&ps_p2d, 0.0, surface->height); - cairo_matrix_scale (&ps_p2d, 1.0, -1.0); cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d); - cairo_matrix_translate (&ps_p2d, 0.0, pattern_height); - cairo_matrix_scale (&ps_p2d, 1.0, -1.0); + cairo_matrix_translate (&ps_p2d, x_offset, y_offset); + if (((cairo_surface_pattern_t *)pattern)->surface->type != CAIRO_SURFACE_TYPE_RECORDING) + { + cairo_matrix_translate (&ps_p2d, 0.0, pattern_extents.height); + cairo_matrix_scale (&ps_p2d, 1.0, -1.0); + } _cairo_output_stream_printf (surface->stream, "[ "); _cairo_output_stream_print_matrix (surface->stream, &ps_p2d); @@ -3511,11 +4224,13 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface, " ]\n" "makepattern setpattern\n"); + surface->paint_proc = old_paint_proc; + release_source: if (image) cairo_surface_destroy (&image->base); - _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source, image_extra); + _cairo_ps_surface_release_source_surface_from_pattern (surface, pattern, source_surface); return status; } @@ -4098,7 +4813,7 @@ _cairo_ps_surface_paint_pattern (cairo_ps_surface_t *surface, case CAIRO_PATTERN_TYPE_SURFACE: case CAIRO_PATTERN_TYPE_RASTER_SOURCE: return _cairo_ps_surface_paint_surface (surface, - (cairo_pattern_t *)source, + source, extents, op, stencil_mask); @@ -4107,8 +4822,8 @@ _cairo_ps_surface_paint_pattern (cairo_ps_surface_t *surface, case CAIRO_PATTERN_TYPE_RADIAL: case CAIRO_PATTERN_TYPE_MESH: return _cairo_ps_surface_paint_gradient (surface, - source, - extents); + source, + extents); case CAIRO_PATTERN_TYPE_SOLID: default: @@ -4146,17 +4861,10 @@ _cairo_ps_surface_get_extents (void *abstract_surface, { cairo_ps_surface_t *surface = abstract_surface; - rectangle->x = 0; - rectangle->y = 0; - - /* XXX: The conversion to integers here is pretty bogus, (not to - * mention the aribitray limitation of width to a short(!). We - * may need to come up with a better interface for get_extents. - */ - rectangle->width = ceil (surface->width); - rectangle->height = ceil (surface->height); + if (surface->surface_bounded) + *rectangle = surface->surface_extents; - return TRUE; + return surface->surface_bounded; } static void @@ -4240,8 +4948,11 @@ _cairo_ps_surface_paint (void *abstract_surface, if (unlikely (status)) goto cleanup_composite; - _cairo_output_stream_printf (stream, "0 0 %f %f rectfill\n", - surface->width, surface->height); + _cairo_output_stream_printf (stream, "%d %d %d %d rectfill\n", + surface->surface_extents.x, + surface->surface_extents.y, + surface->surface_extents.width, + surface->surface_extents.height); } cleanup_composite: @@ -4536,7 +5247,7 @@ _cairo_ps_surface_get_supported_mime_types (void *abstract_surface) return _cairo_ps_supported_mime_types; } -static void +static cairo_int_status_t _cairo_ps_surface_set_paginated_mode (void *abstract_surface, cairo_paginated_mode_t paginated_mode) { @@ -4545,34 +5256,57 @@ _cairo_ps_surface_set_paginated_mode (void *abstract_surface, surface->paginated_mode = paginated_mode; - if (surface->clipper.clip != NULL) { - status = _cairo_pdf_operators_flush (&surface->pdf_operators); + if (paginated_mode == CAIRO_PAGINATED_MODE_RENDER) { + surface->surface_extents.x = 0; + surface->surface_extents.y = 0; + surface->surface_extents.width = ceil (surface->width); + surface->surface_extents.height = ceil (surface->height); - _cairo_output_stream_printf (surface->stream, "Q q\n"); - _cairo_surface_clipper_reset (&surface->clipper); + if (surface->clipper.clip != NULL) + { + status = _cairo_pdf_operators_flush (&surface->pdf_operators); + + _cairo_output_stream_printf (surface->stream, "Q q\n"); + _cairo_surface_clipper_reset (&surface->clipper); + } } + + return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t _cairo_ps_surface_set_bounding_box (void *abstract_surface, - cairo_box_t *bbox) + cairo_box_t *analysis_bbox) { cairo_ps_surface_t *surface = abstract_surface; int i, num_comments; char **comments; - int x1, y1, x2, y2; cairo_bool_t has_page_media, has_page_bbox; const char *page_media; + cairo_rectangle_int_t page_bbox; + cairo_point_int_t bbox_p1, bbox_p2; /* in PS coordinates */ - x1 = floor (_cairo_fixed_to_double (bbox->p1.x)); - y1 = floor (surface->height - _cairo_fixed_to_double (bbox->p2.y)); - x2 = ceil (_cairo_fixed_to_double (bbox->p2.x)); - y2 = ceil (surface->height - _cairo_fixed_to_double (bbox->p1.y)); + _cairo_box_round_to_rectangle (analysis_bbox, &page_bbox); - surface->page_bbox.x = x1; - surface->page_bbox.y = y1; - surface->page_bbox.width = x2 - x1; - surface->page_bbox.height = y2 - y1; + /* convert to PS coordinates */ + bbox_p1.x = page_bbox.x; + bbox_p1.y = ceil(surface->height) - (page_bbox.y + page_bbox.height); + bbox_p2.x = page_bbox.x + page_bbox.width; + bbox_p2.y = ceil(surface->height) - page_bbox.y; + + if (surface->num_pages == 1) { + surface->document_bbox_p1 = bbox_p1; + surface->document_bbox_p2 = bbox_p2; + } else { + if (bbox_p1.x < surface->document_bbox_p1.x) + surface->document_bbox_p1.x = bbox_p1.x; + if (bbox_p1.y < surface->document_bbox_p1.y) + surface->document_bbox_p1.y = bbox_p1.y; + if (bbox_p2.x < surface->document_bbox_p2.x) + surface->document_bbox_p2.x = bbox_p2.x; + if (bbox_p2.y < surface->document_bbox_p2.y) + surface->document_bbox_p2.y = bbox_p2.y; + } _cairo_output_stream_printf (surface->stream, "%%%%Page: %d %d\n", @@ -4613,7 +5347,10 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface, if (!has_page_bbox) { _cairo_output_stream_printf (surface->stream, "%%%%PageBoundingBox: %d %d %d %d\n", - x1, y1, x2, y2); + bbox_p1.x, + bbox_p1.y, + bbox_p2.x, + bbox_p2.y); } if (!surface->eps) { @@ -4625,27 +5362,14 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface, _cairo_output_stream_printf (surface->stream, "%%%%EndPageSetup\n" - "q %d %d %d %d rectclip q\n", - surface->page_bbox.x, - surface->page_bbox.y, - surface->page_bbox.width, - surface->page_bbox.height); + "q %d %d %d %d rectclip\n" + "1 0 0 -1 0 %f cm q\n", + bbox_p1.x, + bbox_p1.y, + bbox_p2.x - bbox_p1.x, + bbox_p2.y - bbox_p1.y, + ceil(surface->height)); - if (surface->num_pages == 1) { - surface->bbox_x1 = x1; - surface->bbox_y1 = y1; - surface->bbox_x2 = x2; - surface->bbox_y2 = y2; - } else { - if (x1 < surface->bbox_x1) - surface->bbox_x1 = x1; - if (y1 < surface->bbox_y1) - surface->bbox_y1 = y1; - if (x2 > surface->bbox_x2) - surface->bbox_x2 = x2; - if (y2 > surface->bbox_y2) - surface->bbox_y2 = y2; - } surface->current_pattern_is_solid_color = FALSE; _cairo_pdf_operators_reset (&surface->pdf_operators); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-qt-surface.cpp b/Build/source/libs/cairo/cairo-src/src/cairo-qt-surface.cpp index 7ddad77df37..5f669d8be38 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-qt-surface.cpp +++ b/Build/source/libs/cairo/cairo-src/src/cairo-qt-surface.cpp @@ -631,7 +631,7 @@ map_qimage_to_image (QImage *qimg, const cairo_rectangle_int_t *extents) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); } - surface = (struct _qimage_surface *) malloc (sizeof(*surface)); + surface = (struct _qimage_surface *) _cairo_malloc (sizeof(*surface)); if (unlikely (surface == NULL)) { pixman_image_unref (pixman_image); delete qimg; @@ -1216,7 +1216,7 @@ _cairo_qt_fast_fill (cairo_qt_surface_t *qs, cairo_clip_t clip, old_clip = qs->clipper.clip; - _cairo_clip_init_copy (&clip, &qs->clipper.clip); + qs->clipper.clip = _cairo_clip_copy (&clip); status = (cairo_int_status_t) _cairo_clip_clip (&clip, path, fill_rule, @@ -1530,7 +1530,7 @@ cairo_qt_surface_create (QPainter *painter) { cairo_qt_surface_t *qs; - qs = (cairo_qt_surface_t *) malloc (sizeof(cairo_qt_surface_t)); + qs = (cairo_qt_surface_t *) _cairo_malloc (sizeof(cairo_qt_surface_t)); if (qs == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1569,7 +1569,7 @@ cairo_qt_surface_create_with_qimage (cairo_format_t format, { cairo_qt_surface_t *qs; - qs = (cairo_qt_surface_t *) malloc (sizeof(cairo_qt_surface_t)); + qs = (cairo_qt_surface_t *) _cairo_malloc (sizeof(cairo_qt_surface_t)); if (qs == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1618,7 +1618,7 @@ cairo_qt_surface_create_with_qpixmap (cairo_content_t content, if ((content & CAIRO_CONTENT_COLOR) == 0) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - qs = (cairo_qt_surface_t *) malloc (sizeof(cairo_qt_surface_t)); + qs = (cairo_qt_surface_t *) _cairo_malloc (sizeof(cairo_qt_surface_t)); if (qs == NULL) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-font.c b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-font.c index feee61a0d86..8cb71434f89 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-font.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-font.c @@ -81,6 +81,14 @@ static void (*CGFontGetGlyphsForUnicharsPtr) (CGFontRef, const UniChar[], const static void (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL; static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL; +/* Not public in the least bit */ +static CGPathRef (*CGFontGetGlyphPathPtr) (CGFontRef fontRef, CGAffineTransform *textTransform, int unknown, CGGlyph glyph) = NULL; + +/* CTFontCreateWithGraphicsFont is not available until 10.5 */ +typedef const struct __CTFontDescriptor *CTFontDescriptorRef; +static CTFontRef (*CTFontCreateWithGraphicsFontPtr) (CGFontRef, CGFloat, const CGAffineTransform*, CTFontDescriptorRef) = NULL; +static CGPathRef (*CTFontCreatePathForGlyphPtr) (CTFontRef, CGGlyph, CGAffineTransform *) = NULL; + /* CGFontGetHMetrics isn't public, but the other functions are public/present in 10.5 */ typedef struct { int ascent; @@ -98,6 +106,10 @@ static ATSFontRef (*FMGetATSFontRefFromFontPtr) (FMFont iFont) = NULL; static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE; static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE; +/* Defined in 10.11 */ +#define CGGLYPH_MAX ((CGGlyph) 0xFFFE) /* kCGFontIndexMax */ +#define CGGLYPH_INVALID ((CGGlyph) 0xFFFF) /* kCGFontIndexInvalid */ + static void quartz_font_ensure_symbols(void) { @@ -125,6 +137,11 @@ quartz_font_ensure_symbols(void) CGFontGetUnitsPerEmPtr = dlsym(RTLD_DEFAULT, "CGFontGetUnitsPerEm"); CGFontGetGlyphAdvancesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphAdvances"); + CTFontCreateWithGraphicsFontPtr = dlsym(RTLD_DEFAULT, "CTFontCreateWithGraphicsFont"); + CTFontCreatePathForGlyphPtr = dlsym(RTLD_DEFAULT, "CTFontCreatePathForGlyph"); + if (!CTFontCreateWithGraphicsFontPtr || !CTFontCreatePathForGlyphPtr) + CGFontGetGlyphPathPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphPath"); + CGFontGetHMetricsPtr = dlsym(RTLD_DEFAULT, "CGFontGetHMetrics"); CGFontGetAscentPtr = dlsym(RTLD_DEFAULT, "CGFontGetAscent"); CGFontGetDescentPtr = dlsym(RTLD_DEFAULT, "CGFontGetDescent"); @@ -140,6 +157,7 @@ quartz_font_ensure_symbols(void) CGFontGetGlyphsForUnicharsPtr && CGFontGetUnitsPerEmPtr && CGFontGetGlyphAdvancesPtr && + ((CTFontCreateWithGraphicsFontPtr && CTFontCreatePathForGlyphPtr) || CGFontGetGlyphPathPtr) && (CGFontGetHMetricsPtr || (CGFontGetAscentPtr && CGFontGetDescentPtr && CGFontGetLeadingPtr))) _cairo_quartz_font_symbols_present = TRUE; @@ -178,7 +196,7 @@ _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, return _cairo_error (CAIRO_STATUS_NO_MEMORY); family = toy_face->family; - full_name = malloc (strlen (family) + 64); // give us a bit of room to tack on Bold, Oblique, etc. + full_name = _cairo_malloc (strlen (family) + 64); // give us a bit of room to tack on Bold, Oblique, etc. /* handle CSS-ish faces */ if (!strcmp(family, "serif") || !strcmp(family, "Times Roman")) family = "Times"; @@ -265,7 +283,7 @@ _cairo_quartz_font_face_scaled_font_create (void *abstract_face, if (!_cairo_quartz_font_symbols_present) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - font = malloc(sizeof(cairo_quartz_scaled_font_t)); + font = _cairo_malloc (sizeof(cairo_quartz_scaled_font_t)); if (font == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -357,7 +375,7 @@ cairo_quartz_font_face_create_for_cgfont (CGFontRef font) quartz_font_ensure_symbols(); - font_face = malloc (sizeof (cairo_quartz_font_face_t)); + font_face = _cairo_malloc (sizeof (cairo_quartz_font_face_t)); if (!font_face) { cairo_status_t ignore_status; ignore_status = _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -389,14 +407,10 @@ _cairo_quartz_scaled_font_fini(void *abstract_font) { } -#define INVALID_GLYPH 0x00 - static inline CGGlyph _cairo_quartz_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) { unsigned long index = _cairo_scaled_glyph_index (scaled_glyph); - if (index > 0xffff) - return INVALID_GLYPH; - return (CGGlyph) index; + return index <= CGGLYPH_MAX ? index : CGGLYPH_INVALID; } static cairo_int_status_t @@ -413,7 +427,7 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font, double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); double xmin, ymin, xmax, ymax; - if (glyph == INVALID_GLYPH) + if (unlikely (glyph == CGGLYPH_INVALID)) goto FAIL; if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) || @@ -545,10 +559,9 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font, CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); CGAffineTransform textMatrix; CGPathRef glyphPath; - CTFontRef ctFont; cairo_path_fixed_t *path; - if (glyph == INVALID_GLYPH) { + if (unlikely (glyph == CGGLYPH_INVALID)) { _cairo_scaled_glyph_set_path (scaled_glyph, &font->base, _cairo_path_fixed_create()); return CAIRO_STATUS_SUCCESS; } @@ -560,9 +573,14 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font, -font->base.scale.yy, 0, 0); - ctFont = CTFontCreateWithGraphicsFont (font_face->cgFont, 1.0, NULL, NULL); - glyphPath = CTFontCreatePathForGlyph (ctFont, glyph, &textMatrix); - CFRelease (ctFont); + if (CTFontCreateWithGraphicsFontPtr && CTFontCreatePathForGlyphPtr) { + CTFontRef ctFont = CTFontCreateWithGraphicsFontPtr (font_face->cgFont, 1.0, NULL, NULL); + glyphPath = CTFontCreatePathForGlyphPtr (ctFont, glyph, &textMatrix); + CFRelease (ctFont); + } else { + glyphPath = CGFontGetGlyphPathPtr (font_face->cgFont, &textMatrix, 0, glyph); + } + if (!glyphPath) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -609,7 +627,7 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font, * Maybe we should draw a better missing-glyph slug or something, * but this is ok for now. */ - if (glyph == INVALID_GLYPH) { + if (unlikely (glyph == CGGLYPH_INVALID)) { surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2); status = cairo_surface_status ((cairo_surface_t *) surface); if (status) @@ -748,12 +766,13 @@ _cairo_quartz_ucs4_to_index (void *abstract_font, { cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font; cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(font); - UniChar u = (UniChar) ucs4; - CGGlyph glyph; + CGGlyph glyph[2]; + UniChar utf16[2]; - CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, &u, &glyph, 1); + int len = _cairo_ucs4_to_utf16 (ucs4, utf16); + CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, utf16, glyph, len); - return glyph; + return glyph[0]; } static cairo_int_status_t diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-image-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-image-surface.c index 498a7b06436..84d56c9b471 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-image-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-image-surface.c @@ -332,7 +332,7 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface) if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24) return SURFACE_ERROR_INVALID_FORMAT; - qisurf = malloc(sizeof(cairo_quartz_image_surface_t)); + qisurf = _cairo_malloc (sizeof(cairo_quartz_image_surface_t)); if (qisurf == NULL) return SURFACE_ERROR_NO_MEMORY; @@ -361,7 +361,8 @@ cairo_quartz_image_surface_create (cairo_surface_t *surface) _cairo_surface_init (&qisurf->base, &cairo_quartz_image_surface_backend, NULL, /* device */ - _cairo_content_from_format (format)); + _cairo_content_from_format (format), + FALSE); /* is_vector */ qisurf->width = width; qisurf->height = height; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-image.h b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-image.h index dae234dacae..0dd5abb4fd2 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-image.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-image.h @@ -1,6 +1,6 @@ /* cairo - a vector graphics library with display and print output * - * Copyright © 2008 Mozilla Corporation + * Copyright © 2008 Mozilla Corporation * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-private.h index 3ef14c3ae60..42e1f9e9161 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-private.h @@ -44,12 +44,13 @@ #include "cairo-quartz.h" #include "cairo-surface-clipper-private.h" -#ifdef CGFLOAT_DEFINED -typedef CGFloat cairo_quartz_float_t; -#else -typedef float cairo_quartz_float_t; +#ifndef CGFLOAT_DEFINED +/* On 10.4, Quartz APIs used float instead of CGFloat */ +typedef float CGFloat; #endif +typedef CGFloat cairo_quartz_float_t; + typedef enum { DO_DIRECT, DO_SHADING, @@ -57,6 +58,9 @@ typedef enum { DO_TILED_IMAGE } cairo_quartz_action_t; +/* define CTFontRef for pre-10.5 SDKs */ +typedef const struct __CTFont *CTFontRef; + typedef struct cairo_quartz_surface { cairo_surface_t base; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-surface.c index 1116ff94c1e..65d03080a73 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-quartz-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-quartz-surface.c @@ -508,9 +508,13 @@ _cairo_cgcontext_set_cairo_operator (CGContextRef context, cairo_operator_t op) /* Quartz doesn't support SATURATE at all. COLOR_DODGE and * COLOR_BURN in Quartz follow the ISO32000 definition, but cairo - * uses the definition from the Adobe Supplement. + * uses the definition from the Adobe Supplement. Also fallback + * on SOFT_LIGHT and HSL_HUE, because their results are + * significantly different from those provided by pixman. */ if (op == CAIRO_OPERATOR_SATURATE || + op == CAIRO_OPERATOR_SOFT_LIGHT || + op == CAIRO_OPERATOR_HSL_HUE || op == CAIRO_OPERATOR_COLOR_DODGE || op == CAIRO_OPERATOR_COLOR_BURN) { @@ -605,14 +609,25 @@ _cairo_quartz_cairo_line_join_to_quartz (cairo_line_join_t cjoin) static inline CGInterpolationQuality _cairo_quartz_filter_to_quartz (cairo_filter_t filter) { + /* The CGInterpolationQuality enumeration values seem to have the + * following meaning: + * - kCGInterpolationNone: nearest neighbor + * - kCGInterpolationLow: bilinear + * - kCGInterpolationHigh: bicubic? Lanczos? + */ + switch (filter) { case CAIRO_FILTER_NEAREST: case CAIRO_FILTER_FAST: return kCGInterpolationNone; case CAIRO_FILTER_BEST: + return kCGInterpolationHigh; + case CAIRO_FILTER_GOOD: case CAIRO_FILTER_BILINEAR: + return kCGInterpolationLow; + case CAIRO_FILTER_GAUSSIAN: return kCGInterpolationDefault; @@ -811,7 +826,7 @@ _cairo_surface_to_cgimage (cairo_surface_t *source, } } - source_img = malloc (sizeof (quartz_source_image_t)); + source_img = _cairo_malloc (sizeof (quartz_source_image_t)); if (unlikely (source_img == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -969,7 +984,7 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t if (unlikely (status)) return status; - info = malloc (sizeof (SurfacePatternDrawInfo)); + info = _cairo_malloc (sizeof (SurfacePatternDrawInfo)); if (unlikely (!info)) return CAIRO_STATUS_NO_MEMORY; @@ -2238,7 +2253,7 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, quartz_ensure_symbols (); /* Init the base surface */ - surface = malloc (sizeof (cairo_quartz_surface_t)); + surface = _cairo_malloc (sizeof (cairo_quartz_surface_t)); if (unlikely (surface == NULL)) return (cairo_quartz_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -2247,7 +2262,8 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext, _cairo_surface_init (&surface->base, &cairo_quartz_surface_backend, NULL, /* device */ - content); + content, + FALSE); /* is_vector */ _cairo_surface_clipper_init (&surface->clipper, _cairo_quartz_surface_clipper_intersect_clip_path); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-quartz.h b/Build/source/libs/cairo/cairo-src/src/cairo-quartz.h index 9be5f9ae5cf..9e11e876fee 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-quartz.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-quartz.h @@ -1,6 +1,6 @@ /* cairo - a vector graphics library with display and print output * - * Copyright © 2006, 2007 Mozilla Corporation + * Copyright © 2006, 2007 Mozilla Corporation * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-recording-surface-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-recording-surface-private.h index 456c63389b7..c1827f5b3d6 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-recording-surface-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-recording-surface-private.h @@ -49,6 +49,9 @@ typedef enum { CAIRO_COMMAND_STROKE, CAIRO_COMMAND_FILL, CAIRO_COMMAND_SHOW_TEXT_GLYPHS, + + /* cairo_tag_begin()/cairo_tag_end() */ + CAIRO_COMMAND_TAG, } cairo_command_type_t; typedef enum { @@ -112,6 +115,17 @@ typedef struct _cairo_command_show_text_glyphs { cairo_scaled_font_t *scaled_font; } cairo_command_show_text_glyphs_t; +typedef struct _cairo_command_tag { + cairo_command_header_t header; + cairo_bool_t begin; + char *tag_name; + char *attributes; + cairo_pattern_union_t source; + cairo_stroke_style_t style; + cairo_matrix_t ctm; + cairo_matrix_t ctm_inverse; +} cairo_command_tag_t; + typedef union _cairo_command { cairo_command_header_t header; @@ -120,6 +134,7 @@ typedef union _cairo_command { cairo_command_stroke_t stroke; cairo_command_fill_t fill; cairo_command_show_text_glyphs_t show_text_glyphs; + cairo_command_tag_t tag; } cairo_command_t; typedef struct _cairo_recording_surface { @@ -169,7 +184,9 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, cairo_private cairo_status_t _cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface, - cairo_surface_t *target); + const cairo_matrix_t *surface_transform, + cairo_surface_t *target, + cairo_bool_t surface_is_unbounded); cairo_private cairo_status_t _cairo_recording_surface_replay_region (cairo_surface_t *surface, const cairo_rectangle_int_t *surface_extents, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-recording-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-recording-surface.c index 78e7cfa7efc..6df8b0821e0 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-recording-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-recording-surface.c @@ -158,7 +158,7 @@ static int bbtree_left_or_right (struct bbtree *bbt, static struct bbtree * bbtree_new (const cairo_box_t *box, cairo_command_header_t *chain) { - struct bbtree *bbt = malloc (sizeof (*bbt)); + struct bbtree *bbt = _cairo_malloc (sizeof (*bbt)); if (bbt == NULL) return NULL; bbt->extents = *box; @@ -386,14 +386,15 @@ cairo_recording_surface_create (cairo_content_t content, { cairo_recording_surface_t *surface; - surface = malloc (sizeof (cairo_recording_surface_t)); + surface = _cairo_malloc (sizeof (cairo_recording_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &cairo_recording_surface_backend, NULL, /* device */ - content); + content, + TRUE); /* is_vector */ surface->unbounded = TRUE; @@ -482,7 +483,16 @@ _cairo_recording_surface_finish (void *abstract_surface) cairo_scaled_font_destroy (command->show_text_glyphs.scaled_font); break; - default: + case CAIRO_COMMAND_TAG: + free (command->tag.tag_name); + if (command->tag.begin) { + free (command->tag.attributes); + _cairo_pattern_fini (&command->tag.source.base); + _cairo_stroke_style_fini (&command->tag.style); + } + break; + + default: ASSERT_NOT_REACHED; } @@ -552,11 +562,11 @@ attach_proxy (cairo_surface_t *source, { struct proxy *proxy; - proxy = malloc (sizeof (*proxy)); + proxy = _cairo_malloc (sizeof (*proxy)); if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content); + _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content, FALSE); proxy->image = image; _cairo_surface_attach_snapshot (source, &proxy->base, NULL); @@ -683,21 +693,6 @@ _cairo_recording_surface_reset (cairo_recording_surface_t *surface) _cairo_array_init (&surface->commands, sizeof (cairo_command_t *)); } -static cairo_bool_t -is_identity_recording_pattern (const cairo_pattern_t *pattern) -{ - cairo_surface_t *surface; - - if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE) - return FALSE; - - if (!_cairo_matrix_is_identity(&pattern->matrix)) - return FALSE; - - surface = ((cairo_surface_pattern_t *)pattern)->surface; - return surface->backend->type == CAIRO_SURFACE_TYPE_RECORDING; -} - static cairo_int_status_t _cairo_recording_surface_paint (void *abstract_surface, cairo_operator_t op, @@ -724,10 +719,6 @@ _cairo_recording_surface_paint (void *abstract_surface, (surface->base.is_clear || _cairo_pattern_is_opaque_solid (source))))) { _cairo_recording_surface_reset (surface); - if (is_identity_recording_pattern (source)) { - cairo_surface_t *src = ((cairo_surface_pattern_t *)source)->surface; - return _cairo_recording_surface_replay (src, &surface->base); - } } status = _cairo_composite_rectangles_init_for_paint (&composite, @@ -737,7 +728,7 @@ _cairo_recording_surface_paint (void *abstract_surface, if (unlikely (status)) return status; - command = malloc (sizeof (cairo_command_paint_t)); + command = _cairo_malloc (sizeof (cairo_command_paint_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -793,7 +784,7 @@ _cairo_recording_surface_mask (void *abstract_surface, if (unlikely (status)) return status; - command = malloc (sizeof (cairo_command_mask_t)); + command = _cairo_malloc (sizeof (cairo_command_mask_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -861,7 +852,7 @@ _cairo_recording_surface_stroke (void *abstract_surface, if (unlikely (status)) return status; - command = malloc (sizeof (cairo_command_stroke_t)); + command = _cairo_malloc (sizeof (cairo_command_stroke_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -937,7 +928,7 @@ _cairo_recording_surface_fill (void *abstract_surface, if (unlikely (status)) return status; - command = malloc (sizeof (cairo_command_fill_t)); + command = _cairo_malloc (sizeof (cairo_command_fill_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -1019,7 +1010,7 @@ _cairo_recording_surface_show_text_glyphs (void *abstract_surface, if (unlikely (status)) return status; - command = malloc (sizeof (cairo_command_show_text_glyphs_t)); + command = _cairo_malloc (sizeof (cairo_command_show_text_glyphs_t)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_COMPOSITE; @@ -1043,7 +1034,7 @@ _cairo_recording_surface_show_text_glyphs (void *abstract_surface, command->num_clusters = num_clusters; if (utf8_len) { - command->utf8 = malloc (utf8_len); + command->utf8 = _cairo_malloc (utf8_len); if (unlikely (command->utf8 == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_ARRAYS; @@ -1094,6 +1085,90 @@ CLEANUP_COMPOSITE: return status; } +static cairo_int_status_t +_cairo_recording_surface_tag (void *abstract_surface, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip) +{ + cairo_status_t status; + cairo_recording_surface_t *surface = abstract_surface; + cairo_command_tag_t *command; + cairo_composite_rectangles_t composite; + + TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id)); + + status = _cairo_composite_rectangles_init_for_paint (&composite, + &surface->base, + CAIRO_OPERATOR_SOURCE, + source ? source : &_cairo_pattern_black.base, + clip); + if (unlikely (status)) + return status; + + command = calloc (1, sizeof (cairo_command_tag_t)); + if (unlikely (command == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto CLEANUP_COMPOSITE; + } + + status = _command_init (surface, + &command->header, CAIRO_COMMAND_TAG, CAIRO_OPERATOR_SOURCE, + &composite); + if (unlikely (status)) + goto CLEANUP_COMMAND; + + command->begin = begin; + command->tag_name = strdup (tag_name); + if (begin) { + if (attributes) + command->attributes = strdup (attributes); + + status = _cairo_pattern_init_snapshot (&command->source.base, source); + if (unlikely (status)) + goto CLEANUP_STRINGS; + + status = _cairo_stroke_style_init_copy (&command->style, style); + if (unlikely (status)) + goto CLEANUP_SOURCE; + + command->ctm = *ctm; + command->ctm_inverse = *ctm_inverse; + } + + status = _cairo_recording_surface_commit (surface, &command->header); + if (unlikely (status)) { + if (begin) + goto CLEANUP_STRINGS; + else + goto CLEANUP_STYLE; + } + + _cairo_recording_surface_destroy_bbtree (surface); + + _cairo_composite_rectangles_fini (&composite); + return CAIRO_STATUS_SUCCESS; + + CLEANUP_STYLE: + _cairo_stroke_style_fini (&command->style); + CLEANUP_SOURCE: + _cairo_pattern_fini (&command->source.base); + CLEANUP_STRINGS: + free (command->tag_name); + free (command->attributes); + CLEANUP_COMMAND: + _cairo_clip_destroy (command->header.clip); + free (command); + CLEANUP_COMPOSITE: + _cairo_composite_rectangles_fini (&composite); + return status; +} + static void _command_init_copy (cairo_recording_surface_t *surface, cairo_command_header_t *dst, @@ -1117,7 +1192,7 @@ _cairo_recording_surface_copy__paint (cairo_recording_surface_t *surface, cairo_command_paint_t *command; cairo_status_t status; - command = malloc (sizeof (*command)); + command = _cairo_malloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1151,7 +1226,7 @@ _cairo_recording_surface_copy__mask (cairo_recording_surface_t *surface, cairo_command_mask_t *command; cairo_status_t status; - command = malloc (sizeof (*command)); + command = _cairo_malloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1192,7 +1267,7 @@ _cairo_recording_surface_copy__stroke (cairo_recording_surface_t *surface, cairo_command_stroke_t *command; cairo_status_t status; - command = malloc (sizeof (*command)); + command = _cairo_malloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1244,7 +1319,7 @@ _cairo_recording_surface_copy__fill (cairo_recording_surface_t *surface, cairo_command_fill_t *command; cairo_status_t status; - command = malloc (sizeof (*command)); + command = _cairo_malloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1288,7 +1363,7 @@ _cairo_recording_surface_copy__glyphs (cairo_recording_surface_t *surface, cairo_command_show_text_glyphs_t *command; cairo_status_t status; - command = malloc (sizeof (*command)); + command = _cairo_malloc (sizeof (*command)); if (unlikely (command == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err; @@ -1309,7 +1384,7 @@ _cairo_recording_surface_copy__glyphs (cairo_recording_surface_t *surface, command->num_clusters = src->show_text_glyphs.num_clusters; if (command->utf8_len) { - command->utf8 = malloc (command->utf8_len); + command->utf8 = _cairo_malloc (command->utf8_len); if (unlikely (command->utf8 == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto err_arrays; @@ -1359,6 +1434,63 @@ err: return status; } +static cairo_status_t +_cairo_recording_surface_copy__tag (cairo_recording_surface_t *surface, + const cairo_command_t *src) +{ + cairo_command_tag_t *command; + cairo_status_t status; + + command = calloc (1, sizeof (*command)); + if (unlikely (command == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto err; + } + + _command_init_copy (surface, &command->header, &src->header); + + command->begin = src->tag.begin; + command->tag_name = strdup (src->tag.tag_name); + if (src->tag.begin) { + if (src->tag.attributes) + command->attributes = strdup (src->tag.attributes); + + status = _cairo_pattern_init_copy (&command->source.base, + &src->stroke.source.base); + if (unlikely (status)) + goto err_command; + + status = _cairo_stroke_style_init_copy (&command->style, + &src->stroke.style); + if (unlikely (status)) + goto err_source; + + command->ctm = src->stroke.ctm; + command->ctm_inverse = src->stroke.ctm_inverse; + } + + status = _cairo_recording_surface_commit (surface, &command->header); + if (unlikely (status)) { + if (src->tag.begin) + goto err_command; + else + goto err_style; + } + + return CAIRO_STATUS_SUCCESS; + +err_style: + _cairo_stroke_style_fini (&command->style); +err_source: + _cairo_pattern_fini (&command->source.base); +err_command: + free(command->tag_name); + free(command->attributes); + free(command); +err: + return status; +} + static cairo_status_t _cairo_recording_surface_copy (cairo_recording_surface_t *dst, cairo_recording_surface_t *src) @@ -1393,6 +1525,10 @@ _cairo_recording_surface_copy (cairo_recording_surface_t *dst, status = _cairo_recording_surface_copy__glyphs (dst, command); break; + case CAIRO_COMMAND_TAG: + status = _cairo_recording_surface_copy__tag (dst, command); + break; + default: ASSERT_NOT_REACHED; } @@ -1424,14 +1560,15 @@ _cairo_recording_surface_snapshot (void *abstract_other) cairo_recording_surface_t *surface; cairo_status_t status; - surface = malloc (sizeof (cairo_recording_surface_t)); + surface = _cairo_malloc (sizeof (cairo_recording_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &cairo_recording_surface_backend, NULL, /* device */ - other->base.content); + other->base.content, + other->base.is_vector); surface->extents_pixels = other->extents_pixels; surface->extents = other->extents; @@ -1507,6 +1644,8 @@ static const cairo_surface_backend_t cairo_recording_surface_backend = { NULL, _cairo_recording_surface_has_show_text_glyphs, _cairo_recording_surface_show_text_glyphs, + NULL, /* get_supported_mime_types */ + _cairo_recording_surface_tag, }; cairo_int_status_t @@ -1571,6 +1710,9 @@ _cairo_recording_surface_get_path (cairo_surface_t *abstract_surface, break; } + case CAIRO_COMMAND_TAG: + break; + default: ASSERT_NOT_REACHED; } @@ -1674,14 +1816,14 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, const cairo_matrix_t *surface_transform, cairo_surface_t *target, const cairo_clip_t *target_clip, + cairo_bool_t surface_is_unbounded, cairo_recording_replay_type_t type, cairo_recording_region_type_t region) { cairo_surface_wrapper_t wrapper; cairo_command_t **elements; cairo_bool_t replay_all = - type == CAIRO_RECORDING_REPLAY && - region == CAIRO_RECORDING_REGION_ALL; + type == CAIRO_RECORDING_CREATE_REGIONS || region == CAIRO_RECORDING_REGION_ALL; cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_rectangle_int_t extents; cairo_bool_t use_indices = FALSE; @@ -1706,7 +1848,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, if (surface_extents) _cairo_surface_wrapper_intersect_extents (&wrapper, surface_extents); r = &_cairo_unbounded_rectangle; - if (! surface->unbounded) { + if (! surface->unbounded && !surface_is_unbounded) { _cairo_surface_wrapper_intersect_extents (&wrapper, &surface->extents); r = &surface->extents; } @@ -1714,7 +1856,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, _cairo_surface_wrapper_set_clip (&wrapper, target_clip); /* Compute the extents of the target clip in recorded device space */ - if (! _cairo_surface_wrapper_get_target_extents (&wrapper, &extents)) + if (! _cairo_surface_wrapper_get_target_extents (&wrapper, surface_is_unbounded, &extents)) goto done; surface->has_bilevel_alpha = TRUE; @@ -1868,11 +2010,23 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, } break; + case CAIRO_COMMAND_TAG: + status = _cairo_surface_wrapper_tag (&wrapper, + command->tag.begin, + command->tag.tag_name, + command->tag.attributes, + &command->tag.source.base, + &command->tag.style, + &command->tag.ctm, + &command->tag.ctm_inverse, + command->header.clip); + break; + default: ASSERT_NOT_REACHED; } - if (type == CAIRO_RECORDING_CREATE_REGIONS) { + if (type == CAIRO_RECORDING_CREATE_REGIONS && command->header.region != CAIRO_RECORDING_REGION_NATIVE) { if (status == CAIRO_INT_STATUS_SUCCESS) { command->header.region = CAIRO_RECORDING_REGION_NATIVE; } else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) { @@ -1975,6 +2129,18 @@ _cairo_recording_surface_replay_one (cairo_recording_surface_t *surface, command->header.clip); break; + case CAIRO_COMMAND_TAG: + status = _cairo_surface_wrapper_tag (&wrapper, + command->tag.begin, + command->tag.tag_name, + command->tag.attributes, + &command->tag.source.base, + &command->tag.style, + &command->tag.ctm, + &command->tag.ctm_inverse, + command->header.clip); + break; + default: ASSERT_NOT_REACHED; } @@ -1999,7 +2165,7 @@ _cairo_recording_surface_replay (cairo_surface_t *surface, cairo_surface_t *target) { return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, NULL, - target, NULL, + target, NULL, FALSE, CAIRO_RECORDING_REPLAY, CAIRO_RECORDING_REGION_ALL); } @@ -2011,7 +2177,7 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, const cairo_clip_t *target_clip) { return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform, - target, target_clip, + target, target_clip, FALSE, CAIRO_RECORDING_REPLAY, CAIRO_RECORDING_REGION_ALL); } @@ -2024,10 +2190,13 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface, */ cairo_status_t _cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface, - cairo_surface_t *target) + const cairo_matrix_t *surface_transform, + cairo_surface_t *target, + cairo_bool_t surface_is_unbounded) { - return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, NULL, + return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform, target, NULL, + surface_is_unbounded, CAIRO_RECORDING_CREATE_REGIONS, CAIRO_RECORDING_REGION_ALL); } @@ -2040,7 +2209,7 @@ _cairo_recording_surface_replay_region (cairo_surface_t *surface, { return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, surface_extents, NULL, - target, NULL, + target, NULL, FALSE, CAIRO_RECORDING_REPLAY, region); } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-region.c b/Build/source/libs/cairo/cairo-src/src/cairo-region.c index ccfb2200e14..c1d35e174ae 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-region.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-region.c @@ -107,6 +107,10 @@ _cairo_region_create_in_error (cairo_status_t status) case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: case CAIRO_STATUS_DEVICE_FINISHED: case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: + case CAIRO_STATUS_PNG_ERROR: + case CAIRO_STATUS_FREETYPE_ERROR: + case CAIRO_STATUS_WIN32_GDI_ERROR: + case CAIRO_STATUS_TAG_ERROR: default: _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_region_t *) &_cairo_region_nil; @@ -175,7 +179,7 @@ _cairo_region_fini (cairo_region_t *region) { assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count)); pixman_region32_fini (®ion->rgn); - VG (VALGRIND_MAKE_MEM_NOACCESS (region, sizeof (cairo_region_t))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t))); } /** diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font-private.h index da7b3469834..317d2119795 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font-private.h @@ -141,6 +141,7 @@ struct _cairo_scaled_glyph { cairo_image_surface_t *surface; /* device-space image */ cairo_path_fixed_t *path; /* device-space outline */ cairo_surface_t *recording_surface; /* device-space recording-surface */ + cairo_image_surface_t *color_surface; /* device-space color image */ const void *dev_private_key; void *dev_private; @@ -177,6 +178,8 @@ _cairo_scaled_glyph_attach_private (cairo_scaled_glyph_t *scaled_glyph, void (*destroy) (cairo_scaled_glyph_private_t *, cairo_scaled_glyph_t *, cairo_scaled_font_t *)); +cairo_private cairo_bool_t +_cairo_scaled_font_has_color_glyphs (cairo_scaled_font_t *scaled_font); CAIRO_END_DECLS diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font-subsets.c b/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font-subsets.c index a239ec9b33e..5c1afd2d03e 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font-subsets.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font-subsets.c @@ -167,7 +167,7 @@ _cairo_sub_font_glyph_create (unsigned long scaled_font_glyph_index, { cairo_sub_font_glyph_t *sub_font_glyph; - sub_font_glyph = malloc (sizeof (cairo_sub_font_glyph_t)); + sub_font_glyph = _cairo_malloc (sizeof (cairo_sub_font_glyph_t)); if (unlikely (sub_font_glyph == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; @@ -277,7 +277,7 @@ _cairo_sub_font_create (cairo_scaled_font_subsets_t *parent, cairo_sub_font_t *sub_font; int i; - sub_font = malloc (sizeof (cairo_sub_font_t)); + sub_font = _cairo_malloc (sizeof (cairo_sub_font_t)); if (unlikely (sub_font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -404,7 +404,7 @@ _cairo_sub_font_glyph_lookup_unicode (cairo_scaled_font_t *scaled_font, if (unicode != (uint32_t) -1) { len = _cairo_ucs4_to_utf8 (unicode, buf); if (len > 0) { - *utf8_out = malloc (len + 1); + *utf8_out = _cairo_malloc (len + 1); if (unlikely (*utf8_out == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -441,7 +441,7 @@ _cairo_sub_font_glyph_map_to_unicode (cairo_sub_font_glyph_t *sub_font_glyph, } } else { /* No existing mapping. Use the requested mapping */ - sub_font_glyph->utf8 = malloc (utf8_len + 1); + sub_font_glyph->utf8 = _cairo_malloc (utf8_len + 1); if (unlikely (sub_font_glyph->utf8 == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -611,7 +611,7 @@ _cairo_sub_font_map_glyph (cairo_sub_font_t *sub_font, if (ucs4_len == 1) { font_unicode = ucs4[0]; free (font_utf8); - font_utf8 = malloc (text_utf8_len + 1); + font_utf8 = _cairo_malloc (text_utf8_len + 1); if (font_utf8 == NULL) { free (ucs4); return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -762,7 +762,7 @@ _cairo_scaled_font_subsets_create_internal (cairo_subsets_type_t type) { cairo_scaled_font_subsets_t *subsets; - subsets = malloc (sizeof (cairo_scaled_font_subsets_t)); + subsets = _cairo_malloc (sizeof (cairo_scaled_font_subsets_t)); if (unlikely (subsets == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return NULL; @@ -1217,7 +1217,7 @@ _cairo_string_init_key (cairo_string_entry_t *key, char *s) static cairo_status_t create_string_entry (char *s, cairo_string_entry_t **entry) { - *entry = malloc (sizeof (cairo_string_entry_t)); + *entry = _cairo_malloc (sizeof (cairo_string_entry_t)); if (unlikely (*entry == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font.c b/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font.c index 53a370d3acc..8dff57d9533 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-scaled-font.c @@ -46,12 +46,6 @@ #include "cairo-scaled-font-private.h" #include "cairo-surface-backend-private.h" -#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) -#define ISFINITE(x) isfinite (x) -#else -#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */ -#endif - /** * SECTION:cairo-scaled-font * @Title: cairo_scaled_font_t @@ -85,7 +79,7 @@ static cairo_cache_t cairo_scaled_glyph_page_cache; #define CAIRO_SCALED_GLYPH_PAGE_SIZE 32 struct _cairo_scaled_glyph_page { cairo_cache_entry_t cache_entry; - + cairo_scaled_font_t *scaled_font; cairo_list_t link; unsigned int num_glyphs; @@ -224,6 +218,9 @@ _cairo_scaled_glyph_fini (cairo_scaled_font_t *scaled_font, cairo_surface_finish (scaled_glyph->recording_surface); cairo_surface_destroy (scaled_glyph->recording_surface); } + + if (scaled_glyph->color_surface != NULL) + cairo_surface_destroy (&scaled_glyph->color_surface->base); } #define ZOMBIE 0 @@ -371,7 +368,7 @@ _cairo_scaled_font_map_lock (void) CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex); if (cairo_scaled_font_map == NULL) { - cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t)); + cairo_scaled_font_map = _cairo_malloc (sizeof (cairo_scaled_font_map_t)); if (unlikely (cairo_scaled_font_map == NULL)) goto CLEANUP_MUTEX_LOCK; @@ -477,7 +474,7 @@ _cairo_scaled_glyph_page_pluck (void *closure) assert (! cairo_list_is_empty (&page->link)); - scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash; + scaled_font = page->scaled_font; CAIRO_MUTEX_LOCK (scaled_font->mutex); _cairo_scaled_glyph_page_destroy (scaled_font, page); @@ -512,7 +509,7 @@ _cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t if (unlikely (status)) return status; - placeholder_scaled_font = malloc (sizeof (cairo_scaled_font_t)); + placeholder_scaled_font = _cairo_malloc (sizeof (cairo_scaled_font_t)); if (unlikely (placeholder_scaled_font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1229,7 +1226,7 @@ _cairo_scaled_font_create_in_error (cairo_status_t status) CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex); scaled_font = _cairo_scaled_font_nil_objects[status]; if (unlikely (scaled_font == NULL)) { - scaled_font = malloc (sizeof (cairo_scaled_font_t)); + scaled_font = _cairo_malloc (sizeof (cairo_scaled_font_t)); if (unlikely (scaled_font == NULL)) { CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex); _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); @@ -1277,8 +1274,8 @@ _cairo_scaled_font_reset_static_data (void) * @scaled_font from being destroyed until a matching call to * cairo_scaled_font_destroy() is made. * - * The number of references to a #cairo_scaled_font_t can be get using - * cairo_scaled_font_get_reference_count(). + * Use cairo_scaled_font_get_reference_count() to get the number of + * references to a #cairo_scaled_font_t. * * Returns: the referenced #cairo_scaled_font_t * @@ -2055,7 +2052,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, status = _cairo_error (CAIRO_STATUS_NEGATIVE_COUNT); goto DONE; } - if (num_glyphs && *glyphs == NULL) { + if (*num_glyphs != 0 && *glyphs == NULL) { status = _cairo_error (CAIRO_STATUS_NULL_POINTER); goto DONE; } @@ -2065,7 +2062,7 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, status = _cairo_error (CAIRO_STATUS_NEGATIVE_COUNT); goto DONE; } - if (num_clusters && *clusters == NULL) { + if (*num_clusters != 0 && *clusters == NULL) { status = _cairo_error (CAIRO_STATUS_NULL_POINTER); goto DONE; } @@ -2830,13 +2827,31 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph, scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE; } +void +_cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font, + cairo_image_surface_t *surface) +{ + if (scaled_glyph->color_surface != NULL) + cairo_surface_destroy (&scaled_glyph->color_surface->base); + + /* sanity check the backend glyph contents */ + _cairo_debug_check_image_surface_is_defined (&surface->base); + scaled_glyph->color_surface = surface; + + if (surface != NULL) + scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE; + else + scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE; +} + static cairo_bool_t _cairo_scaled_glyph_page_can_remove (const void *closure) { const cairo_scaled_glyph_page_t *page = closure; const cairo_scaled_font_t *scaled_font; - scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash; + scaled_font = page->scaled_font; return scaled_font->cache_frozen == 0; } @@ -2860,11 +2875,12 @@ _cairo_scaled_font_allocate_glyph (cairo_scaled_font_t *scaled_font, } } - page = malloc (sizeof (cairo_scaled_glyph_page_t)); + page = _cairo_malloc (sizeof (cairo_scaled_glyph_page_t)); if (unlikely (page == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); page->cache_entry.hash = (unsigned long) scaled_font; + page->scaled_font = scaled_font; page->cache_entry.size = 1; /* XXX occupancy weighting? */ page->num_glyphs = 0; @@ -3175,3 +3191,12 @@ cairo_scaled_font_get_font_options (cairo_scaled_font_t *scaled_font, _cairo_font_options_init_copy (options, &scaled_font->options); } slim_hidden_def (cairo_scaled_font_get_font_options); + +cairo_bool_t +_cairo_scaled_font_has_color_glyphs (cairo_scaled_font_t *scaled_font) +{ + if (scaled_font->backend != NULL && scaled_font->backend->has_color_glyphs != NULL) + return scaled_font->backend->has_color_glyphs (scaled_font); + else + return FALSE; +} diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-script-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-script-surface.c index a4cefdebb4b..7db7dc5b0df 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-script-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-script-surface.c @@ -262,8 +262,9 @@ _bitmap_next_id (struct _bitmap *b, prev = &b->next; b = b->next; } while (b != NULL); + assert (prev != NULL); - bb = malloc (sizeof (struct _bitmap)); + bb = _cairo_malloc (sizeof (struct _bitmap)); if (unlikely (bb == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1104,14 +1105,15 @@ attach_snapshot (cairo_script_context_t *ctx, if (! ctx->attach_snapshots) return; - surface = malloc (sizeof (*surface)); + surface = _cairo_malloc (sizeof (*surface)); if (unlikely (surface == NULL)) return; _cairo_surface_init (&surface->base, &script_snapshot_backend, &ctx->base, - source->content); + source->content, + source->is_vector); _cairo_output_stream_printf (ctx->stream, "dup /s%d exch def ", @@ -1201,7 +1203,8 @@ static cairo_status_t _write_image_surface (cairo_output_stream_t *output, const cairo_image_surface_t *image) { - int stride, row, width; + int row, width; + ptrdiff_t stride; uint8_t row_stack[CAIRO_STACK_BUFFER_SIZE]; uint8_t *rowdata; uint8_t *data; @@ -1253,7 +1256,7 @@ _write_image_surface (cairo_output_stream_t *output, } #else if (stride > ARRAY_LENGTH (row_stack)) { - rowdata = malloc (stride); + rowdata = _cairo_malloc (stride); if (unlikely (rowdata == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } else @@ -2176,7 +2179,7 @@ _cairo_script_surface_finish (void *abstract_surface) } cairo_list_del (&surface->operand.link); } else { - struct deferred_finish *link = malloc (sizeof (*link)); + struct deferred_finish *link = _cairo_malloc (sizeof (*link)); if (link == NULL) { status2 = _cairo_error (CAIRO_STATUS_NO_MEMORY); if (status == CAIRO_STATUS_SUCCESS) @@ -2855,7 +2858,7 @@ _emit_type42_font (cairo_script_surface_t *surface, if (unlikely (status)) return status; - buf = malloc (size); + buf = _cairo_malloc (size); if (unlikely (buf == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2911,7 +2914,7 @@ _emit_scaled_font_init (cairo_script_surface_t *surface, cairo_script_font_t *font_private; cairo_int_status_t status; - font_private = malloc (sizeof (cairo_script_font_t)); + font_private = _cairo_malloc (sizeof (cairo_script_font_t)); if (unlikely (font_private == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -3641,14 +3644,15 @@ _cairo_script_surface_create_internal (cairo_script_context_t *ctx, if (unlikely (ctx == NULL)) return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); - surface = malloc (sizeof (cairo_script_surface_t)); + surface = _cairo_malloc (sizeof (cairo_script_surface_t)); if (unlikely (surface == NULL)) return (cairo_script_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &_cairo_script_surface_backend, &ctx->base, - content); + content, + TRUE); /* is_vector */ _cairo_surface_wrapper_init (&surface->wrapper, passthrough); @@ -3689,7 +3693,7 @@ _cairo_script_context_create_internal (cairo_output_stream_t *stream) { cairo_script_context_t *ctx; - ctx = malloc (sizeof (cairo_script_context_t)); + ctx = _cairo_malloc (sizeof (cairo_script_context_t)); if (unlikely (ctx == NULL)) return _cairo_device_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-skia.h b/Build/source/libs/cairo/cairo-src/src/cairo-skia.h deleted file mode 100644 index 99b92865699..00000000000 --- a/Build/source/libs/cairo/cairo-src/src/cairo-skia.h +++ /dev/null @@ -1,66 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * - * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - */ - -#ifndef CAIRO_SKIA_H -#define CAIRO_SKIA_H - -#include "cairo.h" - -#if CAIRO_HAS_SKIA_SURFACE - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_skia_surface_create (cairo_format_t format, - int width, - int height); - -cairo_public cairo_surface_t * -cairo_skia_surface_create_for_data (unsigned char *data, - cairo_format_t format, - int width, - int height, - int stride); - -CAIRO_END_DECLS - -#else - -# error Cairo was not compiled with support for the Skia backend - -#endif - -#endif diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-spans-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-spans-private.h index b158f4d360a..653183fb1c8 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-spans-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-spans-private.h @@ -168,6 +168,10 @@ _cairo_botor_scan_converter_init (cairo_botor_scan_converter_t *self, const cairo_box_t *extents, cairo_fill_rule_t fill_rule); +cairo_private cairo_status_t +_cairo_botor_scan_converter_add_polygon (cairo_botor_scan_converter_t *converter, + const cairo_polygon_t *polygon); + /* cairo-spans.c: */ cairo_private cairo_scan_converter_t * diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-spans.c b/Build/source/libs/cairo/cairo-src/src/cairo-spans.c index 182390c205a..59452c0ba69 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-spans.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-spans.c @@ -128,6 +128,10 @@ _cairo_scan_converter_create_in_error (cairo_status_t status) case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: RETURN_NIL; case CAIRO_STATUS_DEVICE_FINISHED: RETURN_NIL; case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: + case CAIRO_STATUS_PNG_ERROR: + case CAIRO_STATUS_FREETYPE_ERROR: + case CAIRO_STATUS_WIN32_GDI_ERROR: + case CAIRO_STATUS_TAG_ERROR: default: break; } @@ -241,6 +245,10 @@ _cairo_span_renderer_create_in_error (cairo_status_t status) case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: RETURN_NIL; case CAIRO_STATUS_DEVICE_FINISHED: RETURN_NIL; case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: RETURN_NIL; + case CAIRO_STATUS_PNG_ERROR: RETURN_NIL; + case CAIRO_STATUS_FREETYPE_ERROR: RETURN_NIL; + case CAIRO_STATUS_WIN32_GDI_ERROR: RETURN_NIL; + case CAIRO_STATUS_TAG_ERROR: RETURN_NIL; default: break; } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-stroke-style.c b/Build/source/libs/cairo/cairo-src/src/cairo-stroke-style.c index 51c9414c042..9c373c33327 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-stroke-style.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-stroke-style.c @@ -91,7 +91,7 @@ _cairo_stroke_style_fini (cairo_stroke_style_t *style) style->num_dashes = 0; - VG (VALGRIND_MAKE_MEM_NOACCESS (style, sizeof (cairo_stroke_style_t))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (style, sizeof (cairo_stroke_style_t))); } /* diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-surface-backend-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-surface-backend-private.h index 955a79ff5c3..bcda9aed155 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-surface-backend-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-surface-backend-private.h @@ -200,6 +200,18 @@ struct _cairo_surface_backend { const char ** (*get_supported_mime_types) (void *surface); + + cairo_warn cairo_int_status_t + (*tag) (void *surface, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip); + }; cairo_private cairo_status_t diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-surface-observer.c b/Build/source/libs/cairo/cairo-src/src/cairo-surface-observer.c index e6f78e6da6f..9c4432e246f 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-surface-observer.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-surface-observer.c @@ -348,7 +348,7 @@ _cairo_device_create_observer_internal (cairo_device_t *target, cairo_device_observer_t *device; cairo_status_t status; - device = malloc (sizeof (cairo_device_observer_t)); + device = _cairo_malloc (sizeof (cairo_device_observer_t)); if (unlikely (device == NULL)) return _cairo_device_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -379,13 +379,14 @@ _cairo_surface_create_observer_internal (cairo_device_t *device, cairo_surface_observer_t *surface; cairo_status_t status; - surface = malloc (sizeof (cairo_surface_observer_t)); + surface = _cairo_malloc (sizeof (cairo_surface_observer_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &_cairo_surface_observer_backend, device, - target->content); + target->content, + target->is_vector); status = log_init (&surface->log, ((cairo_device_observer_t *)device)->log.record != NULL); @@ -1417,7 +1418,7 @@ _cairo_surface_observer_add_callback (cairo_list_t *head, { struct callback_list *cb; - cb = malloc (sizeof (*cb)); + cb = _cairo_malloc (sizeof (*cb)); if (unlikely (cb == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-surface-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-surface-private.h index f20ab073932..e4ad5f3b18d 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-surface-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-surface-private.h @@ -70,6 +70,7 @@ struct _cairo_surface { unsigned is_clear : 1; unsigned has_font_options : 1; unsigned owns_device : 1; + unsigned is_vector : 1; cairo_user_data_array_t user_data; cairo_user_data_array_t mime_data; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-surface-snapshot.c b/Build/source/libs/cairo/cairo-src/src/cairo-surface-snapshot.c index 68bf9054ecd..a8b8c0e45d8 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-surface-snapshot.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-surface-snapshot.c @@ -99,15 +99,18 @@ _cairo_surface_snapshot_acquire_source_image (void *abstract_ struct snapshot_extra *extra; cairo_status_t status; - extra = malloc (sizeof (*extra)); - if (unlikely (extra == NULL)) + extra = _cairo_malloc (sizeof (*extra)); + if (unlikely (extra == NULL)) { + *extra_out = NULL; return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } extra->target = _cairo_surface_snapshot_get_target (&surface->base); status = _cairo_surface_acquire_source_image (extra->target, image_out, &extra->extra); if (unlikely (status)) { cairo_surface_destroy (extra->target); free (extra); + extra = NULL; } *extra_out = extra; @@ -258,14 +261,15 @@ _cairo_surface_snapshot (cairo_surface_t *surface) if (snapshot != NULL) return cairo_surface_reference (&snapshot->base); - snapshot = malloc (sizeof (cairo_surface_snapshot_t)); + snapshot = _cairo_malloc (sizeof (cairo_surface_snapshot_t)); if (unlikely (snapshot == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); _cairo_surface_init (&snapshot->base, &_cairo_surface_snapshot_backend, NULL, /* device */ - surface->content); + surface->content, + surface->is_vector); snapshot->base.type = surface->type; CAIRO_MUTEX_INIT (snapshot->mutex); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-surface-subsurface.c b/Build/source/libs/cairo/cairo-src/src/cairo-surface-subsurface.c index b7dfd9d9e0c..b2a10e9bce3 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-surface-subsurface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-surface-subsurface.c @@ -462,7 +462,7 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target, if (unlikely (target->finished)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - surface = malloc (sizeof (cairo_surface_subsurface_t)); + surface = _cairo_malloc (sizeof (cairo_surface_subsurface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -478,7 +478,8 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target, _cairo_surface_init (&surface->base, &_cairo_surface_subsurface_backend, NULL, /* device */ - target->content); + target->content, + target->is_vector); /* XXX forced integer alignment */ surface->extents.x = ceil (x); @@ -521,14 +522,15 @@ _cairo_surface_create_for_rectangle_int (cairo_surface_t *target, assert (target->backend->type != CAIRO_SURFACE_TYPE_SUBSURFACE); - surface = malloc (sizeof (cairo_surface_subsurface_t)); + surface = _cairo_malloc (sizeof (cairo_surface_subsurface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &_cairo_surface_subsurface_backend, NULL, /* device */ - target->content); + target->content, + target->is_vector); surface->extents = *extents; surface->extents.x *= target->device_transform.xx; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-surface-wrapper-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-surface-wrapper-private.h index 6529ebc1115..fd22bd7e6c2 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-surface-wrapper-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-surface-wrapper-private.h @@ -159,6 +159,17 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip); +cairo_private cairo_status_t +_cairo_surface_wrapper_tag (cairo_surface_wrapper_t *wrapper, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip); + cairo_private cairo_surface_t * _cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper, cairo_content_t content, @@ -186,6 +197,7 @@ _cairo_surface_wrapper_is_active (cairo_surface_wrapper_t *wrapper) cairo_private cairo_bool_t _cairo_surface_wrapper_get_target_extents (cairo_surface_wrapper_t *wrapper, + cairo_bool_t surface_is_unbounded, cairo_rectangle_int_t *extents); CAIRO_END_DECLS diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-surface-wrapper.c b/Build/source/libs/cairo/cairo-src/src/cairo-surface-wrapper.c index 9236c8bf42e..47155c3f799 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-surface-wrapper.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-surface-wrapper.c @@ -81,9 +81,6 @@ _cairo_surface_wrapper_get_transform (cairo_surface_wrapper_t *wrapper, { cairo_matrix_init_identity (m); - if (wrapper->has_extents && (wrapper->extents.x || wrapper->extents.y)) - cairo_matrix_translate (m, -wrapper->extents.x, -wrapper->extents.y); - if (! _cairo_matrix_is_identity (&wrapper->transform)) cairo_matrix_multiply (m, &wrapper->transform, m); @@ -109,9 +106,6 @@ _cairo_surface_wrapper_get_inverse_transform (cairo_surface_wrapper_t *wrapper, assert (status == CAIRO_STATUS_SUCCESS); cairo_matrix_multiply (m, &inv, m); } - - if (wrapper->has_extents && (wrapper->extents.x || wrapper->extents.y)) - cairo_matrix_translate (m, wrapper->extents.x, wrapper->extents.y); } static cairo_clip_t * @@ -119,14 +113,14 @@ _cairo_surface_wrapper_get_clip (cairo_surface_wrapper_t *wrapper, const cairo_clip_t *clip) { cairo_clip_t *copy; + cairo_matrix_t m; copy = _cairo_clip_copy (clip); if (wrapper->has_extents) { copy = _cairo_clip_intersect_rectangle (copy, &wrapper->extents); } - copy = _cairo_clip_transform (copy, &wrapper->transform); - if (! _cairo_matrix_is_identity (&wrapper->target->device_transform)) - copy = _cairo_clip_transform (copy, &wrapper->target->device_transform); + _cairo_surface_wrapper_get_transform (wrapper, &m); + copy = _cairo_clip_transform (copy, &m); if (wrapper->clip) copy = _cairo_clip_intersect_clip (copy, wrapper->clip); @@ -507,6 +501,53 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, return status; } +cairo_status_t +_cairo_surface_wrapper_tag (cairo_surface_wrapper_t *wrapper, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip) +{ + cairo_status_t status; + cairo_clip_t *dev_clip; + cairo_matrix_t dev_ctm = *ctm; + cairo_matrix_t dev_ctm_inverse = *ctm_inverse; + cairo_pattern_union_t source_copy; + + if (unlikely (wrapper->target->status)) + return wrapper->target->status; + + dev_clip = _cairo_surface_wrapper_get_clip (wrapper, clip); + if (wrapper->needs_transform) { + cairo_matrix_t m; + + _cairo_surface_wrapper_get_transform (wrapper, &m); + + cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m); + + status = cairo_matrix_invert (&m); + assert (status == CAIRO_STATUS_SUCCESS); + + cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse); + + _copy_transformed_pattern (&source_copy.base, source, &m); + source = &source_copy.base; + } + + status = _cairo_surface_tag (wrapper->target, + begin, tag_name, attributes, + source, stroke_style, + &dev_ctm, &dev_ctm_inverse, + dev_clip); + + _cairo_clip_destroy (dev_clip); + return status; +} + cairo_surface_t * _cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper, cairo_content_t content, @@ -631,12 +672,15 @@ _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper) cairo_bool_t _cairo_surface_wrapper_get_target_extents (cairo_surface_wrapper_t *wrapper, + cairo_bool_t surface_is_unbounded, cairo_rectangle_int_t *extents) { cairo_rectangle_int_t clip; - cairo_bool_t has_clip; + cairo_bool_t has_clip = FALSE; + + if (!surface_is_unbounded) + has_clip = _cairo_surface_get_extents (wrapper->target, &clip); - has_clip = _cairo_surface_get_extents (wrapper->target, &clip); if (wrapper->clip) { if (has_clip) { if (! _cairo_rectangle_intersect (&clip, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-surface.c index fa0ca37db9c..596ca250d4e 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-surface.c @@ -113,7 +113,8 @@ const cairo_surface_t name = { \ FALSE, /* finished */ \ TRUE, /* is_clear */ \ FALSE, /* has_font_options */ \ - FALSE, /* owns_device */ \ + FALSE, /* owns_device */ \ + FALSE, /* is_vector */ \ { 0, 0, 0, NULL, }, /* user_data */ \ { 0, 0, 0, NULL, }, /* mime_data */ \ { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform */ \ @@ -400,7 +401,8 @@ void _cairo_surface_init (cairo_surface_t *surface, const cairo_surface_backend_t *backend, cairo_device_t *device, - cairo_content_t content) + cairo_content_t content, + cairo_bool_t is_vector) { CAIRO_MUTEX_INITIALIZE (); @@ -408,6 +410,7 @@ _cairo_surface_init (cairo_surface_t *surface, surface->device = cairo_device_reference (device); surface->content = content; surface->type = backend->type; + surface->is_vector = is_vector; CAIRO_REFERENCE_COUNT_INIT (&surface->ref_count, 1); surface->status = CAIRO_STATUS_SUCCESS; @@ -501,13 +504,9 @@ cairo_surface_create_similar (cairo_surface_t *other, return _cairo_surface_create_in_error (CAIRO_STATUS_SURFACE_FINISHED); if (unlikely (width < 0 || height < 0)) return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_SIZE); - if (unlikely (! CAIRO_CONTENT_VALID (content))) return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_CONTENT); - if (unlikely (other->status)) - return _cairo_surface_create_in_error (other->status); - /* We inherit the device scale, so create a larger surface */ width = width * other->device_transform.xx; height = height * other->device_transform.yy; @@ -914,8 +913,8 @@ _cairo_surface_create_scratch (cairo_surface_t *other, * @surface from being destroyed until a matching call to * cairo_surface_destroy() is made. * - * The number of references to a #cairo_surface_t can be get using - * cairo_surface_get_reference_count(). + * Use cairo_surface_get_reference_count() to get the number of + * references to a #cairo_surface_t. * * Return value: the referenced #cairo_surface_t. * @@ -1026,8 +1025,6 @@ _cairo_surface_finish (cairo_surface_t *surface) { cairo_status_t status; - surface->finished = TRUE; - /* call finish even if in error mode */ if (surface->backend->finish) { status = surface->backend->finish (surface); @@ -1035,6 +1032,8 @@ _cairo_surface_finish (cairo_surface_t *surface) _cairo_surface_set_error (surface, status); } + surface->finished = TRUE; + assert (surface->snapshot_of == NULL); assert (!_cairo_surface_has_snapshots (surface)); } @@ -1225,6 +1224,80 @@ _cairo_mime_data_destroy (void *ptr) free (mime_data); } + +static const char *_cairo_surface_image_mime_types[] = { + CAIRO_MIME_TYPE_JPEG, + CAIRO_MIME_TYPE_PNG, + CAIRO_MIME_TYPE_JP2, + CAIRO_MIME_TYPE_JBIG2, + CAIRO_MIME_TYPE_CCITT_FAX, +}; + +cairo_bool_t +_cairo_surface_has_mime_image (cairo_surface_t *surface) +{ + cairo_user_data_slot_t *slots; + int i, j, num_slots; + + /* Prevent reads of the array during teardown */ + if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count)) + return FALSE; + + /* The number of mime-types attached to a surface is usually small, + * typically zero. Therefore it is quicker to do a strcmp() against + * each key than it is to intern the string (i.e. compute a hash, + * search the hash table, and do a final strcmp). + */ + num_slots = surface->mime_data.num_elements; + slots = _cairo_array_index (&surface->mime_data, 0); + for (i = 0; i < num_slots; i++) { + if (slots[i].key != NULL) { + for (j = 0; j < ARRAY_LENGTH (_cairo_surface_image_mime_types); j++) { + if (strcmp ((char *) slots[i].key, _cairo_surface_image_mime_types[j]) == 0) + return TRUE; + } + } + } + + return FALSE; +} + +/** + * CAIRO_MIME_TYPE_CCITT_FAX: + * + * Group 3 or Group 4 CCITT facsimile encoding (International + * Telecommunication Union, Recommendations T.4 and T.6.) + * + * Since: 1.16 + **/ + +/** + * CAIRO_MIME_TYPE_CCITT_FAX_PARAMS: + * + * Decode parameters for Group 3 or Group 4 CCITT facsimile encoding. + * See [CCITT Fax Images][ccitt]. + * + * Since: 1.16 + **/ + +/** + * CAIRO_MIME_TYPE_EPS: + * + * Encapsulated PostScript file. + * [Encapsulated PostScript File Format Specification](http://wwwimages.adobe.com/content/dam/Adobe/endevnet/postscript/pdfs/5002.EPSF_Spec.pdf) + * + * Since: 1.16 + **/ + +/** + * CAIRO_MIME_TYPE_EPS_PARAMS: + * + * Embedding parameters Encapsulated PostScript data. + * See [Embedding EPS files][eps]. + * + * Since: 1.16 + **/ + /** * CAIRO_MIME_TYPE_JBIG2: * @@ -1315,7 +1388,8 @@ _cairo_mime_data_destroy (void *ptr) * The recognized MIME types are the following: %CAIRO_MIME_TYPE_JPEG, * %CAIRO_MIME_TYPE_PNG, %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_URI, * %CAIRO_MIME_TYPE_UNIQUE_ID, %CAIRO_MIME_TYPE_JBIG2, - * %CAIRO_MIME_TYPE_JBIG2_GLOBAL, %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID. + * %CAIRO_MIME_TYPE_JBIG2_GLOBAL, %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID, + * %CAIRO_MIME_TYPE_CCITT_FAX, %CAIRO_MIME_TYPE_CCITT_FAX_PARAMS. * * See corresponding backend surface docs for details about which MIME * types it can handle. Caution: the associated MIME data will be @@ -1364,7 +1438,7 @@ cairo_surface_set_mime_data (cairo_surface_t *surface, return _cairo_surface_set_error (surface, status); if (data != NULL) { - mime_data = malloc (sizeof (cairo_mime_data_t)); + mime_data = _cairo_malloc (sizeof (cairo_mime_data_t)); if (unlikely (mime_data == NULL)) return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1387,6 +1461,8 @@ cairo_surface_set_mime_data (cairo_surface_t *surface, return _cairo_surface_set_error (surface, status); } + surface->is_clear = FALSE; + return CAIRO_STATUS_SUCCESS; } slim_hidden_def (cairo_surface_set_mime_data); @@ -1461,6 +1537,8 @@ _cairo_surface_copy_mime_data (cairo_surface_t *dst, _cairo_mime_data_reference, NULL); + dst->is_clear = FALSE; + return CAIRO_STATUS_SUCCESS; } @@ -2518,6 +2596,200 @@ cairo_surface_has_show_text_glyphs (cairo_surface_t *surface) } slim_hidden_def (cairo_surface_has_show_text_glyphs); +#define GLYPH_CACHE_SIZE 64 + +static inline cairo_int_status_t +ensure_scaled_glyph (cairo_scaled_font_t *scaled_font, + cairo_scaled_glyph_t **glyph_cache, + cairo_glyph_t *glyph, + cairo_scaled_glyph_t **scaled_glyph) +{ + int cache_index; + cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; + + cache_index = glyph->index % GLYPH_CACHE_SIZE; + *scaled_glyph = glyph_cache[cache_index]; + if (*scaled_glyph == NULL || _cairo_scaled_glyph_index (*scaled_glyph) != glyph->index) { + status = _cairo_scaled_glyph_lookup (scaled_font, + glyph->index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + scaled_glyph); + if (unlikely (status)) + status = _cairo_scaled_font_set_error (scaled_font, status); + + glyph_cache[cache_index] = *scaled_glyph; + } + + return status; +} + +static inline cairo_int_status_t +composite_one_color_glyph (cairo_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_clip_t *clip, + cairo_glyph_t *glyph, + cairo_scaled_glyph_t *scaled_glyph) +{ + cairo_int_status_t status; + cairo_image_surface_t *glyph_surface; + cairo_pattern_t *pattern; + cairo_matrix_t matrix; + + status = CAIRO_INT_STATUS_SUCCESS; + + glyph_surface = scaled_glyph->color_surface; + + if (glyph_surface->width && glyph_surface->height) { + int x, y; + /* round glyph locations to the nearest pixels */ + /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */ + x = _cairo_lround (glyph->x - glyph_surface->base.device_transform.x0); + y = _cairo_lround (glyph->y - glyph_surface->base.device_transform.y0); + + pattern = cairo_pattern_create_for_surface ((cairo_surface_t *)glyph_surface); + cairo_matrix_init_translate (&matrix, - x, - y); + cairo_pattern_set_matrix (pattern, &matrix); + if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR) + status = surface->backend->mask (surface, op, pattern, pattern, clip); + else + status = surface->backend->paint (surface, op, pattern, clip); + cairo_pattern_destroy (pattern); + } + + return status; +} + +static cairo_int_status_t +composite_color_glyphs (cairo_surface_t *surface, + cairo_operator_t op, + const cairo_pattern_t *source, + char *utf8, + int *utf8_len, + cairo_glyph_t *glyphs, + int *num_glyphs, + cairo_text_cluster_t *clusters, + int *num_clusters, + cairo_text_cluster_flags_t cluster_flags, + cairo_scaled_font_t *scaled_font, + const cairo_clip_t *clip) +{ + cairo_int_status_t status; + int i, j; + cairo_scaled_glyph_t *scaled_glyph; + int remaining_clusters = 0; + int remaining_glyphs = 0; + int remaining_bytes = 0; + int glyph_pos = 0; + int byte_pos = 0; + int gp; + cairo_scaled_glyph_t *glyph_cache[GLYPH_CACHE_SIZE]; + + memset (glyph_cache, 0, sizeof (glyph_cache)); + + status = CAIRO_INT_STATUS_SUCCESS; + + _cairo_scaled_font_freeze_cache (scaled_font); + + if (clusters) { + + if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) + glyph_pos = *num_glyphs - 1; + + for (i = 0; i < *num_clusters; i++) { + cairo_bool_t skip_cluster = FALSE; + + for (j = 0; j < clusters[i].num_glyphs; j++) { + if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) + gp = glyph_pos - j; + else + gp = glyph_pos + j; + + status = ensure_scaled_glyph (scaled_font, glyph_cache, + &glyphs[gp], &scaled_glyph); + if (unlikely (status)) + goto UNLOCK; + + if ((scaled_glyph->has_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) == 0) { + skip_cluster = TRUE; + break; + } + } + + if (skip_cluster) { + memmove (utf8 + remaining_bytes, utf8 + byte_pos, clusters[i].num_bytes); + remaining_bytes += clusters[i].num_bytes; + byte_pos += clusters[i].num_bytes; + for (j = 0; j < clusters[i].num_glyphs; j++, remaining_glyphs++) { + if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) + glyphs[*num_glyphs - 1 - remaining_glyphs] = glyphs[glyph_pos--]; + else + glyphs[remaining_glyphs] = glyphs[glyph_pos++]; + } + clusters[remaining_clusters++] = clusters[i]; + continue; + } + + for (j = 0; j < clusters[i].num_glyphs; j++) { + if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) + gp = glyph_pos - j; + else + gp = glyph_pos + j; + + status = ensure_scaled_glyph (scaled_font, glyph_cache, + &glyphs[gp], &scaled_glyph); + if (unlikely (status)) + goto UNLOCK; + + status = composite_one_color_glyph (surface, op, source, clip, + &glyphs[gp], scaled_glyph); + if (unlikely (status && status != CAIRO_INT_STATUS_NOTHING_TO_DO)) + goto UNLOCK; + } + + if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) + glyph_pos -= clusters[i].num_glyphs; + else + glyph_pos += clusters[i].num_glyphs; + + byte_pos += clusters[i].num_bytes; + } + + if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) + memmove (utf8, utf8 + *utf8_len - remaining_bytes, remaining_bytes); + + *utf8_len = remaining_bytes; + *num_glyphs = remaining_glyphs; + *num_clusters = remaining_clusters; + + } else { + + for (glyph_pos = 0; glyph_pos < *num_glyphs; glyph_pos++) { + status = ensure_scaled_glyph (scaled_font, glyph_cache, + &glyphs[glyph_pos], &scaled_glyph); + if (unlikely (status)) + goto UNLOCK; + + if ((scaled_glyph->has_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) == 0) { + glyphs[remaining_glyphs++] = glyphs[glyph_pos]; + continue; + } + + status = composite_one_color_glyph (surface, op, source, clip, + &glyphs[glyph_pos], scaled_glyph); + if (unlikely (status && status != CAIRO_INT_STATUS_NOTHING_TO_DO)) + goto UNLOCK; + } + + *num_glyphs = remaining_glyphs; + } + +UNLOCK: + _cairo_scaled_font_thaw_cache (scaled_font); + + return status; +} + /* Note: the backends may modify the contents of the glyph array as long as * they do not return %CAIRO_INT_STATUS_UNSUPPORTED. This makes it possible to * avoid copying the array again and again, and edit it in-place. @@ -2574,6 +2846,22 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, status = CAIRO_INT_STATUS_UNSUPPORTED; + if (_cairo_scaled_font_has_color_glyphs (scaled_font)) { + status = composite_color_glyphs (surface, op, + source, + (char *)utf8, &utf8_len, + glyphs, &num_glyphs, + (cairo_text_cluster_t *)clusters, &num_clusters, cluster_flags, + scaled_font, + clip); + + if (unlikely (status && status != CAIRO_INT_STATUS_NOTHING_TO_DO)) + goto DONE; + + if (num_glyphs == 0) + goto DONE; + } + /* The logic here is duplicated in _cairo_analysis_surface show_glyphs and * show_text_glyphs. Keep in synch. */ if (clusters) { @@ -2624,6 +2912,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, } } +DONE: if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) { surface->is_clear = FALSE; surface->serial++; @@ -2632,6 +2921,42 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, return _cairo_surface_set_error (surface, status); } +cairo_status_t +_cairo_surface_tag (cairo_surface_t *surface, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip) +{ + cairo_int_status_t status; + + TRACE ((stderr, "%s\n", __FUNCTION__)); + if (unlikely (surface->status)) + return surface->status; + if (unlikely (surface->finished)) + return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); + + if (surface->backend->tag == NULL) + return CAIRO_STATUS_SUCCESS; + + if (begin) { + status = _pattern_has_error (source); + if (unlikely (status)) + return status; + } + + status = surface->backend->tag (surface, begin, tag_name, attributes, + source, stroke_style, + ctm, ctm_inverse, clip); + + return _cairo_surface_set_error (surface, status); +} + + /** * _cairo_surface_set_resolution: * @surface: the surface @@ -2725,6 +3050,10 @@ _cairo_surface_create_in_error (cairo_status_t status) case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: case CAIRO_STATUS_DEVICE_FINISHED: case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: + case CAIRO_STATUS_PNG_ERROR: + case CAIRO_STATUS_FREETYPE_ERROR: + case CAIRO_STATUS_WIN32_GDI_ERROR: + case CAIRO_STATUS_TAG_ERROR: default: _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t *) &_cairo_surface_nil; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-svg-surface-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-svg-surface-private.h index ddbf464b1d2..6f693252a89 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-svg-surface-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-svg-surface-private.h @@ -48,6 +48,13 @@ typedef struct cairo_svg_document cairo_svg_document_t; +typedef struct _cairo_svg_source_surface { + cairo_hash_entry_t base; + unsigned int id; + unsigned char *unique_id; + unsigned long unique_id_length; +} cairo_svg_source_surface_t; + typedef struct cairo_svg_surface { cairo_surface_t base; @@ -55,11 +62,13 @@ typedef struct cairo_svg_surface { double width; double height; + cairo_bool_t surface_bounded; cairo_svg_document_t *document; cairo_output_stream_t *xml_node; cairo_array_t page_set; + cairo_hash_table_t *source_surfaces; cairo_surface_clipper_t clipper; unsigned int clip_level; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-svg-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-svg-surface.c index d9f4b92652e..dd37198eff3 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-svg-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-svg-surface.c @@ -94,6 +94,7 @@ static const char *_cairo_svg_supported_mime_types[] = { CAIRO_MIME_TYPE_JPEG, CAIRO_MIME_TYPE_PNG, + CAIRO_MIME_TYPE_UNIQUE_ID, CAIRO_MIME_TYPE_URI, NULL }; @@ -121,6 +122,20 @@ static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST] "1.2" }; +static const char * _cairo_svg_unit_strings[] = +{ + "", + "em", + "ex", + "px", + "in", + "cm", + "mm", + "pt", + "pc", + "%" +}; + struct cairo_svg_page { unsigned int surface_id; unsigned int clip_level; @@ -135,6 +150,7 @@ struct cairo_svg_document { double width; double height; + cairo_svg_unit_t unit; cairo_output_stream_t *xml_node_defs; cairo_output_stream_t *xml_node_glyphs; @@ -176,7 +192,9 @@ static cairo_surface_t * _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, cairo_content_t content, double width, - double height); + double height, + cairo_bool_t bounded); + static cairo_surface_t * _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, double width, @@ -252,6 +270,9 @@ cairo_svg_surface_create_for_stream (cairo_write_func_t write_func, * or %CAIRO_MIME_TYPE_PNG is specified, the corresponding data is * Base64-encoded and emitted. * + * If %CAIRO_MIME_TYPE_UNIQUE_ID is present, all surfaces with the same + * unique identifier will only be embedded once. + * * Return value: a pointer to the newly created surface. The caller * owns the surface and should call cairo_surface_destroy() when done * with it. @@ -399,6 +420,164 @@ cairo_svg_version_to_string (cairo_svg_version_t version) return _cairo_svg_version_strings[version]; } +/** + * cairo_svg_surface_set_document_unit: + * @surface: a SVG #cairo_surface_t + * @unit: SVG unit + * + * Use the specified unit for the width and height of the generated SVG file. + * See #cairo_svg_unit_t for a list of available unit values that can be used + * here. + * + * This function can be called at any time before generating the SVG file. + * + * However to minimize the risk of ambiguities it's recommended to call it + * before any drawing operations have been performed on the given surface, to + * make it clearer what the unit used in the drawing operations is. + * + * The simplest way to do this is to call this function immediately after + * creating the SVG surface. + * + * Note if this function is never called, the default unit for SVG documents + * generated by cairo will be "pt". This is for historical reasons. + * + * Since: 1.16 + **/ +void +cairo_svg_surface_set_document_unit (cairo_surface_t *abstract_surface, + cairo_svg_unit_t unit) +{ + cairo_svg_surface_t *surface = NULL; /* hide compiler warning */ + + if (! _extract_svg_surface (abstract_surface, &surface)) + return; + + if (unit <= CAIRO_SVG_UNIT_PERCENT) + surface->document->unit = unit; +} + +/** + * cairo_svg_surface_get_document_unit: + * @surface: a SVG #cairo_surface_t + * + * Get the unit of the SVG surface. + * + * If the surface passed as an argument is not a SVG surface, the function + * sets the error status to CAIRO_STATUS_SURFACE_TYPE_MISMATCH and returns + * CAIRO_SVG_UNIT_USER. + * + * Return value: the SVG unit of the SVG surface. + * + * Since: 1.16 + **/ +cairo_svg_unit_t +cairo_svg_surface_get_document_unit (cairo_surface_t *abstract_surface) +{ + cairo_svg_surface_t *surface = NULL; /* hide compiler warning */ + + if (! _extract_svg_surface (abstract_surface, &surface)) { + _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); + return CAIRO_SVG_UNIT_USER; + } + + return surface->document->unit; +} + +static void +_cairo_svg_source_surface_init_key (cairo_svg_source_surface_t *key) +{ + if (key->unique_id && key->unique_id_length > 0) { + key->base.hash = _cairo_hash_bytes (_CAIRO_HASH_INIT_VALUE, + key->unique_id, key->unique_id_length); + } else { + key->base.hash = key->id; + } +} + +static cairo_bool_t +_cairo_svg_source_surface_equal (const void *key_a, const void *key_b) +{ + const cairo_svg_source_surface_t *a = key_a; + const cairo_svg_source_surface_t *b = key_b; + + if (a->unique_id && b->unique_id && a->unique_id_length == b->unique_id_length) + return (memcmp (a->unique_id, b->unique_id, a->unique_id_length) == 0); + + return (a->id == b->id); +} + +static void +_cairo_svg_source_surface_pluck (void *entry, void *closure) +{ + cairo_svg_source_surface_t *surface_entry = entry; + cairo_hash_table_t *patterns = closure; + + _cairo_hash_table_remove (patterns, &surface_entry->base); + free (surface_entry->unique_id); + free (surface_entry); +} + +static cairo_status_t +_cairo_svg_surface_add_source_surface (cairo_svg_surface_t *surface, + cairo_surface_t *source_surface, + int *source_id, + cairo_bool_t *is_new) +{ + cairo_svg_source_surface_t source_key; + cairo_svg_source_surface_t *source_entry; + unsigned char *unique_id = NULL; + unsigned long unique_id_length = 0; + cairo_status_t status; + + source_key.id = source_surface->unique_id; + cairo_surface_get_mime_data (source_surface, CAIRO_MIME_TYPE_UNIQUE_ID, + (const unsigned char **) &source_key.unique_id, + &source_key.unique_id_length); + _cairo_svg_source_surface_init_key (&source_key); + source_entry = _cairo_hash_table_lookup (surface->source_surfaces, &source_key.base); + if (source_entry) { + *source_id = source_entry->id; + *is_new = FALSE; + return CAIRO_STATUS_SUCCESS; + } + + if (source_key.unique_id && source_key.unique_id_length > 0) { + unique_id = _cairo_malloc (source_key.unique_id_length); + if (unique_id == NULL) { + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } + + unique_id_length = source_key.unique_id_length; + memcpy (unique_id, source_key.unique_id, unique_id_length); + } else { + unique_id = NULL; + unique_id_length = 0; + } + + source_entry = malloc (sizeof (cairo_svg_source_surface_t)); + if (source_entry == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto fail; + } + + source_entry->id = source_key.id; + source_entry->unique_id_length = unique_id_length; + source_entry->unique_id = unique_id; + _cairo_svg_source_surface_init_key (source_entry); + status = _cairo_hash_table_insert (surface->source_surfaces, &source_entry->base); + if (unlikely(status)) + goto fail; + + *is_new = TRUE; + *source_id = source_entry->id; + return CAIRO_STATUS_SUCCESS; + + fail: + free (unique_id); + free (source_entry); + return status; +} + static cairo_bool_t _cliprect_covers_surface (cairo_svg_surface_t *surface, cairo_path_fixed_t *path) @@ -470,23 +649,26 @@ static cairo_surface_t * _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, cairo_content_t content, double width, - double height) + double height, + cairo_bool_t bounded) { cairo_svg_surface_t *surface; cairo_surface_t *paginated; cairo_status_t status, status_ignored; - surface = malloc (sizeof (cairo_svg_surface_t)); + surface = _cairo_malloc (sizeof (cairo_svg_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &cairo_svg_surface_backend, NULL, /* device */ - content); + content, + TRUE); /* is_vector */ surface->width = width; surface->height = height; + surface->surface_bounded = bounded; surface->document = _cairo_svg_document_reference (document); @@ -519,6 +701,12 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, surface->force_fallbacks = FALSE; surface->content = content; + surface->source_surfaces = _cairo_hash_table_create (_cairo_svg_source_surface_equal); + if (unlikely (surface->source_surfaces == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto CLEANUP; + } + paginated = _cairo_paginated_surface_create (&surface->base, surface->content, &cairo_svg_surface_paginated_backend); @@ -560,7 +748,7 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream, } surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA, - width, height); + width, height, TRUE); if (surface->status) { status = _cairo_svg_document_destroy (document); return surface; @@ -1010,6 +1198,11 @@ _cairo_svg_surface_finish (void *abstract_surface) _cairo_surface_clipper_reset (&surface->clipper); + _cairo_hash_table_foreach (surface->source_surfaces, + _cairo_svg_source_surface_pluck, + surface->source_surfaces); + _cairo_hash_table_destroy (surface->source_surfaces); + status2 = _cairo_svg_document_destroy (document); if (status == CAIRO_STATUS_SUCCESS) status = status2; @@ -1281,7 +1474,8 @@ _cairo_svg_surface_emit_attr_value (cairo_output_stream_t *stream, static cairo_status_t _cairo_svg_surface_emit_surface (cairo_svg_document_t *document, - cairo_surface_t *surface) + cairo_surface_t *surface, + int source_id) { cairo_rectangle_int_t extents; cairo_bool_t is_bounded; @@ -1289,18 +1483,12 @@ _cairo_svg_surface_emit_surface (cairo_svg_document_t *document, const unsigned char *uri; unsigned long uri_len; - if (_cairo_user_data_array_get_data (&surface->user_data, - (cairo_user_data_key_t *) document)) - { - return CAIRO_STATUS_SUCCESS; - } - is_bounded = _cairo_surface_get_extents (surface, &extents); assert (is_bounded); _cairo_output_stream_printf (document->xml_node_defs, "unique_id, + source_id, extents.width, extents.height); _cairo_output_stream_printf (document->xml_node_defs, " xlink:href=\""); @@ -1319,10 +1507,7 @@ _cairo_svg_surface_emit_surface (cairo_svg_document_t *document, _cairo_output_stream_printf (document->xml_node_defs, "\"/>\n"); - /* and tag it */ - return _cairo_user_data_array_set_data (&surface->user_data, - (cairo_user_data_key_t *) document, - document, NULL); + return CAIRO_STATUS_SUCCESS; } static cairo_status_t @@ -1336,17 +1521,29 @@ _cairo_svg_surface_emit_composite_surface_pattern (cairo_output_stream_t *outp { cairo_status_t status; cairo_matrix_t p2u; + int source_id; + cairo_bool_t is_new; p2u = pattern->base.matrix; status = cairo_matrix_invert (&p2u); /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_STATUS_SUCCESS); - status = _cairo_svg_surface_emit_surface (svg_surface->document, - pattern->surface); + status = _cairo_svg_surface_add_source_surface (svg_surface, + pattern->surface, + &source_id, + &is_new); if (unlikely (status)) return status; + if (is_new) { + status = _cairo_svg_surface_emit_surface (svg_surface->document, + pattern->surface, + source_id); + if (unlikely (status)) + return status; + } + if (pattern_id != invalid_pattern_id) { cairo_rectangle_int_t extents; cairo_bool_t is_bounded; @@ -1368,7 +1565,7 @@ _cairo_svg_surface_emit_composite_surface_pattern (cairo_output_stream_t *outp _cairo_output_stream_printf (output, "surface->unique_id); + source_id); if (extra_attributes) _cairo_output_stream_printf (output, " %s", extra_attributes); @@ -1389,25 +1586,23 @@ _cairo_svg_surface_emit_composite_surface_pattern (cairo_output_stream_t *outp static cairo_status_t _cairo_svg_surface_emit_recording_surface (cairo_svg_document_t *document, - cairo_recording_surface_t *source) + cairo_recording_surface_t *source, + int source_id) { cairo_status_t status; cairo_surface_t *paginated_surface; cairo_svg_surface_t *svg_surface; cairo_array_t *page_set; - + cairo_rectangle_int_t extents; + cairo_bool_t bounded; cairo_output_stream_t *contents; - if (_cairo_user_data_array_get_data (&source->base.user_data, - (cairo_user_data_key_t *) document)) - { - return CAIRO_STATUS_SUCCESS; - } - + bounded = _cairo_surface_get_extents (&source->base, &extents); paginated_surface = _cairo_svg_surface_create_for_document (document, source->base.content, - source->extents_pixels.width, - source->extents_pixels.height); + extents.width, + extents.height, + bounded); if (unlikely (paginated_surface->status)) return paginated_surface->status; @@ -1435,13 +1630,17 @@ _cairo_svg_surface_emit_recording_surface (cairo_svg_document_t *document, if (! svg_surface->is_base_clip_emitted) { svg_surface->is_base_clip_emitted = TRUE; - _cairo_output_stream_printf (document->xml_node_defs, - "\n" - " \n" - "\n", - svg_surface->base_clip, - svg_surface->width, - svg_surface->height); + if (_cairo_surface_get_extents (&svg_surface->base, &extents)) { + _cairo_output_stream_printf (document->xml_node_defs, + "\n" + " \n" + "\n", + svg_surface->base_clip, + extents.x, + extents.y, + extents.width, + extents.height); + } } if (source->base.content == CAIRO_CONTENT_ALPHA) { @@ -1450,13 +1649,13 @@ _cairo_svg_surface_emit_recording_surface (cairo_svg_document_t *document, "\n", - source->base.unique_id, + source_id, svg_surface->base_clip); } else { _cairo_output_stream_printf (document->xml_node_defs, "\n", - source->base.unique_id, + source_id, svg_surface->base_clip); } @@ -1482,13 +1681,7 @@ _cairo_svg_surface_emit_recording_surface (cairo_svg_document_t *document, status = cairo_surface_status (paginated_surface); cairo_surface_destroy (paginated_surface); - if (unlikely (status)) - return status; - - /* and tag it */ - return _cairo_user_data_array_set_data (&source->base.user_data, - (cairo_user_data_key_t *) document, - document, NULL); + return status; } static cairo_recording_surface_t * @@ -1515,17 +1708,28 @@ _cairo_svg_surface_emit_composite_recording_pattern (cairo_output_stream_t *outp cairo_recording_surface_t *recording_surface; cairo_matrix_t p2u; cairo_status_t status; + int source_id; + cairo_bool_t is_new; p2u = pattern->base.matrix; status = cairo_matrix_invert (&p2u); /* cairo_pattern_set_matrix ensures the matrix is invertible */ assert (status == CAIRO_STATUS_SUCCESS); - recording_surface = to_recording_surface (pattern); - status = _cairo_svg_surface_emit_recording_surface (document, recording_surface); + status = _cairo_svg_surface_add_source_surface (surface, + pattern->surface, + &source_id, + &is_new); if (unlikely (status)) return status; + recording_surface = to_recording_surface (pattern); + if (is_new) { + status = _cairo_svg_surface_emit_recording_surface (document, recording_surface, source_id); + if (unlikely (status)) + return status; + } + if (pattern_id != invalid_pattern_id) { _cairo_output_stream_printf (output, "base.unique_id); + source_id); if (pattern_id == invalid_pattern_id) { _cairo_svg_surface_emit_operator (output, surface, op); @@ -2257,7 +2461,7 @@ _cairo_svg_surface_get_extents (void *abstract_surface, rectangle->width = ceil (surface->width); rectangle->height = ceil (surface->height); - return TRUE; + return surface->surface_bounded; } static cairo_status_t @@ -2658,7 +2862,7 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream, if (output_stream->status) return output_stream->status; - document = malloc (sizeof (cairo_svg_document_t)); + document = _cairo_malloc (sizeof (cairo_svg_document_t)); if (unlikely (document == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -2675,6 +2879,7 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream, document->finished = FALSE; document->width = width; document->height = height; + document->unit = CAIRO_SVG_UNIT_PT; document->linear_pattern_id = 0; document->radial_pattern_id = 0; @@ -2777,9 +2982,10 @@ _cairo_svg_document_finish (cairo_svg_document_t *document) "\n" "\n", - document->width, document->height, + document->width, _cairo_svg_unit_strings [document->unit], + document->height, _cairo_svg_unit_strings [document->unit], document->width, document->height, _cairo_svg_internal_version_strings [document->svg_version]); @@ -2851,13 +3057,15 @@ _cairo_svg_document_finish (cairo_svg_document_t *document) return status; } -static void +static cairo_int_status_t _cairo_svg_surface_set_paginated_mode (void *abstract_surface, cairo_paginated_mode_t paginated_mode) { cairo_svg_surface_t *surface = abstract_surface; surface->paginated_mode = paginated_mode; + + return CAIRO_STATUS_SUCCESS; } static cairo_bool_t diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-svg.h b/Build/source/libs/cairo/cairo-src/src/cairo-svg.h index 592c645f627..4d24857bcaa 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-svg.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-svg.h @@ -53,6 +53,46 @@ typedef enum _cairo_svg_version { CAIRO_SVG_VERSION_1_2 } cairo_svg_version_t; +/** + * cairo_svg_unit_t: + * + * @CAIRO_SVG_UNIT_USER: User unit, a value in the current coordinate system. + * If used in the root element for the initial coordinate systems it + * corresponds to pixels. (Since 1.16) + * @CAIRO_SVG_UNIT_EM: The size of the element's font. (Since 1.16) + * @CAIRO_SVG_UNIT_EX: The x-height of the element’s font. (Since 1.16) + * @CAIRO_SVG_UNIT_PX: Pixels (1px = 1/96th of 1in). (Since 1.16) + * @CAIRO_SVG_UNIT_IN: Inches (1in = 2.54cm = 96px). (Since 1.16) + * @CAIRO_SVG_UNIT_CM: Centimeters (1cm = 96px/2.54). (Since 1.16) + * @CAIRO_SVG_UNIT_MM: Millimeters (1mm = 1/10th of 1cm). (Since 1.16) + * @CAIRO_SVG_UNIT_PT: Points (1pt = 1/72th of 1in). (Since 1.16) + * @CAIRO_SVG_UNIT_PC: Picas (1pc = 1/6th of 1in). (Since 1.16) + * @CAIRO_SVG_UNIT_PERCENT: Percent, a value that is some fraction of another + * reference value. (Since 1.16) + * + * #cairo_svg_unit_t is used to describe the units valid for coordinates and + * lengths in the SVG specification. + * + * See also: + * https://www.w3.org/TR/SVG/coords.html#Units + * https://www.w3.org/TR/SVG/types.html#DataTypeLength + * https://www.w3.org/TR/css-values-3/#lengths + * + * Since: 1.16 + **/ +typedef enum _cairo_svg_unit { + CAIRO_SVG_UNIT_USER = 0, + CAIRO_SVG_UNIT_EM, + CAIRO_SVG_UNIT_EX, + CAIRO_SVG_UNIT_PX, + CAIRO_SVG_UNIT_IN, + CAIRO_SVG_UNIT_CM, + CAIRO_SVG_UNIT_MM, + CAIRO_SVG_UNIT_PT, + CAIRO_SVG_UNIT_PC, + CAIRO_SVG_UNIT_PERCENT +} cairo_svg_unit_t; + cairo_public cairo_surface_t * cairo_svg_surface_create (const char *filename, double width_in_points, @@ -75,6 +115,13 @@ cairo_svg_get_versions (cairo_svg_version_t const **versions, cairo_public const char * cairo_svg_version_to_string (cairo_svg_version_t version); +cairo_public void +cairo_svg_surface_set_document_unit (cairo_surface_t *surface, + cairo_svg_unit_t unit); + +cairo_public cairo_svg_unit_t +cairo_svg_surface_get_document_unit (cairo_surface_t *surface); + CAIRO_END_DECLS #else /* CAIRO_HAS_SVG_SURFACE */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-tag-attributes-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-tag-attributes-private.h new file mode 100644 index 00000000000..3f5fa5b64a2 --- /dev/null +++ b/Build/source/libs/cairo/cairo-src/src/cairo-tag-attributes-private.h @@ -0,0 +1,99 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2016 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 the cairo graphics library. + * + * The Initial Developer of the Original Code is Adrian Johnson. + * + * Contributor(s): + * Adrian Johnson + */ + +#ifndef CAIRO_TAG_ATTRIBUTES_PRIVATE_H +#define CAIRO_TAG_ATTRIBUTES_PRIVATE_H + +#include "cairo-array-private.h" +#include "cairo-error-private.h" +#include "cairo-types-private.h" + +typedef enum { + TAG_LINK_INVALID = 0, + TAG_LINK_EMPTY, + TAG_LINK_DEST, + TAG_LINK_URI, + TAG_LINK_FILE, +} cairo_tag_link_type_t; + +typedef struct _cairo_link_attrs { + cairo_tag_link_type_t link_type; + cairo_array_t rects; + char *dest; + char *uri; + char *file; + int page; + cairo_bool_t has_pos; + cairo_point_double_t pos; +} cairo_link_attrs_t; + +typedef struct _cairo_dest_attrs { + char *name; + double x; + double y; + cairo_bool_t x_valid; + cairo_bool_t y_valid; + cairo_bool_t internal; +} cairo_dest_attrs_t; + +typedef struct _cairo_ccitt_params { + int columns; + int rows; + int k; + cairo_bool_t end_of_line; + cairo_bool_t encoded_byte_align; + cairo_bool_t end_of_block; + cairo_bool_t black_is_1; + int damaged_rows_before_error; +} cairo_ccitt_params_t; + +typedef struct _cairo_eps_params { + cairo_box_double_t bbox; +} cairo_eps_params_t; + +cairo_private cairo_int_status_t +_cairo_tag_parse_link_attributes (const char *attributes, cairo_link_attrs_t *link_attrs); + +cairo_private cairo_int_status_t +_cairo_tag_parse_dest_attributes (const char *attributes, cairo_dest_attrs_t *dest_attrs); + +cairo_private cairo_int_status_t +_cairo_tag_parse_ccitt_params (const char *attributes, cairo_ccitt_params_t *dest_attrs); + +cairo_private cairo_int_status_t +_cairo_tag_parse_eps_params (const char *attributes, cairo_eps_params_t *dest_attrs); + +#endif /* CAIRO_TAG_ATTRIBUTES_PRIVATE_H */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-tag-attributes.c b/Build/source/libs/cairo/cairo-src/src/cairo-tag-attributes.c new file mode 100644 index 00000000000..44b1147fb91 --- /dev/null +++ b/Build/source/libs/cairo/cairo-src/src/cairo-tag-attributes.c @@ -0,0 +1,702 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2016 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 the cairo graphics library. + * + * The Initial Developer of the Original Code is Adrian Johnson. + * + * Contributor(s): + * Adrian Johnson + */ + +#include "cairoint.h" + +#include "cairo-array-private.h" +#include "cairo-list-inline.h" +#include "cairo-tag-attributes-private.h" + +#include + +typedef enum { + ATTRIBUTE_BOOL, /* Either true/false or 1/0 may be used. */ + ATTRIBUTE_INT, + ATTRIBUTE_FLOAT, /* Decimal separator is in current locale. */ + ATTRIBUTE_STRING, /* Enclose in single quotes. String escapes: + * \' - single quote + * \\ - backslash + */ +} attribute_type_t; + +typedef struct _attribute_spec { + const char *name; + attribute_type_t type; + int array_size; /* 0 = scalar, -1 = variable size array */ +} attribute_spec_t; + +/* + * name [required] Unique name of this destination (UTF-8) + * x [optional] x coordinate of destination on page. Default is x coord of + * extents of operations enclosed by the dest begin/end tags. + * y [optional] y coordinate of destination on page. Default is y coord of + * extents of operations enclosed by the dest begin/end tags. + * internal [optional] If true, the name may be optimized out of the PDF where + * possible. Default false. + */ +static attribute_spec_t _dest_attrib_spec[] = { + { "name", ATTRIBUTE_STRING }, + { "x", ATTRIBUTE_FLOAT }, + { "y", ATTRIBUTE_FLOAT }, + { "internal", ATTRIBUTE_BOOL }, + { NULL } +}; + +/* + * rect [optional] One or more rectangles to define link region. Default + * is the extents of the operations enclosed by the link begin/end tags. + * Each rectangle is specified by four array elements: x, y, width, height. + * ie the array size must be a multiple of four. + * + * Internal Links + * -------------- + * either: + * dest - name of dest tag in the PDF file to link to (UTF8) + * or + * page - Page number in the PDF file to link to + * pos - [optional] Position of destination on page. Default is 0,0. + * + * URI Links + * --------- + * uri [required] Uniform resource identifier (ASCII). + + * File Links + * ---------- + * file - [required] File name of PDF file to link to. + * either: + * dest - name of dest tag in the PDF file to link to (UTF8) + * or + * page - Page number in the PDF file to link to + * pos - [optional] Position of destination on page. Default is 0,0. + */ +static attribute_spec_t _link_attrib_spec[] = +{ + { "rect", ATTRIBUTE_FLOAT, -1 }, + { "dest", ATTRIBUTE_STRING }, + { "uri", ATTRIBUTE_STRING }, + { "file", ATTRIBUTE_STRING }, + { "page", ATTRIBUTE_INT }, + { "pos", ATTRIBUTE_FLOAT, 2 }, + { NULL } +}; + +/* + * Required: + * Columns - width of the image in pixels. + * Rows - height of the image in scan lines. + * + * Optional: + * K - An integer identifying the encoding scheme used. < 0 is 2 dimensional + * Group 4, = 0 is Group3 1 dimensional, > 0 is mixed 1 and 2 dimensional + * encoding. Default: 0. + * EndOfLine - If true end-of-line bit patterns are present. Default: false. + * EncodedByteAlign - If true the end of line is padded with 0 bits so the next + * line begins on a byte boundary. Default: false. + * EndOfBlock - If true the data contains an end-of-block pattern. Default: true. + * BlackIs1 - If true 1 bits are black pixels. Default: false. + * DamagedRowsBeforeError - Number of damages rows tolerated before an error + * occurs. Default: 0. + */ +static attribute_spec_t _ccitt_params_spec[] = +{ + { "Columns", ATTRIBUTE_INT }, + { "Rows", ATTRIBUTE_INT }, + { "K", ATTRIBUTE_INT }, + { "EndOfLine", ATTRIBUTE_BOOL }, + { "EncodedByteAlign", ATTRIBUTE_BOOL }, + { "EndOfBlock", ATTRIBUTE_BOOL }, + { "BlackIs1", ATTRIBUTE_BOOL }, + { "DamagedRowsBeforeError", ATTRIBUTE_INT }, + { NULL } +}; + +/* + * bbox - Bounding box of EPS file. The format is [ llx lly urx ury ] + * llx - lower left x xoordinate + * lly - lower left y xoordinate + * urx - upper right x xoordinate + * ury - upper right y xoordinate + * all cordinates are in PostScript coordinates. + */ +static attribute_spec_t _eps_params_spec[] = +{ + { "bbox", ATTRIBUTE_FLOAT, 4 }, + { NULL } +}; + +typedef union { + cairo_bool_t b; + int i; + double f; + char *s; +} attrib_val_t; + +typedef struct _attribute { + char *name; + attribute_type_t type; + int array_len; /* 0 = scalar */ + attrib_val_t scalar; + cairo_array_t array; /* array of attrib_val_t */ + cairo_list_t link; +} attribute_t; + +static const char * +skip_space (const char *p) +{ + while (_cairo_isspace (*p)) + p++; + + return p; +} + +static const char * +parse_bool (const char *p, cairo_bool_t *b) +{ + if (*p == '1') { + *b = TRUE; + return p + 1; + } else if (*p == '0') { + *b = FALSE; + return p + 1; + } else if (strcmp (p, "true") == 0) { + *b = TRUE; + return p + 4; + } else if (strcmp (p, "false") == 0) { + *b = FALSE; + return p + 5; + } + + return NULL; +} + +static const char * +parse_int (const char *p, int *i) +{ + int n; + + if (sscanf(p, "%d%n", i, &n) > 0) + return p + n; + + return NULL; +} + +static const char * +parse_float (const char *p, double *d) +{ + int n; + + if (sscanf(p, "%lf%n", d, &n) > 0) + return p + n; + + return NULL; +} + +static const char * +decode_string (const char *p, int *len, char *s) +{ + if (*p != '\'') + return NULL; + + p++; + if (! *p) + return NULL; + + *len = 0; + while (*p) { + if (*p == '\\') { + p++; + if (*p) { + if (s) + *s++ = *p; + p++; + (*len)++; + } + } else if (*p == '\'') { + return p + 1; + } else { + if (s) + *s++ = *p; + p++; + (*len)++; + } + } + + return NULL; +} + +static const char * +parse_string (const char *p, char **s) +{ + const char *end; + int len; + + end = decode_string (p, &len, NULL); + if (!end) + return NULL; + + *s = _cairo_malloc (len + 1); + decode_string (p, &len, *s); + (*s)[len] = 0; + + return end; +} + +static const char * +parse_scalar (const char *p, attribute_type_t type, attrib_val_t *scalar) +{ + switch (type) { + case ATTRIBUTE_BOOL: + return parse_bool (p, &scalar->b); + case ATTRIBUTE_INT: + return parse_int (p, &scalar->i); + case ATTRIBUTE_FLOAT: + return parse_float (p, &scalar->f); + case ATTRIBUTE_STRING: + return parse_string (p, &scalar->s); + } + + return NULL; +} + +static cairo_int_status_t +parse_array (const char *p, attribute_type_t type, cairo_array_t *array, const char **end) +{ + attrib_val_t val; + cairo_int_status_t status; + + p = skip_space (p); + if (! *p) + return _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + + if (*p++ != '[') + return _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + + while (TRUE) { + p = skip_space (p); + if (! *p) + return _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + + if (*p == ']') { + *end = p + 1; + return CAIRO_INT_STATUS_SUCCESS; + } + + p = parse_scalar (p, type, &val); + if (!p) + return _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + + status = _cairo_array_append (array, &val); + if (unlikely (status)) + return status; + } + + return _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); +} + +static cairo_int_status_t +parse_name (const char *p, const char **end, char **s) +{ + const char *p2; + char *name; + int len; + + if (! _cairo_isalpha (*p)) + return _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + + p2 = p; + while (_cairo_isalpha (*p2) || _cairo_isdigit (*p2)) + p2++; + + len = p2 - p; + name = _cairo_malloc (len + 1); + if (unlikely (name == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + memcpy (name, p, len); + name[len] = 0; + *s = name; + *end = p2; + + return CAIRO_INT_STATUS_SUCCESS; +} + +static cairo_int_status_t +parse_attributes (const char *attributes, attribute_spec_t *attrib_def, cairo_list_t *list) +{ + attribute_spec_t *def; + attribute_t *attrib; + char *name = NULL; + cairo_int_status_t status; + const char *p = attributes; + + if (! p) + return _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + + while (*p) { + p = skip_space (p); + if (! *p) + break; + + status = parse_name (p, &p, &name); + if (status) + return status; + + def = attrib_def; + while (def->name) { + if (strcmp (name, def->name) == 0) + break; + def++; + } + if (! def->name) { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto fail1; + } + + attrib = calloc (1, sizeof (attribute_t)); + if (unlikely (attrib == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto fail1; + } + + attrib->name = name; + attrib->type = def->type; + _cairo_array_init (&attrib->array, sizeof(attrib_val_t)); + + p = skip_space (p); + if (def->type == ATTRIBUTE_BOOL && *p != '=') { + attrib->scalar.b = TRUE; + } else { + if (*p++ != '=') { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto fail2; + } + + if (def->array_size == 0) { + p = parse_scalar (p, def->type, &attrib->scalar); + if (!p) { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto fail2; + } + + attrib->array_len = 0; + } else { + status = parse_array (p, def->type, &attrib->array, &p); + if (unlikely (status)) + goto fail2; + + attrib->array_len = _cairo_array_num_elements (&attrib->array); + if (def->array_size > 0 && attrib->array_len != def->array_size) { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto fail2; + } + } + } + + cairo_list_add_tail (&attrib->link, list); + } + + return CAIRO_INT_STATUS_SUCCESS; + + fail2: + _cairo_array_fini (&attrib->array); + if (attrib->type == ATTRIBUTE_STRING) + free (attrib->scalar.s); + free (attrib); + fail1: + free (name); + + return status; +} + +static void +free_attributes_list (cairo_list_t *list) +{ + attribute_t *attr, *next; + + cairo_list_foreach_entry_safe (attr, next, attribute_t, list, link) + { + cairo_list_del (&attr->link); + free (attr->name); + _cairo_array_fini (&attr->array); + if (attr->type == ATTRIBUTE_STRING) + free (attr->scalar.s); + free (attr); + } +} + +static attribute_t * +find_attribute (cairo_list_t *list, const char *name) +{ + attribute_t *attr; + + cairo_list_foreach_entry (attr, attribute_t, list, link) + { + if (strcmp (attr->name, name) == 0) + return attr; + } + + return NULL; +} + +cairo_int_status_t +_cairo_tag_parse_link_attributes (const char *attributes, cairo_link_attrs_t *link_attrs) +{ + cairo_list_t list; + cairo_int_status_t status; + attribute_t *attr; + attrib_val_t val; + + cairo_list_init (&list); + status = parse_attributes (attributes, _link_attrib_spec, &list); + if (unlikely (status)) + return status; + + memset (link_attrs, 0, sizeof (cairo_link_attrs_t)); + _cairo_array_init (&link_attrs->rects, sizeof (cairo_rectangle_t)); + if (find_attribute (&list, "uri")) { + link_attrs->link_type = TAG_LINK_URI; + } else if (find_attribute (&list, "file")) { + link_attrs->link_type = TAG_LINK_FILE; + } else if (find_attribute (&list, "dest")) { + link_attrs->link_type = TAG_LINK_DEST; + } else if (find_attribute (&list, "page")) { + link_attrs->link_type = TAG_LINK_DEST; + } else { + link_attrs->link_type = TAG_LINK_EMPTY; + goto cleanup; + } + + cairo_list_foreach_entry (attr, attribute_t, &list, link) + { + if (strcmp (attr->name, "uri") == 0) { + if (link_attrs->link_type != TAG_LINK_URI) { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto cleanup; + } + + link_attrs->uri = strdup (attr->scalar.s); + } else if (strcmp (attr->name, "file") == 0) { + if (link_attrs->link_type != TAG_LINK_FILE) { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto cleanup; + } + + link_attrs->file = strdup (attr->scalar.s); + } else if (strcmp (attr->name, "dest") == 0) { + if (! (link_attrs->link_type == TAG_LINK_DEST || + link_attrs->link_type != TAG_LINK_FILE)) { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto cleanup; + } + + link_attrs->dest = strdup (attr->scalar.s); + } else if (strcmp (attr->name, "page") == 0) { + if (! (link_attrs->link_type == TAG_LINK_DEST || + link_attrs->link_type != TAG_LINK_FILE)) { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto cleanup; + } + + link_attrs->page = attr->scalar.i; + + } else if (strcmp (attr->name, "pos") == 0) { + if (! (link_attrs->link_type == TAG_LINK_DEST || + link_attrs->link_type != TAG_LINK_FILE)) { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto cleanup; + } + + _cairo_array_copy_element (&attr->array, 0, &val); + link_attrs->pos.x = val.f; + _cairo_array_copy_element (&attr->array, 1, &val); + link_attrs->pos.y = val.f; + link_attrs->has_pos = TRUE; + } else if (strcmp (attr->name, "rect") == 0) { + cairo_rectangle_t rect; + int i; + int num_elem = _cairo_array_num_elements (&attr->array); + if (num_elem == 0 || num_elem % 4 != 0) { + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + goto cleanup; + } + + for (i = 0; i < num_elem; i += 4) { + _cairo_array_copy_element (&attr->array, i, &val); + rect.x = val.f; + _cairo_array_copy_element (&attr->array, i+1, &val); + rect.y = val.f; + _cairo_array_copy_element (&attr->array, i+2, &val); + rect.width = val.f; + _cairo_array_copy_element (&attr->array, i+3, &val); + rect.height = val.f; + status = _cairo_array_append (&link_attrs->rects, &rect); + if (unlikely (status)) + goto cleanup; + } + } + } + + cleanup: + free_attributes_list (&list); + if (unlikely (status)) { + free (link_attrs->dest); + free (link_attrs->uri); + free (link_attrs->file); + _cairo_array_fini (&link_attrs->rects); + } + + return status; +} + +cairo_int_status_t +_cairo_tag_parse_dest_attributes (const char *attributes, cairo_dest_attrs_t *dest_attrs) +{ + cairo_list_t list; + cairo_int_status_t status; + attribute_t *attr; + + memset (dest_attrs, 0, sizeof (cairo_dest_attrs_t)); + cairo_list_init (&list); + status = parse_attributes (attributes, _dest_attrib_spec, &list); + if (unlikely (status)) + goto cleanup; + + cairo_list_foreach_entry (attr, attribute_t, &list, link) + { + if (strcmp (attr->name, "name") == 0) { + dest_attrs->name = strdup (attr->scalar.s); + } else if (strcmp (attr->name, "x") == 0) { + dest_attrs->x = attr->scalar.f; + dest_attrs->x_valid = TRUE; + } else if (strcmp (attr->name, "y") == 0) { + dest_attrs->y = attr->scalar.f; + dest_attrs->y_valid = TRUE; + } else if (strcmp (attr->name, "internal") == 0) { + dest_attrs->internal = attr->scalar.b; + } + } + + if (! dest_attrs->name) + status = _cairo_error (CAIRO_INT_STATUS_TAG_ERROR); + + cleanup: + free_attributes_list (&list); + + return status; +} + +cairo_int_status_t +_cairo_tag_parse_ccitt_params (const char *attributes, cairo_ccitt_params_t *ccitt_params) +{ + cairo_list_t list; + cairo_int_status_t status; + attribute_t *attr; + + ccitt_params->columns = -1; + ccitt_params->rows = -1; + + /* set defaults */ + ccitt_params->k = 0; + ccitt_params->end_of_line = FALSE; + ccitt_params->encoded_byte_align = FALSE; + ccitt_params->end_of_block = TRUE; + ccitt_params->black_is_1 = FALSE; + ccitt_params->damaged_rows_before_error = 0; + + cairo_list_init (&list); + status = parse_attributes (attributes, _ccitt_params_spec, &list); + if (unlikely (status)) + goto cleanup; + + cairo_list_foreach_entry (attr, attribute_t, &list, link) + { + if (strcmp (attr->name, "Columns") == 0) { + ccitt_params->columns = attr->scalar.i; + } else if (strcmp (attr->name, "Rows") == 0) { + ccitt_params->rows = attr->scalar.i; + } else if (strcmp (attr->name, "K") == 0) { + ccitt_params->k = attr->scalar.i; + } else if (strcmp (attr->name, "EndOfLine") == 0) { + ccitt_params->end_of_line = attr->scalar.b; + } else if (strcmp (attr->name, "EncodedByteAlign") == 0) { + ccitt_params->encoded_byte_align = attr->scalar.b; + } else if (strcmp (attr->name, "EndOfBlock") == 0) { + ccitt_params->end_of_block = attr->scalar.b; + } else if (strcmp (attr->name, "BlackIs1") == 0) { + ccitt_params->black_is_1 = attr->scalar.b; + } else if (strcmp (attr->name, "DamagedRowsBeforeError") == 0) { + ccitt_params->damaged_rows_before_error = attr->scalar.b; + } + } + + cleanup: + free_attributes_list (&list); + + return status; +} + +cairo_int_status_t +_cairo_tag_parse_eps_params (const char *attributes, cairo_eps_params_t *eps_params) +{ + cairo_list_t list; + cairo_int_status_t status; + attribute_t *attr; + attrib_val_t val; + + cairo_list_init (&list); + status = parse_attributes (attributes, _eps_params_spec, &list); + if (unlikely (status)) + goto cleanup; + + cairo_list_foreach_entry (attr, attribute_t, &list, link) + { + if (strcmp (attr->name, "bbox") == 0) { + _cairo_array_copy_element (&attr->array, 0, &val); + eps_params->bbox.p1.x = val.f; + _cairo_array_copy_element (&attr->array, 1, &val); + eps_params->bbox.p1.y = val.f; + _cairo_array_copy_element (&attr->array, 2, &val); + eps_params->bbox.p2.x = val.f; + _cairo_array_copy_element (&attr->array, 3, &val); + eps_params->bbox.p2.y = val.f; + } + } + + cleanup: + free_attributes_list (&list); + + return status; +} diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-tag-stack-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-tag-stack-private.h new file mode 100644 index 00000000000..4af2a85dec5 --- /dev/null +++ b/Build/source/libs/cairo/cairo-src/src/cairo-tag-stack-private.h @@ -0,0 +1,107 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2016 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 the cairo graphics library. + * + * The Initial Developer of the Original Code is Adrian Johnson. + * + * Contributor(s): + * Adrian Johnson + */ + +#ifndef CAIRO_TAG_STACK_PRIVATE_H +#define CAIRO_TAG_STACK_PRIVATE_H + +#include "cairo-error-private.h" +#include "cairo-list-inline.h" + +/* The type of a single tag */ +typedef enum { + TAG_TYPE_INVALID = 0, + TAG_TYPE_STRUCTURE = 1, + TAG_TYPE_LINK = 2, + TAG_TYPE_DEST = 4, +} cairo_tag_type_t; + +/* The type of the structure tree. */ +typedef enum _cairo_tag_stack_structure_type { + TAG_TREE_TYPE_TAGGED, /* compliant with Tagged PDF */ + TAG_TREE_TYPE_STRUCTURE, /* valid structure but not 'Tagged PDF' compliant */ + TAG_TREE_TYPE_LINK_ONLY, /* contains Link tags only */ + TAG_TREE_TYPE_NO_TAGS, /* no tags used */ + TAG_TREE_TYPE_INVALID, /* invalid tag structure */ +} cairo_tag_stack_structure_type_t; + +typedef struct _cairo_tag_stack_elem { + char *name; + char *attributes; + void *data; + cairo_list_t link; + +} cairo_tag_stack_elem_t; + +typedef struct _cairo_tag_stack { + cairo_list_t list; + cairo_tag_stack_structure_type_t type; + int size; + +} cairo_tag_stack_t; + +cairo_private void +_cairo_tag_stack_init (cairo_tag_stack_t *stack); + +cairo_private void +_cairo_tag_stack_fini (cairo_tag_stack_t *stack); + +cairo_private cairo_tag_stack_structure_type_t +_cairo_tag_stack_get_structure_type (cairo_tag_stack_t *stack); + +cairo_private cairo_int_status_t +_cairo_tag_stack_push (cairo_tag_stack_t *stack, + const char *name, + const char *attributes); + +cairo_private void +_cairo_tag_stack_set_top_data (cairo_tag_stack_t *stack, + void *data); + +cairo_private cairo_int_status_t +_cairo_tag_stack_pop (cairo_tag_stack_t *stack, + const char *name, + cairo_tag_stack_elem_t **elem); + +cairo_private cairo_tag_stack_elem_t * +_cairo_tag_stack_top_elem (cairo_tag_stack_t *stack); + +cairo_private void +_cairo_tag_stack_free_elem (cairo_tag_stack_elem_t *elem); + +cairo_private cairo_tag_type_t +_cairo_tag_get_type (const char *name); + +#endif /* CAIRO_TAG_STACK_PRIVATE_H */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-tag-stack.c b/Build/source/libs/cairo/cairo-src/src/cairo-tag-stack.c new file mode 100644 index 00000000000..7c2d5245e0a --- /dev/null +++ b/Build/source/libs/cairo/cairo-src/src/cairo-tag-stack.c @@ -0,0 +1,280 @@ +/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2016 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 the cairo graphics library. + * + * The Initial Developer of the Original Code is Adrian Johnson. + * + * Contributor(s): + * Adrian Johnson + */ + +#include "cairoint.h" + +#include "cairo-tag-stack-private.h" + +/* Tagged PDF must have one of these tags at the top level */ +static const char * _cairo_tag_stack_tagged_pdf_top_level_element_list[] = +{ + "Document", + "Part", + "Art", + "Sect", + "Div", + NULL +}; + +/* List of valid tag names. Table numbers reference PDF 32000 */ +static const char * _cairo_tag_stack_struct_pdf_list[] = +{ + /* Table 333 - Grouping Elements */ + "Document", + "Part", + "Art", + "Sect", + "Div", + "BlockQuote", + "Caption", + "TOC", + "TOCI", + "Index", + "NonStruct", + "Private", + + /* Table 335 - Standard structure types for paragraphlike elements */ + "P", "H", + "H1", "H2", "H3", "H4", "H5", "H6", + + /* Table 336 - Standard structure types for list elements */ + "L", "LI", "Lbl", "LBody", + + /* Table 337 - Standard structure types for table elements */ + "Table", + "TR", "TH", "TD", + "THead", "TBody", "TFoot", + + /* Table 338 - Standard structure types for inline-level structure elements */ + "Span", + "Quote", + "Note", + "Reference", + "BibEntry", + "Code", + "Link", /* CAIRO_TAG_LINK */ + "Annot", + "Ruby", + "Warichu", + + /* Table 339 - Standard structure types for Ruby and Warichu elements */ + "RB", "RT", "RP", + "WT", "WP", + + /* Table 340 - Standard structure types for illustration elements */ + "Figure", + "Formula", + "Form", + + NULL +}; + +/* List of cairo specific tag names */ +static const char * _cairo_tag_stack_cairo_tag_list[] = +{ + CAIRO_TAG_DEST, + NULL +}; + +void +_cairo_tag_stack_init (cairo_tag_stack_t *stack) +{ + cairo_list_init (&stack->list); + stack->type = TAG_TREE_TYPE_NO_TAGS; + stack->size = 0; +} + +void +_cairo_tag_stack_fini (cairo_tag_stack_t *stack) +{ + while (! cairo_list_is_empty (&stack->list)) { + cairo_tag_stack_elem_t *elem; + + elem = cairo_list_first_entry (&stack->list, cairo_tag_stack_elem_t, link); + cairo_list_del (&elem->link); + free (elem->name); + free (elem->attributes); + free (elem); + } +} + +cairo_tag_stack_structure_type_t +_cairo_tag_stack_get_structure_type (cairo_tag_stack_t *stack) +{ + return stack->type; +} + +static cairo_bool_t +name_in_list (const char *name, const char **list) +{ + if (! name) + return FALSE; + + while (*list) { + if (strcmp (name, *list) == 0) + return TRUE; + list++; + } + + return FALSE; +} + +cairo_int_status_t +_cairo_tag_stack_push (cairo_tag_stack_t *stack, + const char *name, + const char *attributes) +{ + cairo_tag_stack_elem_t *elem; + + if (! name_in_list (name, _cairo_tag_stack_struct_pdf_list) && + ! name_in_list (name, _cairo_tag_stack_cairo_tag_list)) + { + stack->type = TAG_TYPE_INVALID; + return _cairo_error (CAIRO_STATUS_TAG_ERROR); + } + + if (stack->type == TAG_TREE_TYPE_NO_TAGS) { + if (name_in_list (name, _cairo_tag_stack_tagged_pdf_top_level_element_list)) + stack->type = TAG_TREE_TYPE_TAGGED; + else if (strcmp (name, "Link") == 0) + stack->type = TAG_TREE_TYPE_LINK_ONLY; + else if (name_in_list (name, _cairo_tag_stack_struct_pdf_list)) + stack->type = TAG_TREE_TYPE_STRUCTURE; + } else { + if (stack->type == TAG_TREE_TYPE_LINK_ONLY && + (strcmp (name, "Link") != 0) && + name_in_list (name, _cairo_tag_stack_struct_pdf_list)) + { + stack->type = TAG_TREE_TYPE_STRUCTURE; + } + } + + elem = _cairo_malloc (sizeof(cairo_tag_stack_elem_t)); + if (unlikely (elem == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + elem->name = strdup (name); + if (unlikely (elem->name == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + if (attributes) { + elem->attributes = strdup (attributes); + if (unlikely (elem->attributes == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } else { + elem->attributes = NULL; + } + + elem->data = NULL; + + cairo_list_add_tail (&elem->link, &stack->list); + stack->size++; + + return CAIRO_STATUS_SUCCESS; +} + +cairo_private void +_cairo_tag_stack_set_top_data (cairo_tag_stack_t *stack, + void *data) +{ + cairo_tag_stack_elem_t *top; + + top = _cairo_tag_stack_top_elem (stack); + if (top) + top->data = data; +} + +cairo_int_status_t +_cairo_tag_stack_pop (cairo_tag_stack_t *stack, + const char *name, + cairo_tag_stack_elem_t **elem) +{ + cairo_tag_stack_elem_t *top; + + top = _cairo_tag_stack_top_elem (stack); + if (!top) { + stack->type = TAG_TYPE_INVALID; + return _cairo_error (CAIRO_STATUS_TAG_ERROR); + } + + cairo_list_del (&top->link); + stack->size--; + if (strcmp (top->name, name) != 0) { + stack->type = TAG_TYPE_INVALID; + _cairo_tag_stack_free_elem (top); + return _cairo_error (CAIRO_STATUS_TAG_ERROR); + } + + if (elem) + *elem = top; + else + _cairo_tag_stack_free_elem (top); + + return CAIRO_STATUS_SUCCESS; +} + +cairo_tag_stack_elem_t * +_cairo_tag_stack_top_elem (cairo_tag_stack_t *stack) +{ + if (cairo_list_is_empty (&stack->list)) + return NULL; + + return cairo_list_last_entry (&stack->list, cairo_tag_stack_elem_t, link); +} + +void +_cairo_tag_stack_free_elem (cairo_tag_stack_elem_t *elem) +{ + free (elem->name); + free (elem->attributes); + free (elem); +} + +cairo_tag_type_t +_cairo_tag_get_type (const char *name) +{ + if (! name_in_list (name, _cairo_tag_stack_struct_pdf_list) && + ! name_in_list (name, _cairo_tag_stack_cairo_tag_list)) + return TAG_TYPE_INVALID; + + if (strcmp(name, "Link") == 0) + return (TAG_TYPE_LINK | TAG_TYPE_STRUCTURE); + + if (strcmp(name, "cairo.dest") == 0) + return TAG_TYPE_DEST; + + return TAG_TYPE_STRUCTURE; +} diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-tee-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-tee-surface.c index 294e5f162e2..7a94c9bca4c 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-tee-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-tee-surface.c @@ -428,14 +428,15 @@ cairo_tee_surface_create (cairo_surface_t *master) if (unlikely (master->status)) return _cairo_surface_create_in_error (master->status); - surface = malloc (sizeof (cairo_tee_surface_t)); + surface = _cairo_malloc (sizeof (cairo_tee_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &cairo_tee_surface_backend, master->device, - master->content); + master->content, + TRUE); /* is_vector */ _cairo_surface_wrapper_init (&surface->master, master); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-tor-scan-converter.c b/Build/source/libs/cairo/cairo-src/src/cairo-tor-scan-converter.c index b1b51872b19..e8142d5bcf6 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-tor-scan-converter.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-tor-scan-converter.c @@ -29,7 +29,7 @@ * The source is from commit 734c53237a867a773640bd5b64816249fa1730f8 * of * - * http://gitweb.freedesktop.org/?p=users/joonas/glitter-paths + * https://gitweb.freedesktop.org/?p=users/joonas/glitter-paths */ /* Glitter-paths is a stand alone polygon rasteriser derived from * David Turner's reimplementation of Tor Anderssons's 15x17 @@ -483,7 +483,7 @@ _pool_chunk_create(struct pool *pool, size_t size) { struct _pool_chunk *p; - p = malloc(SIZEOF_POOL_CHUNK + size); + p = _cairo_malloc (SIZEOF_POOL_CHUNK + size); if (unlikely (NULL == p)) longjmp (*pool->jmp, _cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1872,7 +1872,7 @@ _cairo_tor_scan_converter_create (int xmin, cairo_tor_scan_converter_t *self; cairo_status_t status; - self = malloc (sizeof(struct _cairo_tor_scan_converter)); + self = _cairo_malloc (sizeof(struct _cairo_tor_scan_converter)); if (unlikely (self == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto bail_nomem; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-tor22-scan-converter.c b/Build/source/libs/cairo/cairo-src/src/cairo-tor22-scan-converter.c index 4cec5ee4f37..bf44742b0b3 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-tor22-scan-converter.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-tor22-scan-converter.c @@ -29,7 +29,7 @@ * The source is from commit 734c53237a867a773640bd5b64816249fa1730f8 * of * - * http://gitweb.freedesktop.org/?p=users/joonas/glitter-paths + * https://gitweb.freedesktop.org/?p=users/joonas/glitter-paths */ /* Glitter-paths is a stand alone polygon rasteriser derived from * David Turner's reimplementation of Tor Anderssons's 15x17 @@ -504,7 +504,7 @@ _pool_chunk_create(struct pool *pool, size_t size) { struct _pool_chunk *p; - p = malloc(size + sizeof(struct _pool_chunk)); + p = _cairo_malloc (size + sizeof(struct _pool_chunk)); if (unlikely (NULL == p)) longjmp (*pool->jmp, _cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1682,7 +1682,7 @@ _cairo_tor22_scan_converter_create (int xmin, cairo_tor22_scan_converter_t *self; cairo_status_t status; - self = malloc (sizeof(struct _cairo_tor22_scan_converter)); + self = _cairo_malloc (sizeof(struct _cairo_tor22_scan_converter)); if (unlikely (self == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto bail_nomem; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-toy-font-face.c b/Build/source/libs/cairo/cairo-src/src/cairo-toy-font-face.c index 516f391953f..3d2217daef8 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-toy-font-face.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-toy-font-face.c @@ -312,7 +312,7 @@ cairo_toy_font_face_create (const char *family, } /* Otherwise create it and insert into hash table. */ - font_face = malloc (sizeof (cairo_toy_font_face_t)); + font_face = _cairo_malloc (sizeof (cairo_toy_font_face_t)); if (unlikely (font_face == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto UNWIND_HASH_TABLE_LOCK; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-traps.c b/Build/source/libs/cairo/cairo-src/src/cairo-traps.c index 3aa0052f91f..1b748484338 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-traps.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-traps.c @@ -113,7 +113,7 @@ _cairo_traps_fini (cairo_traps_t *traps) if (traps->traps != traps->traps_embedded) free (traps->traps); - VG (VALGRIND_MAKE_MEM_NOACCESS (traps, sizeof (cairo_traps_t))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (traps, sizeof (cairo_traps_t))); } /* make room for at least one more trap */ diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-tristrip.c b/Build/source/libs/cairo/cairo-src/src/cairo-tristrip.c index bb4972f5003..bcf3b237167 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-tristrip.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-tristrip.c @@ -58,7 +58,7 @@ _cairo_tristrip_fini (cairo_tristrip_t *strip) if (strip->points != strip->points_embedded) free (strip->points); - VG (VALGRIND_MAKE_MEM_NOACCESS (strip, sizeof (cairo_tristrip_t))); + VG (VALGRIND_MAKE_MEM_UNDEFINED (strip, sizeof (cairo_tristrip_t))); } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-truetype-subset.c b/Build/source/libs/cairo/cairo-src/src/cairo-truetype-subset.c index b650ebe8678..6cef4ee423c 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-truetype-subset.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-truetype-subset.c @@ -77,22 +77,22 @@ struct _cairo_truetype_font { struct { char *font_name; char *ps_name; - unsigned int num_glyphs; - int *widths; + int num_glyphs_in_face; /* glyphs in font */ long x_min, y_min, x_max, y_max; long ascent, descent; int units_per_em; } base; - subset_glyph_t *glyphs; + subset_glyph_t *glyphs; /* array size: num_glyphs_in_face + 2 */ const cairo_scaled_font_backend_t *backend; - int num_glyphs_in_face; + unsigned int num_glyphs; /* glyphs used */ + int *widths; /* array size: num_glyphs_in_face + 1 */ int checksum_index; cairo_array_t output; cairo_array_t string_offsets; unsigned long last_offset; unsigned long last_boundary; - int *parent_to_subset; + int *parent_to_subset; /* array size: num_glyphs_in_face + 1 */ cairo_status_t status; cairo_bool_t is_pdf; }; @@ -107,7 +107,6 @@ check (tt_hhea_t, 36); check (tt_maxp_t, 32); check (tt_name_record_t, 12); check (tt_name_t, 18); -check (tt_name_t, 18); check (tt_composite_glyph_t, 16); check (tt_glyph_data_t, 26); #undef check @@ -139,6 +138,7 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, cairo_truetype_font_t **font_return) { cairo_status_t status; + cairo_bool_t is_synthetic; cairo_truetype_font_t *font; const cairo_scaled_font_backend_t *backend; tt_head_t head; @@ -159,9 +159,15 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, * return CAIRO_INT_STATUS_UNSUPPORTED; */ - /* We need to use a fallback font generated from the synthesized outlines. */ - if (backend->is_synthetic && backend->is_synthetic (scaled_font_subset->scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; + /* We need to use a fallback font if this font differs from the glyf outlines. */ + if (backend->is_synthetic) { + status = backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic); + if (unlikely (status)) + return status; + + if (is_synthetic) + return CAIRO_INT_STATUS_UNSUPPORTED; + } size = sizeof (tt_head_t); status = backend->load_truetype_table (scaled_font_subset->scaled_font, @@ -187,12 +193,12 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, if (unlikely (status)) return status; - font = malloc (sizeof (cairo_truetype_font_t)); + font = _cairo_malloc (sizeof (cairo_truetype_font_t)); if (unlikely (font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); font->backend = backend; - font->num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs); + font->base.num_glyphs_in_face = be16_to_cpu (maxp.num_glyphs); font->scaled_font_subset = scaled_font_subset; font->last_offset = 0; @@ -205,21 +211,21 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, /* Add 2: +1 case font does not contain .notdef, and +1 because an extra * entry is required to contain the end location of the last glyph. */ - font->glyphs = calloc (font->num_glyphs_in_face + 2, sizeof (subset_glyph_t)); + font->glyphs = calloc (font->base.num_glyphs_in_face + 2, sizeof (subset_glyph_t)); if (unlikely (font->glyphs == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail1; } /* Add 1 in case font does not contain .notdef */ - font->parent_to_subset = calloc (font->num_glyphs_in_face + 1, sizeof (int)); + font->parent_to_subset = calloc (font->base.num_glyphs_in_face + 1, sizeof (int)); if (unlikely (font->parent_to_subset == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail2; } font->is_pdf = is_pdf; - font->base.num_glyphs = 0; + font->num_glyphs = 0; font->base.x_min = (int16_t) be16_to_cpu (head.x_min); font->base.y_min = (int16_t) be16_to_cpu (head.y_min); font->base.x_max = (int16_t) be16_to_cpu (head.x_max); @@ -240,7 +246,7 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, /* If the PS name is not found, create a CairoFont-x-y name. */ if (font->base.ps_name == NULL) { - font->base.ps_name = malloc (30); + font->base.ps_name = _cairo_malloc (30); if (unlikely (font->base.ps_name == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail3; @@ -252,8 +258,8 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, } /* Add 1 in case font does not contain .notdef */ - font->base.widths = calloc (font->num_glyphs_in_face + 1, sizeof (int)); - if (unlikely (font->base.widths == NULL)) { + font->widths = calloc (font->base.num_glyphs_in_face + 1, sizeof (int)); + if (unlikely (font->widths == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail4; } @@ -271,7 +277,7 @@ _cairo_truetype_font_create (cairo_scaled_font_subset_t *scaled_font_subset, fail5: _cairo_array_fini (&font->string_offsets); - free (font->base.widths); + free (font->widths); fail4: free (font->base.ps_name); fail3: @@ -290,7 +296,7 @@ static void cairo_truetype_font_destroy (cairo_truetype_font_t *font) { _cairo_array_fini (&font->string_offsets); - free (font->base.widths); + free (font->widths); free (font->base.ps_name); free (font->base.font_name); free (font->parent_to_subset); @@ -612,11 +618,11 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font, return _cairo_truetype_font_set_error (font, status); if (be16_to_cpu (header.index_to_loc_format) == 0) - size = sizeof (int16_t) * (font->num_glyphs_in_face + 1); + size = sizeof (int16_t) * (font->base.num_glyphs_in_face + 1); else - size = sizeof (int32_t) * (font->num_glyphs_in_face + 1); + size = sizeof (int32_t) * (font->base.num_glyphs_in_face + 1); - u.bytes = malloc (size); + u.bytes = _cairo_malloc (size); if (unlikely (u.bytes == NULL)) return _cairo_truetype_font_set_error (font, CAIRO_STATUS_NO_MEMORY); @@ -626,7 +632,7 @@ cairo_truetype_font_write_glyf_table (cairo_truetype_font_t *font, return _cairo_truetype_font_set_error (font, status); start_offset = _cairo_array_num_elements (&font->output); - for (i = 0; i < font->base.num_glyphs; i++) { + for (i = 0; i < font->num_glyphs; i++) { index = font->glyphs[i].parent_index; if (be16_to_cpu (header.index_to_loc_format) == 0) { begin = be16_to_cpu (u.short_offsets[index]) * 2; @@ -754,7 +760,7 @@ cairo_truetype_font_write_hhea_table (cairo_truetype_font_t *font, unsigned long if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); - hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->base.num_glyphs)); + hhea->num_hmetrics = cpu_to_be16 ((uint16_t)(font->num_glyphs)); return CAIRO_STATUS_SUCCESS; } @@ -784,7 +790,7 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font, num_hmetrics = be16_to_cpu(hhea.num_hmetrics); - for (i = 0; i < font->base.num_glyphs; i++) { + for (i = 0; i < font->num_glyphs; i++) { long_entry_size = 2 * sizeof (int16_t); short_entry_size = sizeof (int16_t); status = cairo_truetype_font_allocate_write_buffer (font, @@ -818,7 +824,7 @@ cairo_truetype_font_write_hmtx_table (cairo_truetype_font_t *font, if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); } - font->base.widths[i] = be16_to_cpu (p[0]); + font->widths[i] = be16_to_cpu (p[0]); } return CAIRO_STATUS_SUCCESS; @@ -845,10 +851,10 @@ cairo_truetype_font_write_loca_table (cairo_truetype_font_t *font, if (be16_to_cpu (header.index_to_loc_format) == 0) { - for (i = 0; i < font->base.num_glyphs + 1; i++) + for (i = 0; i < font->num_glyphs + 1; i++) cairo_truetype_font_write_be16 (font, font->glyphs[i].location / 2); } else { - for (i = 0; i < font->base.num_glyphs + 1; i++) + for (i = 0; i < font->num_glyphs + 1; i++) cairo_truetype_font_write_be32 (font, font->glyphs[i].location); } @@ -876,7 +882,7 @@ cairo_truetype_font_write_maxp_table (cairo_truetype_font_t *font, if (unlikely (status)) return _cairo_truetype_font_set_error (font, status); - maxp->num_glyphs = cpu_to_be16 (font->base.num_glyphs); + maxp->num_glyphs = cpu_to_be16 (font->num_glyphs); return CAIRO_STATUS_SUCCESS; } @@ -1020,13 +1026,13 @@ cairo_truetype_font_use_glyph (cairo_truetype_font_t *font, unsigned short glyph, unsigned short *out) { - if (glyph >= font->num_glyphs_in_face) + if (glyph >= font->base.num_glyphs_in_face) return CAIRO_INT_STATUS_UNSUPPORTED; if (font->parent_to_subset[glyph] == 0) { - font->parent_to_subset[glyph] = font->base.num_glyphs; - font->glyphs[font->base.num_glyphs].parent_index = glyph; - font->base.num_glyphs++; + font->parent_to_subset[glyph] = font->num_glyphs; + font->glyphs[font->num_glyphs].parent_index = glyph; + font->num_glyphs++; } *out = font->parent_to_subset[glyph]; @@ -1179,7 +1185,7 @@ cairo_truetype_subset_init_internal (cairo_truetype_subset_t *truetype_subse goto fail3; } for (i = 0; i < font->scaled_font_subset->num_glyphs; i++) - truetype_subset->widths[i] = (double)font->base.widths[i]/font->base.units_per_em; + truetype_subset->widths[i] = (double)font->widths[i]/font->base.units_per_em; truetype_subset->x_min = (double)font->base.x_min/font->base.units_per_em; truetype_subset->y_min = (double)font->base.y_min/font->base.units_per_em; @@ -1189,7 +1195,7 @@ cairo_truetype_subset_init_internal (cairo_truetype_subset_t *truetype_subse truetype_subset->descent = (double)font->base.descent/font->base.units_per_em; if (length) { - truetype_subset->data = malloc (length); + truetype_subset->data = _cairo_malloc (length); if (unlikely (truetype_subset->data == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail4; @@ -1202,7 +1208,7 @@ cairo_truetype_subset_init_internal (cairo_truetype_subset_t *truetype_subse if (num_strings) { offsets_length = num_strings * sizeof (unsigned long); - truetype_subset->string_offsets = malloc (offsets_length); + truetype_subset->string_offsets = _cairo_malloc (offsets_length); if (unlikely (truetype_subset->string_offsets == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail5; @@ -1290,7 +1296,7 @@ _cairo_truetype_reverse_cmap (cairo_scaled_font_t *scaled_font, return CAIRO_INT_STATUS_UNSUPPORTED; size = be16_to_cpu (map->length); - map = malloc (size); + map = _cairo_malloc (size); if (unlikely (map == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1456,7 +1462,7 @@ find_name (tt_name_t *name, int name_id, int platform, int encoding, int languag if (len > MAX_FONT_NAME_LENGTH) break; - str = malloc (len + 1); + str = _cairo_malloc (len + 1); if (str == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1482,7 +1488,7 @@ find_name (tt_name_t *name, int name_id, int platform, int encoding, int languag for (i = 0; i < u_len; i++) size += _cairo_ucs4_to_utf8 (be16_to_cpu(u[i]), NULL); - utf8 = malloc (size + 1); + utf8 = _cairo_malloc (size + 1); if (utf8 == NULL) { status =_cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail; @@ -1517,7 +1523,7 @@ find_name (tt_name_t *name, int name_id, int platform, int encoding, int languag } } if (has_tag) { - p = malloc (len - 6); + p = _cairo_malloc (len - 6); if (unlikely (p == NULL)) { status =_cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail; @@ -1562,7 +1568,7 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font, if (status) return status; - name = malloc (size); + name = _cairo_malloc (size); if (name == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-type1-fallback.c b/Build/source/libs/cairo/cairo-src/src/cairo-type1-fallback.c index c8e7e908bb6..0b8e66cd0b9 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-type1-fallback.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-type1-fallback.c @@ -760,7 +760,7 @@ _cairo_type1_fallback_init_internal (cairo_type1_subset_t *type1_subset, length = font->header_size + font->data_size + font->trailer_size; - type1_subset->data = malloc (length); + type1_subset->data = _cairo_malloc (length); if (unlikely (type1_subset->data == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto fail3; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-type1-subset.c b/Build/source/libs/cairo/cairo-src/src/cairo-type1-subset.c index feac2836f00..5f07456888b 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-type1-subset.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-type1-subset.c @@ -311,7 +311,7 @@ cairo_type1_font_subset_get_matrix (cairo_type1_font_subset_t *font, const char *decimal_point; int decimal_point_len; - decimal_point = cairo_get_locale_decimal_point (); + decimal_point = _cairo_get_locale_decimal_point (); decimal_point_len = strlen (decimal_point); assert (decimal_point_len != 0); @@ -326,7 +326,7 @@ cairo_type1_font_subset_get_matrix (cairo_type1_font_subset_t *font, return CAIRO_INT_STATUS_UNSUPPORTED; s_max = end - start + 5*decimal_point_len + 1; - s = malloc (s_max); + s = _cairo_malloc (s_max); if (unlikely (s == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -420,7 +420,7 @@ cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font) while (end > start && _cairo_isspace(end[-1])) end--; - s = malloc (end - start + 1); + s = _cairo_malloc (end - start + 1); if (unlikely (s == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -624,7 +624,7 @@ cairo_type1_font_subset_decrypt_eexec_segment (cairo_type1_font_subset_t *font) in = (unsigned char *) font->eexec_segment; end = (unsigned char *) in + font->eexec_segment_size; - font->cleartext = malloc (font->eexec_segment_size + 1); + font->cleartext = _cairo_malloc (font->eexec_segment_size + 1); if (unlikely (font->cleartext == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -783,7 +783,7 @@ cairo_type1_font_subset_parse_charstring (cairo_type1_font_subset_t *font, const unsigned char *p; int command; - charstring = malloc (encrypted_charstring_length); + charstring = _cairo_malloc (encrypted_charstring_length); if (unlikely (charstring == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1096,7 +1096,7 @@ cairo_type1_font_subset_build_glyph_list (cairo_type1_font_subset_t *font, glyph_data_t glyph; cairo_status_t status; - s = malloc (name_length + 1); + s = _cairo_malloc (name_length + 1); if (unlikely (s == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1285,7 +1285,7 @@ cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font, if (lenIV_end == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; - lenIV_str = malloc (lenIV_end - lenIV_start + 1); + lenIV_str = _cairo_malloc (lenIV_end - lenIV_start + 1); if (unlikely (lenIV_str == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1331,7 +1331,7 @@ cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font, /* look for "dup" which marks the beginning of the first subr */ array_start = find_token (subr_count_end, font->cleartext_end, "dup"); - if (subrs == NULL) + if (array_start == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; /* Read in the subroutines */ @@ -1642,7 +1642,7 @@ cairo_type1_font_subset_generate (void *abstract_font, return CAIRO_INT_STATUS_UNSUPPORTED; font->type1_length = data_length; - font->type1_data = malloc (font->type1_length); + font->type1_data = _cairo_malloc (font->type1_length); if (unlikely (font->type1_data == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1715,14 +1715,20 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, { cairo_type1_font_subset_t font; cairo_status_t status; + cairo_bool_t is_synthetic; unsigned long length; unsigned int i; char buf[30]; - /* We need to use a fallback font generated from the synthesized outlines. */ - if (scaled_font_subset->scaled_font->backend->is_synthetic && - scaled_font_subset->scaled_font->backend->is_synthetic (scaled_font_subset->scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; + /* We need to use a fallback font if this font differs from the type1 outlines. */ + if (scaled_font_subset->scaled_font->backend->is_synthetic) { + status = scaled_font_subset->scaled_font->backend->is_synthetic (scaled_font_subset->scaled_font, &is_synthetic); + if (unlikely (status)) + return status; + + if (is_synthetic) + return CAIRO_INT_STATUS_UNSUPPORTED; + } status = _cairo_type1_font_subset_init (&font, scaled_font_subset, hex_encode); if (unlikely (status)) @@ -1762,7 +1768,7 @@ _cairo_type1_subset_init (cairo_type1_subset_t *type1_subset, length = font.base.header_size + font.base.data_size + font.base.trailer_size; - type1_subset->data = malloc (length); + type1_subset->data = _cairo_malloc (length); if (unlikely (type1_subset->data == NULL)) goto fail3; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-type3-glyph-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-type3-glyph-surface.c index c99d461066c..6b21023190c 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-type3-glyph-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-type3-glyph-surface.c @@ -78,19 +78,19 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font, cairo_bool_t ps) { cairo_type3_glyph_surface_t *surface; - cairo_matrix_t invert_y_axis; if (unlikely (stream != NULL && stream->status)) return _cairo_surface_create_in_error (stream->status); - surface = malloc (sizeof (cairo_type3_glyph_surface_t)); + surface = _cairo_malloc (sizeof (cairo_type3_glyph_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &cairo_type3_glyph_surface_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + TRUE); /* is_vector */ surface->scaled_font = scaled_font; surface->stream = stream; @@ -101,8 +101,6 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font, * entry in the Type 3 dictionary. In the PDF backend this is an * identity matrix. */ surface->cairo_to_pdf = scaled_font->scale_inverse; - cairo_matrix_init_scale (&invert_y_axis, 1, -1); - cairo_matrix_multiply (&surface->cairo_to_pdf, &surface->cairo_to_pdf, &invert_y_axis); _cairo_pdf_operators_init (&surface->pdf_operators, surface->stream, @@ -294,15 +292,13 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface, cairo_type3_glyph_surface_t *surface = abstract_surface; cairo_int_status_t status; cairo_scaled_font_t *font; - cairo_matrix_t new_ctm, invert_y_axis; + cairo_matrix_t new_ctm; status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); if (unlikely (status)) return status; - cairo_matrix_init_scale (&invert_y_axis, 1, -1); - cairo_matrix_multiply (&new_ctm, &invert_y_axis, &scaled_font->ctm); - cairo_matrix_multiply (&new_ctm, &surface->cairo_to_pdf, &new_ctm); + cairo_matrix_multiply (&new_ctm, &surface->cairo_to_pdf, &scaled_font->ctm); font = cairo_scaled_font_create (scaled_font->font_face, &scaled_font->font_matrix, &new_ctm, @@ -387,14 +383,10 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x); y = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y); - mat.xx = image->width; - mat.xy = 0; - mat.yx = 0; - mat.yy = image->height; - mat.x0 = x; - mat.y0 = y; + cairo_matrix_init(&mat, image->width, 0, + 0, -image->height, + x, y); cairo_matrix_multiply (&mat, &mat, &surface->scaled_font->scale_inverse); - mat.y0 *= -1; return _cairo_type3_glyph_surface_emit_image (surface, image, &mat); } @@ -523,9 +515,9 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface, "%f 0 %f %f %f %f d1\n", x_advance, _cairo_fixed_to_double (bbox->p1.x), - - _cairo_fixed_to_double (bbox->p2.y), + _cairo_fixed_to_double (bbox->p1.y), _cairo_fixed_to_double (bbox->p2.x), - - _cairo_fixed_to_double (bbox->p1.y)); + _cairo_fixed_to_double (bbox->p2.y)); if (status == CAIRO_INT_STATUS_SUCCESS) { cairo_output_stream_t *mem_stream; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-types-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-types-private.h index 3d15d968e4b..da373030c26 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-types-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-types-private.h @@ -194,6 +194,7 @@ struct _cairo_font_options { cairo_hint_style_t hint_style; cairo_hint_metrics_t hint_metrics; cairo_round_glyph_positions_t round_glyph_positions; + char *variations; }; struct _cairo_glyph_text_info { diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-unicode.c b/Build/source/libs/cairo/cairo-src/src/cairo-unicode.c index 88de39516b6..966ae84b59b 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-unicode.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-unicode.c @@ -342,6 +342,36 @@ _cairo_ucs4_to_utf8 (uint32_t unicode, return bytes; } +/** + * _cairo_ucs4_to_utf16: + * @unicode: a UCS-4 character + * @utf16: buffer to write utf16 string into. Must have at least 2 + * elements. Or %NULL. + * + * This space left intentionally blank. + * + * Return value: Number of elements in the utf16 string or 0 if an + * invalid unicode character + **/ +int +_cairo_ucs4_to_utf16 (uint32_t unicode, + uint16_t *utf16) +{ + if (unicode < 0x10000) { + if (utf16) + utf16[0] = unicode; + return 1; + } else if (unicode < 0x110000) { + if (utf16) { + utf16[0] = (unicode - 0x10000) / 0x400 + 0xd800; + utf16[1] = (unicode - 0x10000) % 0x400 + 0xdc00; + } + return 2; + } else { + return 0; + } +} + #if CAIRO_HAS_UTF8_TO_UTF16 /** * _cairo_utf8_to_utf16: @@ -401,12 +431,7 @@ _cairo_utf8_to_utf16 (const char *str, for (i = 0; i < n16;) { uint32_t wc = _utf8_get_char (in); - if (wc < 0x10000) { - str16[i++] = wc; - } else { - str16[i++] = (wc - 0x10000) / 0x400 + 0xd800; - str16[i++] = (wc - 0x10000) % 0x400 + 0xdc00; - } + i += _cairo_ucs4_to_utf16 (wc, str16 + i); in = UTF8_NEXT_CHAR (in); } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-user-font.c b/Build/source/libs/cairo/cairo-src/src/cairo-user-font.c index 6d2de2097d5..a26fb57ee10 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-user-font.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-user-font.c @@ -402,7 +402,7 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ font_face->immutable = TRUE; - user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t)); + user_scaled_font = _cairo_malloc (sizeof (cairo_user_scaled_font_t)); if (unlikely (user_scaled_font == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -544,7 +544,7 @@ cairo_user_font_face_create (void) { cairo_user_font_face_t *font_face; - font_face = malloc (sizeof (cairo_user_font_face_t)); + font_face = _cairo_malloc (sizeof (cairo_user_font_face_t)); if (!font_face) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return (cairo_font_face_t *)&_cairo_font_face_nil; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-version.c b/Build/source/libs/cairo/cairo-src/src/cairo-version.c index a94cef6819d..65ae2b108e2 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-version.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-version.c @@ -115,8 +115,8 @@ * * Compile-time * ------------ - * CAIRO_VERSION_STRING Human-readable - * CAIRO_VERSION Encoded, suitable for comparison + * #CAIRO_VERSION_STRING Human-readable + * #CAIRO_VERSION Encoded, suitable for comparison *   * Run-time * -------- diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-vg-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-vg-surface.c index 6e0d9a0ed69..77986331aa3 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-vg-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-vg-surface.c @@ -1517,7 +1517,7 @@ _vg_surface_create_internal (cairo_vg_context_t *context, { cairo_vg_surface_t *surface; - surface = malloc (sizeof (cairo_vg_surface_t)); + surface = _cairo_malloc (sizeof (cairo_vg_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1529,7 +1529,8 @@ _vg_surface_create_internal (cairo_vg_context_t *context, _cairo_surface_init (&surface->base, &cairo_vg_surface_backend, NULL, /* device */ - _vg_format_to_content (format)); + _vg_format_to_content (format), + FALSE); /* is_vector */ surface->width = width; surface->height = height; @@ -1711,7 +1712,7 @@ cairo_vg_context_create_for_glx (Display *dpy, GLXContext ctx) cairo_vg_context_t *context; cairo_status_t status; - context = malloc (sizeof (*context)); + context = _cairo_malloc (sizeof (*context)); if (unlikely (context == NULL)) return (cairo_vg_context_t *) &_vg_context_nil; @@ -1816,7 +1817,7 @@ cairo_vg_context_create_for_egl (EGLDisplay egl_display, cairo_vg_context_t *context; cairo_status_t status; - context = malloc (sizeof (*context)); + context = _cairo_malloc (sizeof (*context)); if (unlikely (context == NULL)) return (cairo_vg_context_t *) &_vg_context_nil; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-vg.h b/Build/source/libs/cairo/cairo-src/src/cairo-vg.h index f9a62e51c69..a2701db3bd4 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-vg.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-vg.h @@ -1,8 +1,8 @@ /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * - * Copyright © 2007 * Mozilla Corporation - * Copyright © 2009 Chris Wilson + * Copyright © 2007 * Mozilla Corporation + * Copyright © 2009 Chris Wilson * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-win32.h b/Build/source/libs/cairo/cairo-src/src/cairo-win32.h index 3d2e1c60169..db4cac69f49 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-win32.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-win32.h @@ -48,6 +48,10 @@ CAIRO_BEGIN_DECLS cairo_public cairo_surface_t * cairo_win32_surface_create (HDC hdc); +cairo_public cairo_surface_t * +cairo_win32_surface_create_with_format (HDC hdc, + cairo_format_t format); + cairo_public cairo_surface_t * cairo_win32_printing_surface_create (HDC hdc); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-connection.c b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-connection.c index 67897fa4ecc..51f5ee323cd 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-connection.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-connection.c @@ -111,7 +111,7 @@ _cairo_xcb_connection_find_visual_formats (cairo_xcb_connection_t *connection, cairo_xcb_xrender_format_t *f; cairo_status_t status; - f = malloc (sizeof (cairo_xcb_xrender_format_t)); + f = _cairo_malloc (sizeof (cairo_xcb_xrender_format_t)); if (unlikely (f == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -177,7 +177,7 @@ _cairo_xcb_connection_parse_xrender_formats (cairo_xcb_connection_t *connection, if (! _cairo_hash_table_lookup (connection->xrender_formats, &key)) { cairo_xcb_xrender_format_t *f; - f = malloc (sizeof (cairo_xcb_xrender_format_t)); + f = _cairo_malloc (sizeof (cairo_xcb_xrender_format_t)); if (unlikely (f == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -634,7 +634,7 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection) } } - connection = malloc (sizeof (cairo_xcb_connection_t)); + connection = _cairo_malloc (sizeof (cairo_xcb_connection_t)); if (unlikely (connection == NULL)) goto unlock; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-screen.c b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-screen.c index d0019f9cdff..0d23ad3c3d9 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-screen.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-screen.c @@ -249,7 +249,7 @@ _cairo_xcb_screen_get (xcb_connection_t *xcb_connection, } } - screen = malloc (sizeof (cairo_xcb_screen_t)); + screen = _cairo_malloc (sizeof (cairo_xcb_screen_t)); if (unlikely (screen == NULL)) goto unlock; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-shm.c b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-shm.c index 2be2dac5bf9..763778ab2c4 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-shm.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-shm.c @@ -209,7 +209,7 @@ _cairo_xcb_connection_allocate_shm_info (cairo_xcb_connection_t *connection, return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - pool = malloc (sizeof (cairo_xcb_shm_mem_pool_t)); + pool = _cairo_malloc (sizeof (cairo_xcb_shm_mem_pool_t)); if (unlikely (pool == NULL)) { CAIRO_MUTEX_UNLOCK (connection->shm_mutex); return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface-core.c b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface-core.c index 9c0c0a0957d..91c0ff995e4 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface-core.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface-core.c @@ -85,7 +85,7 @@ _cairo_xcb_pixmap_create (cairo_xcb_surface_t *target, { cairo_xcb_pixmap_t *surface; - surface = malloc (sizeof (cairo_xcb_pixmap_t)); + surface = _cairo_malloc (sizeof (cairo_xcb_pixmap_t)); if (unlikely (surface == NULL)) return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -93,7 +93,8 @@ _cairo_xcb_pixmap_create (cairo_xcb_surface_t *target, _cairo_surface_init (&surface->base, &_cairo_xcb_pixmap_backend, NULL, - target->base.content); + target->base.content, + FALSE); /* is_vector */ surface->connection = target->connection; surface->screen = target->screen; @@ -118,7 +119,7 @@ _cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target) { cairo_xcb_pixmap_t *surface; - surface = malloc (sizeof (cairo_xcb_pixmap_t)); + surface = _cairo_malloc (sizeof (cairo_xcb_pixmap_t)); if (unlikely (surface == NULL)) return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -126,7 +127,8 @@ _cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target) _cairo_surface_init (&surface->base, &_cairo_xcb_pixmap_backend, NULL, - target->base.content); + target->base.content, + FALSE); /* is_vector */ surface->connection = target->connection; surface->screen = target->screen; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface-render.c b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface-render.c index 139dcda827a..42f27c71fe2 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface-render.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface-render.c @@ -114,7 +114,7 @@ _cairo_xcb_picture_create (cairo_xcb_screen_t *screen, { cairo_xcb_picture_t *surface; - surface = malloc (sizeof (cairo_xcb_picture_t)); + surface = _cairo_malloc (sizeof (cairo_xcb_picture_t)); if (unlikely (surface == NULL)) return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -122,7 +122,8 @@ _cairo_xcb_picture_create (cairo_xcb_screen_t *screen, _cairo_surface_init (&surface->base, &_cairo_xcb_picture_backend, &screen->connection->device, - _cairo_content_from_pixman_format (pixman_format)); + _cairo_content_from_pixman_format (pixman_format), + FALSE); /* is_vector */ cairo_list_add (&surface->link, &screen->pictures); @@ -4140,7 +4141,7 @@ _cairo_xcb_font_create (cairo_xcb_connection_t *connection, cairo_xcb_font_t *priv; int i; - priv = malloc (sizeof (cairo_xcb_font_t)); + priv = _cairo_malloc (sizeof (cairo_xcb_font_t)); if (unlikely (priv == NULL)) return NULL; @@ -4333,7 +4334,7 @@ _cairo_xcb_glyph_fini (cairo_scaled_glyph_private_t *glyph_private, } if (to_free == NULL) { - to_free = malloc (sizeof (cairo_xcb_font_glyphset_free_glyphs_t)); + to_free = _cairo_malloc (sizeof (cairo_xcb_font_glyphset_free_glyphs_t)); if (unlikely (to_free == NULL)) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); return; /* XXX cannot propagate failure */ @@ -4360,7 +4361,7 @@ _cairo_xcb_glyph_attach (cairo_xcb_connection_t *c, { cairo_xcb_glyph_private_t *priv; - priv = malloc (sizeof (*priv)); + priv = _cairo_malloc (sizeof (*priv)); if (unlikely (priv == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -4471,7 +4472,7 @@ _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection, if (c == 0) break; - new = malloc (c); + new = _cairo_malloc (c); if (unlikely (new == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL; @@ -4502,7 +4503,7 @@ _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection, if (c == 0) break; - new = malloc (4 * c); + new = _cairo_malloc (4 * c); if (unlikely (new == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL; @@ -4584,7 +4585,7 @@ _emit_glyphs_chunk (cairo_xcb_surface_t *dst, int i; if (estimated_req_size > ARRAY_LENGTH (stack_buf)) { - buf = malloc (estimated_req_size); + buf = _cairo_malloc (estimated_req_size); if (unlikely (buf == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface.c index df49e8269b9..7f601bb71c1 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xcb-surface.c @@ -1075,14 +1075,15 @@ _cairo_xcb_surface_create_internal (cairo_xcb_screen_t *screen, { cairo_xcb_surface_t *surface; - surface = malloc (sizeof (cairo_xcb_surface_t)); + surface = _cairo_malloc (sizeof (cairo_xcb_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &_cairo_xcb_surface_backend, &screen->connection->device, - _cairo_content_from_pixman_format (pixman_format)); + _cairo_content_from_pixman_format (pixman_format), + FALSE); /* is_vector */ surface->connection = _cairo_xcb_connection_reference (screen->connection); surface->screen = screen; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-core-compositor.c b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-core-compositor.c index 5babcc81bed..1392999617f 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-core-compositor.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-core-compositor.c @@ -632,9 +632,10 @@ _cairo_xlib_core_compositor_fill (const cairo_compositor_t *compositor, const cairo_compositor_t * _cairo_xlib_core_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_compositor_t compositor; - if (compositor.delegate == NULL) { + if (_cairo_atomic_init_once_enter(&once)) { compositor.delegate = _cairo_xlib_fallback_compositor_get (); compositor.paint = _cairo_xlib_core_compositor_paint; @@ -642,6 +643,8 @@ _cairo_xlib_core_compositor_get (void) compositor.fill = _cairo_xlib_core_compositor_fill; compositor.stroke = _cairo_xlib_core_compositor_stroke; compositor.glyphs = NULL; /* XXX PolyGlyph? */ + + _cairo_atomic_init_once_leave(&once); } return &compositor; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-display.c b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-display.c index a2a3bc7924b..add42299b4c 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-display.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-display.c @@ -207,7 +207,7 @@ _cairo_xlib_device_create (Display *dpy) } } - display = malloc (sizeof (cairo_xlib_display_t)); + display = _cairo_malloc (sizeof (cairo_xlib_display_t)); if (unlikely (display == NULL)) { device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); goto UNLOCK; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-private.h b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-private.h index 0f2f2e1faa0..71dccc3a725 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-private.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-private.h @@ -104,7 +104,7 @@ struct _cairo_xlib_display { * We also use this variable as a guard against a second * independent bug with transformed repeating pictures: * - * http://lists.freedesktop.org/archives/cairo/2004-September/001839.html + * https://lists.freedesktop.org/archives/cairo/2004-September/001839.html * * Both are fixed in xorg >= 6.9 and hopefully in > 6.8.2, so * we can reuse the test for now. diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-render-compositor.c b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-render-compositor.c index 8a1ec7bd731..0db59a8a6f5 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-render-compositor.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-render-compositor.c @@ -965,7 +965,7 @@ _cairo_xlib_font_fini (cairo_scaled_font_private_t *abstract_private, cairo_list_del (&priv->link); status = _cairo_xlib_display_acquire (priv->device, &display); - if (status) + if (unlikely (status)) /* this should be impossible but leak just in case */ goto BAIL; for (i = 0; i < NUM_GLYPHSETS; i++) { @@ -978,7 +978,7 @@ _cairo_xlib_font_fini (cairo_scaled_font_private_t *abstract_private, cairo_device_release (&display->base); BAIL: - cairo_device_destroy (&display->base); + cairo_device_destroy (priv->device); free (priv); } @@ -989,7 +989,7 @@ _cairo_xlib_font_create (cairo_xlib_display_t *display, cairo_xlib_font_t *priv; int i; - priv = malloc (sizeof (cairo_xlib_font_t)); + priv = _cairo_malloc (sizeof (cairo_xlib_font_t)); if (unlikely (priv == NULL)) return NULL; @@ -1089,7 +1089,7 @@ _cairo_xlib_glyph_attach (cairo_xlib_display_t *display, { cairo_xlib_glyph_private_t *priv; - priv = malloc (sizeof (*priv)); + priv = _cairo_malloc (sizeof (*priv)); if (unlikely (priv == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1290,7 +1290,7 @@ _cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display, if (c == 0) break; - new = malloc (c); + new = _cairo_malloc (c); if (!new) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL; @@ -1318,7 +1318,7 @@ _cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display, if (c == 0) break; - new = malloc (4 * c); + new = _cairo_malloc (4 * c); if (unlikely (new == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL; @@ -1725,9 +1725,10 @@ composite_glyphs (void *surface, const cairo_compositor_t * _cairo_xlib_mask_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_mask_compositor_t compositor; - if (compositor.base.delegate == NULL) { + if (_cairo_atomic_init_once_enter(&once)) { _cairo_mask_compositor_init (&compositor, _cairo_xlib_fallback_compositor_get ()); @@ -1745,6 +1746,8 @@ _cairo_xlib_mask_compositor_get (void) compositor.composite_boxes = composite_boxes; compositor.check_composite_glyphs = check_composite_glyphs; compositor.composite_glyphs = composite_glyphs; + + _cairo_atomic_init_once_leave(&once); } return &compositor.base; @@ -1827,6 +1830,9 @@ composite_traps (void *abstract_dst, //X_DEBUG ((display->display, "composite_trapezoids (dst=%x)", (unsigned int) dst->drawable)); + if (traps->num_traps == 0) + return CAIRO_STATUS_SUCCESS; + if (dst->base.is_clear && (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)) { @@ -1973,9 +1979,10 @@ composite_tristrip (void *abstract_dst, const cairo_compositor_t * _cairo_xlib_traps_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_traps_compositor_t compositor; - if (compositor.base.delegate == NULL) { + if (_cairo_atomic_init_once_enter(&once)) { _cairo_traps_compositor_init (&compositor, _cairo_xlib_mask_compositor_get ()); @@ -1997,6 +2004,8 @@ _cairo_xlib_traps_compositor_get (void) compositor.composite_tristrip = composite_tristrip; compositor.check_composite_glyphs = check_composite_glyphs; compositor.composite_glyphs = composite_glyphs; + + _cairo_atomic_init_once_leave(&once); } return &compositor.base; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-screen.c b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-screen.c index 57beeaab426..ff3bdfcf9e1 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-screen.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-screen.c @@ -330,7 +330,7 @@ _cairo_xlib_screen_get (Display *dpy, goto CLEANUP_DISPLAY; } - info = malloc (sizeof (cairo_xlib_screen_t)); + info = _cairo_malloc (sizeof (cairo_xlib_screen_t)); if (unlikely (info == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto CLEANUP_DISPLAY; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-source.c b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-source.c index 1591f5874f6..6269edca53e 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-source.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-source.c @@ -109,7 +109,7 @@ source (cairo_xlib_surface_t *dst, Picture picture, Pixmap pixmap) if (picture == None) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - source = malloc (sizeof (*source)); + source = _cairo_malloc (sizeof (*source)); if (unlikely (source == NULL)) { XRenderFreePicture (dst->display->display, picture); if (pixmap) @@ -120,7 +120,8 @@ source (cairo_xlib_surface_t *dst, Picture picture, Pixmap pixmap) _cairo_surface_init (&source->base, &cairo_xlib_source_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + FALSE); /* is_vector */ /* The source exists only within an operation */ source->picture = picture; @@ -626,7 +627,8 @@ static cairo_xlib_source_t *init_source (cairo_xlib_surface_t *dst, _cairo_surface_init (&source->base, &cairo_xlib_source_backend, NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA); + CAIRO_CONTENT_COLOR_ALPHA, + FALSE); /* is_vector */ pa.subwindow_mode = IncludeInferiors; source->picture = XRenderCreatePicture (dpy, @@ -964,14 +966,15 @@ surface_source (cairo_xlib_surface_t *dst, _cairo_xlib_shm_surface_get_pixmap (src)) { cairo_xlib_proxy_t *proxy; - proxy = malloc (sizeof(*proxy)); + proxy = _cairo_malloc (sizeof(*proxy)); if (unlikely (proxy == NULL)) return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); _cairo_surface_init (&proxy->source.base, &cairo_xlib_proxy_backend, dst->base.device, - src->content); + src->content, + src->is_vector); proxy->source.dpy = dst->display->display; proxy->source.picture = XRenderCreatePicture (proxy->source.dpy, diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-surface-shm.c b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-surface-shm.c index 9824eff823b..1ee1e3d70f4 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-surface-shm.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-surface-shm.c @@ -573,7 +573,7 @@ _cairo_xlib_shm_pool_create(cairo_xlib_display_t *display, size_t bytes, maxbits = 16, minbits = MIN_BITS; Status success; - pool = malloc (sizeof (cairo_xlib_shm_t)); + pool = _cairo_malloc (sizeof (cairo_xlib_shm_t)); if (pool == NULL) return NULL; @@ -650,7 +650,7 @@ _cairo_xlib_shm_info_create (cairo_xlib_display_t *display, assert (mem != NULL); - info = malloc (sizeof (*info)); + info = _cairo_malloc (sizeof (*info)); if (info == NULL) { _cairo_mempool_free (&pool->mem, mem); return NULL; @@ -814,14 +814,15 @@ _cairo_xlib_shm_surface_create (cairo_xlib_surface_t *other, if (size < MIN_SIZE) return NULL; - shm = malloc (sizeof (*shm)); + shm = _cairo_malloc (sizeof (*shm)); if (unlikely (shm == NULL)) return (cairo_xlib_shm_surface_t *)_cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); _cairo_surface_init (&shm->image.base, &cairo_xlib_shm_surface_backend, other->base.device, - _cairo_content_from_pixman_format (format)); + _cairo_content_from_pixman_format (format), + FALSE); /* is_vector */ if (_cairo_xlib_display_acquire (other->base.device, &display)) goto cleanup_shm; @@ -1386,7 +1387,7 @@ _cairo_xlib_display_init_shm (cairo_xlib_display_t *display) if (!can_use_shm (display->display, &has_pixmap)) return; - shm = malloc (sizeof (*shm)); + shm = _cairo_malloc (sizeof (*shm)); if (unlikely (shm == NULL)) return; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-surface.c index ee14af2786d..2a6d896d3b9 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-surface.c @@ -189,12 +189,6 @@ _cairo_surface_is_xlib (cairo_surface_t *surface); #define CAIRO_ASSUME_PIXMAP 20 -static const XTransform identity = { { - { 1 << 16, 0x00000, 0x00000 }, - { 0x00000, 1 << 16, 0x00000 }, - { 0x00000, 0x00000, 1 << 16 }, -} }; - static Visual * _visual_for_xrender_format(Screen *screen, XRenderPictFormat *xrender_format) @@ -1772,7 +1766,7 @@ found: ; } - surface = malloc (sizeof (cairo_xlib_surface_t)); + surface = _cairo_malloc (sizeof (cairo_xlib_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -1800,7 +1794,8 @@ found: _cairo_surface_init (&surface->base, &cairo_xlib_surface_backend, screen->device, - _xrender_format_to_content (xrender_format)); + _xrender_format_to_content (xrender_format), + FALSE); /* is_vector */ surface->screen = screen; surface->compositor = display->compositor; @@ -1891,7 +1886,7 @@ static cairo_bool_t valid_size (int width, int height) /* Note: the minimum surface size allowed in the X protocol is 1x1. * However, as we historically did not check the minimum size we * allowed applications to lie and set the correct size later (one hopes). - * To preserve compatability we must allow applications to use + * To preserve compatibility we must allow applications to use * 0x0 surfaces. */ return (width >= 0 && width <= XLIB_COORD_MAX && diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-visual.c b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-visual.c index 863822eebbd..979cd5b36b4 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-visual.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-visual.c @@ -82,7 +82,7 @@ _cairo_xlib_visual_info_create (Display *dpy, for (i = 0; i < RAMP_SIZE; i++) ramp_index_to_short[i] = (0xffff * i + ((RAMP_SIZE-1)>>1)) / (RAMP_SIZE-1); - info = malloc (sizeof (cairo_xlib_visual_info_t)); + info = _cairo_malloc (sizeof (cairo_xlib_visual_info_t)); if (unlikely (info == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-xcb-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-xcb-surface.c index af3e1557899..4fa9f288328 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xlib-xcb-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xlib-xcb-surface.c @@ -391,7 +391,7 @@ _cairo_xlib_xcb_device_create (Display *dpy, cairo_device_t *xcb_device) } } - display = malloc (sizeof (cairo_xlib_xcb_display_t)); + display = _cairo_malloc (sizeof (cairo_xlib_xcb_display_t)); if (unlikely (display == NULL)) { device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); goto unlock; @@ -438,7 +438,7 @@ _cairo_xlib_xcb_surface_create (void *dpy, if (unlikely (xcb->status)) return xcb; - surface = malloc (sizeof (*surface)); + surface = _cairo_malloc (sizeof (*surface)); if (unlikely (surface == NULL)) { cairo_surface_destroy (xcb); return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); @@ -447,7 +447,8 @@ _cairo_xlib_xcb_surface_create (void *dpy, _cairo_surface_init (&surface->base, &_cairo_xlib_xcb_surface_backend, _cairo_xlib_xcb_device_create (dpy, xcb->device), - xcb->content); + xcb->content, + FALSE); /* is_vector */ /* _cairo_surface_init() got another reference to the device, drop ours */ cairo_device_destroy (surface->base.device); diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-xml-surface.c b/Build/source/libs/cairo/cairo-src/src/cairo-xml-surface.c index 6dbafdba2ba..35773a2b225 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-xml-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-xml-surface.c @@ -36,7 +36,7 @@ /* This surface is intended to produce a verbose, hierarchical, DAG XML file * representing a single surface. It is intended to be used by debuggers, - * such as cairo-sphinx, or by application test-suites that what a log of + * such as cairo-sphinx, or by application test-suites that want a log of * operations. */ @@ -258,7 +258,7 @@ _cairo_xml_create_internal (cairo_output_stream_t *stream) { cairo_xml_t *xml; - xml = malloc (sizeof (cairo_xml_t)); + xml = _cairo_malloc (sizeof (cairo_xml_t)); if (unlikely (xml == NULL)) return _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY); @@ -933,7 +933,7 @@ _cairo_xml_emit_type42_font (cairo_xml_t *xml, if (unlikely (status)) return status; - buf = malloc (size); + buf = _cairo_malloc (size); if (unlikely (buf == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -1098,14 +1098,15 @@ _cairo_xml_surface_create_internal (cairo_device_t *device, { cairo_xml_surface_t *surface; - surface = malloc (sizeof (cairo_xml_surface_t)); + surface = _cairo_malloc (sizeof (cairo_xml_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &_cairo_xml_surface_backend, device, - content); + content, + TRUE); /* is_vector */ surface->width = width; surface->height = height; diff --git a/Build/source/libs/cairo/cairo-src/src/cairo.c b/Build/source/libs/cairo/cairo-src/src/cairo.c index e3acf4d46c7..ca0c91e8b04 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo.c @@ -107,6 +107,221 @@ * space. **/ +/** + * SECTION:cairo-tag + * @Title: Tags and Links + * @Short_Description: Hyperlinks and document structure + * @See_Also: #cairo_pdf_surface_t + * + * The tag functions provide the ability to specify hyperlinks and + * document logical structure on supported backends. The following tags are supported: + * * [Link][link] - Create a hyperlink + * * [Destinations][dest] - Create a hyperlink destination + * * [Document Structure Tags][doc-struct] - Create PDF Document Structure + * + * # Link Tags # {#link} + * A hyperlink is specified by enclosing the hyperlink text with the %CAIRO_TAG_LINK tag. + * + * For example: + * + * cairo_tag_begin (cr, CAIRO_TAG_LINK, "uri='https://cairographics.org'"); + * cairo_move_to (cr, 50, 50); + * cairo_show_text (cr, "This is a link to the cairo website."); + * cairo_tag_end (cr, CAIRO_TAG_LINK); + * + * + * The PDF backend uses one or more rectangles to define the clickable + * area of the link. By default cairo will use the extents of the + * drawing operations enclosed by the begin/end link tags to define the + * clickable area. In some cases, such as a link split across two + * lines, the default rectangle is undesirable. + * + * @rect: [optional] The "rect" attribute allows the application to + * specify one or more rectangles that form the clickable region. The + * value of this attribute is an array of floats. Each rectangle is + * specified by four elements in the array: x, y, width, height. The + * array size must be a multiple of four. + * + * An example of creating a link with user specified clickable region: + * + * cairo_font_extents_t font_extents; + * cairo_text_extents_t text1_extents; + * cairo_text_extents_t text2_extents; + * char attribs[100]; + * const char *text1 = "This link is split"; + * const char *text2 = "across two lines"; + * + * cairo_font_extents (cr, &font_extents); + * cairo_move_to (cr, 450, 50); + * cairo_text_extents (cr, text1, &text1_extents); + * cairo_move_to (cr, 50, 70); + * cairo_text_extents (cr, text2, &text2_extents); + * sprintf (attribs, + * "rect=[%f %f %f %f %f %f %f %f] uri='https://cairographics.org'", + * text1_extents.x_bearing, + * text1_extents.y_bearing, + * text1_extents.width, + * text1_extents.height, + * text2_extents.x_bearing, + * text2_extents.y_bearing, + * text2_extents.width, + * text2_extents.height); + * + * cairo_tag_begin (cr, CAIRO_TAG_LINK, attribs); + * cairo_show_text (cr, "This is a link to the cairo website"); + * cairo_move_to (cr, 450, 50); + * cairo_show_text (cr, text1); + * cairo_move_to (cr, 50, 70); + * cairo_show_text (cr, text2); + * cairo_tag_end (cr, CAIRO_TAG_LINK); + * + * + * There are three types of links. Each type has its own attributes as detailed below. + * * [Internal Links][internal-link] - A link to a location in the same document + * * [URI Links][uri-link] - A link to a Uniform resource identifier + * * [File Links][file-link] - A link to a location in another document + * + * ## Internal Links ## {#internal-link} + * An internal link is a link to a location in the same document. The destination + * is specified with either: + * + * @dest: a UTF-8 string specifying the destination in the PDF file to link + * to. Destinations are created with the %CAIRO_TAG_DEST tag. + * + * or the two attributes: + * + * @page: An integer specifying the page number in the PDF file to link to. + * + * @pos: [optional] An array of two floats specifying the x,y position + * on the page. + * + * An example of the link attributes to link to a page and x,y position: + * + * "page=3 pos=[3.1 6.2]" + * + * + * ## URI Links ## {#uri-link} + * A URI link is a link to a Uniform Resource Identifier ([RFC 2396](http://tools.ietf.org/html/rfc2396)). + * + * A URI is specified with the following attribute: + * + * @uri: An ASCII string specifying the URI. + * + * An example of the link attributes to the cairo website: + * + * "uri='https://cairographics.org'" + * + * + * ## File Links ## {#file-link} + * A file link is a link a location in another PDF file. + * + * The file attribute (required) specifies the name of the PDF file: + * + * @file: File name of PDF file to link to. + * + * The position is specified by either: + * + * @dest: a UTF-8 string specifying the named destination in the PDF file. + * + * or + * + * @page: An integer specifying the page number in the PDF file. + * + * @pos: [optional] An array of two floats specifying the x,y + * position on the page. Position coordinates in external files are in PDF + * coordinates (0,0 at bottom left). + * + * An example of the link attributes to PDF file: + * + * "file='document.pdf' page=16 pos=[25 40]" + * + * + * # Destination Tags # {#dest} + * + * A destination is specified by enclosing the destination drawing + * operations with the %CAIRO_TAG_DEST tag. + * + * @name: [required] A UTF-8 string specifying the name of this destination. + * + * @x: [optional] A float specifying the x coordinate of destination + * position on this page. If not specified the default + * x coordinate is the left side of the extents of the + * operations enclosed by the %CAIRO_TAG_DEST begin/end tags. If + * no operations are enclosed, the x coordidate is 0. + * + * @y: [optional] A float specifying the y coordinate of destination + * position on this page. If not specified the default + * y coordinate is the top of the extents of the + * operations enclosed by the %CAIRO_TAG_DEST begin/end tags. If + * no operations are enclosed, the y coordidate is 0. + * + * @internal: A boolean that if true, the destination name may be + * omitted from PDF where possible. In this case, links + * refer directly to the page and position instead of via + * the named destination table. Note that if this + * destination is referenced by another PDF (see [File Links][file-link]), + * this attribute must be false. Default is false. + * + * + * /* Create a hyperlink */ + * cairo_tag_begin (cr, CAIRO_TAG_LINK, "dest='mydest' internal"); + * cairo_move_to (cr, 50, 50); + * cairo_show_text (cr, "This is a hyperlink."); + * cairo_tag_end (cr, CAIRO_TAG_LINK); + * + * /* Create a destination */ + * cairo_tag_begin (cr, CAIRO_TAG_DEST, "name='mydest'"); + * cairo_move_to (cr, 50, 250); + * cairo_show_text (cr, "This paragraph is the destination of the above link."); + * cairo_tag_end (cr, CAIRO_TAG_DEST); + * + * + * # Document Structure (PDF) # {#doc-struct} + * + * The document structure tags provide a means of specifying structural information + * such as headers, paragraphs, tables, and figures. The inclusion of structural information facilitates: + * * Extraction of text and graphics for copy and paste + * * Reflow of text and graphics in the viewer + * * Processing text eg searching and indexing + * * Conversion to other formats + * * Accessability support + * + * The list of structure types is specified in section 14.8.4 of the + * [PDF Reference](http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf). + * + * Note the PDF "Link" structure tag is the same as the cairo %CAIRO_TAG_LINK tag. + * + * The following example creates a document structure for a document containing two section, each with + * a header and a paragraph. + * + * + * cairo_tag_begin (cr, "Document", NULL); + * + * cairo_tag_begin (cr, "Sect", NULL); + * cairo_tag_begin (cr, "H1", NULL); + * cairo_show_text (cr, "Heading 1"); + * cairo_tag_end (cr, "H1"); + * + * cairo_tag_begin (cr, "P", NULL); + * cairo_show_text (cr, "Paragraph 1"); + * cairo_tag_end (cr, "P"); + * cairo_tag_end (cr, "Sect"); + * + * cairo_tag_begin (cr, "Sect", NULL); + * cairo_tag_begin (cr, "H1", NULL); + * cairo_show_text (cr, "Heading 2"); + * cairo_tag_end (cr, "H1"); + * + * cairo_tag_begin (cr, "P", NULL); + * cairo_show_text (cr, "Paragraph 2"); + * cairo_tag_end (cr, "P"); + * cairo_tag_end (cr, "Sect"); + * + * cairo_tag_end (cr, "Document"); + * + * + **/ + #define DEFINE_NIL_CONTEXT(status) \ { \ CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ \ @@ -153,7 +368,11 @@ static const cairo_t _cairo_nil[] = { DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_ERROR), DEFINE_NIL_CONTEXT (CAIRO_STATUS_INVALID_MESH_CONSTRUCTION), DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_FINISHED), - DEFINE_NIL_CONTEXT (CAIRO_STATUS_JBIG2_GLOBAL_MISSING) + DEFINE_NIL_CONTEXT (CAIRO_STATUS_JBIG2_GLOBAL_MISSING), + DEFINE_NIL_CONTEXT (CAIRO_STATUS_PNG_ERROR), + DEFINE_NIL_CONTEXT (CAIRO_STATUS_FREETYPE_ERROR), + DEFINE_NIL_CONTEXT (CAIRO_STATUS_WIN32_GDI_ERROR), + DEFINE_NIL_CONTEXT (CAIRO_STATUS_TAG_ERROR) }; COMPILE_TIME_ASSERT (ARRAY_LENGTH (_cairo_nil) == CAIRO_STATUS_LAST_STATUS - 1); @@ -260,8 +479,8 @@ _cairo_init (cairo_t *cr, * @cr from being destroyed until a matching call to cairo_destroy() * is made. * - * The number of references to a #cairo_t can be get using - * cairo_get_reference_count(). + * Use cairo_get_reference_count() to get the number of references to + * a #cairo_t. * * Return value: the referenced #cairo_t. * @@ -625,7 +844,7 @@ slim_hidden_def (cairo_set_operator); #if 0 -/** +/* * cairo_set_opacity: * @cr: a #cairo_t * @opacity: the level of opacity to use when compositing @@ -635,9 +854,7 @@ slim_hidden_def (cairo_set_operator); * using the alpha value. * * The default opacity is 1. - * - * Since: TBD - **/ + */ void cairo_set_opacity (cairo_t *cr, double opacity) { @@ -2663,6 +2880,100 @@ cairo_copy_clip_rectangle_list (cairo_t *cr) return cr->backend->clip_copy_rectangle_list (cr); } +/** + * CAIRO_TAG_DEST: + * + * Create a destination for a hyperlink. Destination tag attributes + * are detailed at [Destinations][dests]. + * + * Since: 1.16 + **/ + +/** + * CAIRO_TAG_LINK: + * + * Create hyperlink. Link tag attributes are detailed at + * [Links][links]. + * + * Since: 1.16 + **/ + +/** + * cairo_tag_begin: + * @cr: a cairo context + * @tag_name: tag name + * @attributes: tag attributes + * + * Marks the beginning of the @tag_name structure. Call + * cairo_tag_end() with the same @tag_name to mark the end of the + * structure. + * + * The attributes string is of the form "key1=value2 key2=value2 ...". + * Values may be boolean (true/false or 1/0), integer, float, string, + * or an array. + * + * String values are enclosed in single quotes + * ('). Single quotes and backslashes inside the string should be + * escaped with a backslash. + * + * Boolean values may be set to true by only + * specifying the key. eg the attribute string "key" is the equivalent + * to "key=true". + * + * Arrays are enclosed in '[]'. eg "rect=[1.2 4.3 2.0 3.0]". + * + * If no attributes are required, @attributes can be an empty string or NULL. + * + * See [Tags and Links Description][cairo-Tags-and-Links.description] + * for the list of tags and attributes. + * + * Invalid nesting of tags or invalid attributes will cause @cr to + * shutdown with a status of %CAIRO_STATUS_TAG_ERROR. + * + * See cairo_tag_end(). + * + * Since: 1.16 + **/ +void +cairo_tag_begin (cairo_t *cr, const char *tag_name, const char *attributes) +{ + cairo_status_t status; + + if (unlikely (cr->status)) + return; + + status = cr->backend->tag_begin (cr, tag_name, attributes); + if (unlikely (status)) + _cairo_set_error (cr, status); +} + +/** + * cairo_tag_end: + * @cr: a cairo context + * @tag_name: tag name + * + * Marks the end of the @tag_name structure. + * + * Invalid nesting of tags will cause @cr to shutdown with a status of + * %CAIRO_STATUS_TAG_ERROR. + * + * See cairo_tag_begin(). + * + * Since: 1.16 + **/ +cairo_public void +cairo_tag_end (cairo_t *cr, const char *tag_name) +{ + cairo_status_t status; + + if (unlikely (cr->status)) + return; + + status = cr->backend->tag_end (cr, tag_name); + if (unlikely (status)) + _cairo_set_error (cr, status); +} + /** * cairo_select_font_face: * @cr: a #cairo_t diff --git a/Build/source/libs/cairo/cairo-src/src/cairo.h b/Build/source/libs/cairo/cairo-src/src/cairo.h index 3104d47e4c4..3492bdc6bf9 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo.h +++ b/Build/source/libs/cairo/cairo-src/src/cairo.h @@ -292,6 +292,10 @@ typedef struct _cairo_user_data_key { * @CAIRO_STATUS_DEVICE_FINISHED: target device has been finished (Since 1.12) * @CAIRO_STATUS_JBIG2_GLOBAL_MISSING: %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID has been used on at least one image * but no image provided %CAIRO_MIME_TYPE_JBIG2_GLOBAL (Since 1.14) + * @CAIRO_STATUS_PNG_ERROR: error occurred in libpng while reading from or writing to a PNG file (Since 1.16) + * @CAIRO_STATUS_FREETYPE_ERROR: error occurred in libfreetype (Since 1.16) + * @CAIRO_STATUS_WIN32_GDI_ERROR: error occurred in the Windows Graphics Device Interface (Since 1.16) + * @CAIRO_STATUS_TAG_ERROR: invalid tag name, attributes, or nesting (Since 1.16) * @CAIRO_STATUS_LAST_STATUS: this is a special value indicating the number of * status values defined in this enumeration. When using this value, note * that the version of cairo at run-time may have additional status values @@ -348,6 +352,10 @@ typedef enum _cairo_status { CAIRO_STATUS_INVALID_MESH_CONSTRUCTION, CAIRO_STATUS_DEVICE_FINISHED, CAIRO_STATUS_JBIG2_GLOBAL_MISSING, + CAIRO_STATUS_PNG_ERROR, + CAIRO_STATUS_FREETYPE_ERROR, + CAIRO_STATUS_WIN32_GDI_ERROR, + CAIRO_STATUS_TAG_ERROR, CAIRO_STATUS_LAST_STATUS } cairo_status_t; @@ -390,7 +398,7 @@ typedef enum _cairo_content { * @CAIRO_FORMAT_A1: each pixel is a 1-bit quantity holding * an alpha value. Pixels are packed together into 32-bit * quantities. The ordering of the bits matches the - * endianess of the platform. On a big-endian machine, the + * endianness of the platform. On a big-endian machine, the * first pixel is in the uppermost bit, on a little-endian * machine the first pixel is in the least-significant bit. (Since 1.0) * @CAIRO_FORMAT_RGB16_565: each pixel is a 16-bit quantity @@ -598,7 +606,7 @@ cairo_pop_group_to_source (cairo_t *cr); * translucent layers too. * For a more detailed explanation of the effects of each operator, including * the mathematical definitions, see - * http://cairographics.org/operators/. + * https://cairographics.org/operators/. * * Since: 1.0 **/ @@ -1018,6 +1026,17 @@ cairo_copy_clip_rectangle_list (cairo_t *cr); cairo_public void cairo_rectangle_list_destroy (cairo_rectangle_list_t *rectangle_list); +/* Logical structure tagging functions */ + +#define CAIRO_TAG_DEST "cairo.dest" +#define CAIRO_TAG_LINK "Link" + +cairo_public void +cairo_tag_begin (cairo_t *cr, const char *tag_name, const char *attributes); + +cairo_public void +cairo_tag_end (cairo_t *cr, const char *tag_name); + /* Font/Text functions */ /** @@ -1044,7 +1063,7 @@ typedef struct _cairo_scaled_font cairo_scaled_font_t; * * A #cairo_font_face_t specifies all aspects of a font other * than the size or font matrix (a font matrix is used to distort - * a font by sheering it or scaling it unequally in the two + * a font by shearing it or scaling it unequally in the two * directions) . A font face can be set on a #cairo_t by using * cairo_set_font_face(); the size and font matrix are set with * cairo_set_font_size() and cairo_set_font_matrix(). @@ -1411,6 +1430,13 @@ cairo_font_options_set_hint_metrics (cairo_font_options_t *options, cairo_public cairo_hint_metrics_t cairo_font_options_get_hint_metrics (const cairo_font_options_t *options); +cairo_public const char * +cairo_font_options_get_variations (cairo_font_options_t *options); + +cairo_public void +cairo_font_options_set_variations (cairo_font_options_t *options, + const char *variations); + /* This interface is for dealing with text as text, not caring about the font object inside the the cairo_t. */ @@ -2340,7 +2366,6 @@ cairo_surface_status (cairo_surface_t *surface); * @CAIRO_SURFACE_TYPE_DRM: The surface is of type Direct Render Manager, since 1.10 * @CAIRO_SURFACE_TYPE_TEE: The surface is of type 'tee' (a multiplexing surface), since 1.10 * @CAIRO_SURFACE_TYPE_XML: The surface is of type XML (for debugging), since 1.10 - * @CAIRO_SURFACE_TYPE_SKIA: The surface is of type Skia, since 1.10 * @CAIRO_SURFACE_TYPE_SUBSURFACE: The surface is a subsurface created with * cairo_surface_create_for_rectangle(), since 1.10 * @CAIRO_SURFACE_TYPE_COGL: This surface is of type Cogl, since 1.12 @@ -2434,6 +2459,10 @@ cairo_surface_set_user_data (cairo_surface_t *surface, #define CAIRO_MIME_TYPE_JBIG2 "application/x-cairo.jbig2" #define CAIRO_MIME_TYPE_JBIG2_GLOBAL "application/x-cairo.jbig2-global" #define CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID "application/x-cairo.jbig2-global-id" +#define CAIRO_MIME_TYPE_CCITT_FAX "image/g3fax" +#define CAIRO_MIME_TYPE_CCITT_FAX_PARAMS "application/x-cairo.ccitt.params" +#define CAIRO_MIME_TYPE_EPS "application/postscript" +#define CAIRO_MIME_TYPE_EPS_PARAMS "application/x-cairo.eps.params" cairo_public void cairo_surface_get_mime_data (cairo_surface_t *surface, diff --git a/Build/source/libs/cairo/cairo-src/src/cairoint.h b/Build/source/libs/cairo/cairo-src/src/cairoint.h index 555aa899030..cfae18cf93b 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairoint.h +++ b/Build/source/libs/cairo/cairo-src/src/cairoint.h @@ -107,6 +107,12 @@ _cairo_win32_tmpfile (void); #undef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE) +#define ISFINITE(x) isfinite (x) +#else +#define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */ +#endif + #ifndef FALSE #define FALSE 0 #endif @@ -282,6 +288,12 @@ _cairo_isdigit (int c) return (c >= '0' && c <= '9'); } +static inline int cairo_const +_cairo_isalpha (int c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + #include "cairo-types-private.h" #include "cairo-cache-private.h" #include "cairo-reference-count-private.h" @@ -471,7 +483,8 @@ typedef enum _cairo_scaled_glyph_info { CAIRO_SCALED_GLYPH_INFO_METRICS = (1 << 0), CAIRO_SCALED_GLYPH_INFO_SURFACE = (1 << 1), CAIRO_SCALED_GLYPH_INFO_PATH = (1 << 2), - CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE = (1 << 3) + CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE = (1 << 3), + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE = (1 << 4) } cairo_scaled_glyph_info_t; typedef struct _cairo_scaled_font_subset { @@ -556,8 +569,12 @@ struct _cairo_scaled_font_backend { unsigned long index, uint32_t *ucs4); - cairo_warn cairo_bool_t - (*is_synthetic)(void *scaled_font); + /* Determine if this scaled font differs from the outlines in the font tables. + * eg synthesized bold/italic or a non default variant of a variable font. + */ + cairo_warn cairo_int_status_t + (*is_synthetic)(void *scaled_font, + cairo_bool_t *is_synthetic); /* For type 1 fonts, return the glyph name for a given glyph index. * A glyph index and list of glyph names in the Type 1 fonts is provided. @@ -597,6 +614,9 @@ struct _cairo_scaled_font_backend { long offset, unsigned char *buffer, unsigned long *length); + + cairo_bool_t + (*has_color_glyphs) (void *scaled_font); }; struct _cairo_font_face_backend { @@ -860,6 +880,9 @@ cairo_private void _cairo_font_options_init_copy (cairo_font_options_t *options, const cairo_font_options_t *other); +cairo_private void +_cairo_font_options_fini (cairo_font_options_t *options); + cairo_private void _cairo_font_options_set_lcd_filter (cairo_font_options_t *options, cairo_lcd_filter_t lcd_filter); @@ -892,6 +915,9 @@ _cairo_validate_text_clusters (const char *utf8, int num_clusters, cairo_text_cluster_flags_t cluster_flags); +cairo_private unsigned long +_cairo_string_hash (const char *str, int len); + cairo_private cairo_status_t _cairo_intern_string (const char **str_inout, int len); @@ -899,7 +925,10 @@ cairo_private void _cairo_intern_string_reset_static_data (void); cairo_private const char * -cairo_get_locale_decimal_point (void); +_cairo_get_locale_decimal_point (void); + +cairo_private double +_cairo_strtod (const char *nptr, char **endptr); /* cairo-path-fixed.c */ cairo_private cairo_path_fixed_t * @@ -1021,6 +1050,7 @@ cairo_private void _cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, + cairo_bool_t vector, cairo_rectangle_int_t *extents); cairo_private cairo_status_t @@ -1244,6 +1274,11 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font, cairo_surface_t *recording_surface); +cairo_private void +_cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font, + cairo_image_surface_t *surface); + cairo_private cairo_int_status_t _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, unsigned long index, @@ -1307,6 +1342,9 @@ _cairo_stroke_style_dash_approximate (const cairo_stroke_style_t *style, /* cairo-surface.c */ +cairo_private cairo_bool_t +_cairo_surface_has_mime_image (cairo_surface_t *surface); + cairo_private cairo_status_t _cairo_surface_copy_mime_data (cairo_surface_t *dst, cairo_surface_t *src); @@ -1335,7 +1373,8 @@ cairo_private void _cairo_surface_init (cairo_surface_t *surface, const cairo_surface_backend_t *backend, cairo_device_t *device, - cairo_content_t content); + cairo_content_t content, + cairo_bool_t is_vector); cairo_private void _cairo_surface_set_font_options (cairo_surface_t *surface, @@ -1415,6 +1454,17 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip); +cairo_private cairo_status_t +_cairo_surface_tag (cairo_surface_t *surface, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip); + cairo_private cairo_status_t _cairo_surface_acquire_source_image (cairo_surface_t *surface, cairo_image_surface_t **image_out, @@ -1468,7 +1518,7 @@ _cairo_surface_release_device_reference (cairo_surface_t *surface); * for that, even without being considered "valid" for the sake of * things like cairo_image_surface_create(). * - * Since 1.2.0 we ran into the same situtation with X servers with BGR + * Since 1.2.0 we ran into the same situation with X servers with BGR * visuals. This time we invented #cairo_internal_format_t instead, * (see it for more discussion). * @@ -1536,6 +1586,9 @@ _cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font, cairo_private void _cairo_image_reset_static_data (void); +cairo_private void +_cairo_image_compositor_reset_static_data (void); + cairo_private cairo_surface_t * _cairo_image_surface_create_with_pixman_format (unsigned char *data, pixman_format_code_t pixman_format, @@ -1779,6 +1832,12 @@ _cairo_matrix_to_pixman_matrix_offset (const cairo_matrix_t *matrix, int *out_x_offset, int *out_y_offset); +cairo_private void +_cairo_debug_print_matrix (FILE *file, const cairo_matrix_t *matrix); + +cairo_private void +_cairo_debug_print_rect (FILE *file, const cairo_rectangle_int_t *rect); + cairo_private cairo_status_t _cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t *traps, const cairo_polygon_t *polygon, @@ -1847,6 +1906,10 @@ cairo_private int _cairo_ucs4_to_utf8 (uint32_t unicode, char *utf8); +cairo_private int +_cairo_ucs4_to_utf16 (uint32_t unicode, + uint16_t *utf16); + #if CAIRO_HAS_WIN32_FONT || CAIRO_HAS_QUARTZ_FONT || CAIRO_HAS_PDF_OPERATORS # define CAIRO_HAS_UTF8_TO_UTF16 1 #endif @@ -1868,6 +1931,10 @@ _cairo_matrix_multiply (cairo_matrix_t *r, cairo_private void _cairo_observers_notify (cairo_list_t *observers, void *arg); +/* Open a file with a UTF-8 filename */ +cairo_private cairo_status_t +_cairo_fopen (const char *filename, const char *mode, FILE **file_out); + /* Avoid unnecessary PLT entries. */ slim_hidden_proto (cairo_clip_preserve); slim_hidden_proto (cairo_close_path); @@ -2060,7 +2127,7 @@ _cairo_debug_check_image_surface_is_defined (const cairo_surface_t *surface); #endif cairo_private void -_cairo_debug_print_path (FILE *stream, cairo_path_fixed_t *path); +_cairo_debug_print_path (FILE *stream, const cairo_path_fixed_t *path); cairo_private void _cairo_debug_print_polygon (FILE *stream, cairo_polygon_t *polygon); diff --git a/Build/source/libs/cairo/cairo-src/src/test-compositor-surface.c b/Build/source/libs/cairo/cairo-src/src/test-compositor-surface.c index 1cc5f692120..d6e04a122c2 100644 --- a/Build/source/libs/cairo/cairo-src/src/test-compositor-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/test-compositor-surface.c @@ -78,7 +78,7 @@ test_compositor_surface_create (const cairo_compositor_t *compositor, if (unlikely (pixman_image == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - surface = malloc (sizeof (test_compositor_surface_t)); + surface = _cairo_malloc (sizeof (test_compositor_surface_t)); if (unlikely (surface == NULL)) { pixman_image_unref (pixman_image); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -87,7 +87,8 @@ test_compositor_surface_create (const cairo_compositor_t *compositor, _cairo_surface_init (&surface->base.base, &test_compositor_surface_backend, NULL, /* device */ - content); + content, + FALSE); /* is_vector */ _cairo_image_surface_init (&surface->base, pixman_image, pixman_format); surface->base.compositor = compositor; diff --git a/Build/source/libs/cairo/cairo-src/src/test-null-compositor-surface.c b/Build/source/libs/cairo/cairo-src/src/test-null-compositor-surface.c index 2301055e30a..35913a2b9fb 100644 --- a/Build/source/libs/cairo/cairo-src/src/test-null-compositor-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/test-null-compositor-surface.c @@ -81,7 +81,7 @@ test_compositor_surface_create (const cairo_compositor_t *compositor, if (unlikely (pixman_image == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - surface = malloc (sizeof (test_compositor_surface_t)); + surface = _cairo_malloc (sizeof (test_compositor_surface_t)); if (unlikely (surface == NULL)) { pixman_image_unref (pixman_image); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); @@ -90,7 +90,8 @@ test_compositor_surface_create (const cairo_compositor_t *compositor, _cairo_surface_init (&surface->base.base, &test_compositor_surface_backend, NULL, /* device */ - content); + content, + FALSE); /* is_vector */ _cairo_image_surface_init (&surface->base, pixman_image, pixman_format); surface->base.compositor = compositor; @@ -403,9 +404,10 @@ check_composite (const cairo_composite_rectangles_t *extents) static const cairo_compositor_t * no_traps_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_traps_compositor_t compositor; - if (compositor.base.delegate == NULL) { + if (_cairo_atomic_init_once_enter(&once)) { _cairo_traps_compositor_init (&compositor, no_fallback_compositor_get ()); @@ -425,6 +427,8 @@ no_traps_compositor_get (void) compositor.composite_traps = composite_traps; compositor.check_composite_glyphs = check_composite_glyphs; compositor.composite_glyphs = composite_glyphs; + + _cairo_atomic_init_once_leave(&once); } return &compositor.base; @@ -433,9 +437,10 @@ no_traps_compositor_get (void) static const cairo_compositor_t * no_spans_compositor_get (void) { + static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; static cairo_spans_compositor_t compositor; - if (compositor.base.delegate == NULL) { + if (_cairo_atomic_init_once_enter(&once)) { _cairo_spans_compositor_init (&compositor, no_traps_compositor_get()); @@ -447,6 +452,8 @@ no_spans_compositor_get (void) //compositor.check_span_renderer = check_span_renderer; compositor.renderer_init = span_renderer_init; compositor.renderer_fini = span_renderer_fini; + + _cairo_atomic_init_once_leave(&once); } return &compositor.base; diff --git a/Build/source/libs/cairo/cairo-src/src/test-paginated-surface.c b/Build/source/libs/cairo/cairo-src/src/test-paginated-surface.c index 0a7c79b37bf..7967f7406cd 100644 --- a/Build/source/libs/cairo/cairo-src/src/test-paginated-surface.c +++ b/Build/source/libs/cairo/cairo-src/src/test-paginated-surface.c @@ -74,14 +74,15 @@ _cairo_test_paginated_surface_create (cairo_surface_t *target) if (unlikely (status)) return _cairo_surface_create_in_error (status); - surface = malloc (sizeof (test_paginated_surface_t)); + surface = _cairo_malloc (sizeof (test_paginated_surface_t)); if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); _cairo_surface_init (&surface->base, &test_paginated_surface_backend, NULL, /* device */ - target->content); + target->content, + TRUE); /* is_vector */ surface->target = cairo_surface_reference (target); @@ -231,13 +232,15 @@ _test_paginated_surface_show_text_glyphs (void *abstract_surface, } -static void +static cairo_int_status_t _test_paginated_surface_set_paginated_mode (void *abstract_surface, cairo_paginated_mode_t mode) { test_paginated_surface_t *surface = abstract_surface; surface->paginated_mode = mode; + + return CAIRO_STATUS_SUCCESS; } static const cairo_surface_backend_t test_paginated_surface_backend = { diff --git a/Build/source/libs/cairo/configure b/Build/source/libs/cairo/configure index 88aa5606f5c..905af910bf5 100755 --- a/Build/source/libs/cairo/configure +++ b/Build/source/libs/cairo/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for cairo (TeX Live) 1.14.12. +# Generated by GNU Autoconf 2.69 for cairo (TeX Live) 1.16.0. # # Report bugs to . # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='cairo (TeX Live)' PACKAGE_TARNAME='cairo--tex-live-' -PACKAGE_VERSION='1.14.12' -PACKAGE_STRING='cairo (TeX Live) 1.14.12' +PACKAGE_VERSION='1.16.0' +PACKAGE_STRING='cairo (TeX Live) 1.16.0' PACKAGE_BUGREPORT='tex-k@tug.org' PACKAGE_URL='' @@ -1349,7 +1349,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures cairo (TeX Live) 1.14.12 to adapt to many kinds of systems. +\`configure' configures cairo (TeX Live) 1.16.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1420,7 +1420,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of cairo (TeX Live) 1.14.12:";; + short | recursive ) echo "Configuration of cairo (TeX Live) 1.16.0:";; esac cat <<\_ACEOF @@ -1523,7 +1523,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -cairo (TeX Live) configure 1.14.12 +cairo (TeX Live) configure 1.16.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2129,7 +2129,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by cairo (TeX Live) $as_me 1.14.12, which was +It was created by cairo (TeX Live) $as_me 1.16.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4383,7 +4383,7 @@ fi # Define the identity of the package. PACKAGE='cairo--tex-live-' - VERSION='1.14.12' + VERSION='1.16.0' cat >>confdefs.h <<_ACEOF @@ -7274,7 +7274,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by cairo (TeX Live) $as_me 1.14.12, which was +This file was extended by cairo (TeX Live) $as_me 1.16.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -7340,7 +7340,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -cairo (TeX Live) config.status 1.14.12 +cairo (TeX Live) config.status 1.16.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/Build/source/libs/cairo/version.ac b/Build/source/libs/cairo/version.ac index 07c577c5867..6874654198b 100644 --- a/Build/source/libs/cairo/version.ac +++ b/Build/source/libs/cairo/version.ac @@ -8,4 +8,4 @@ dnl dnl -------------------------------------------------------- dnl dnl m4-include this file to define the current cairo version -m4_define([cairo_version], [1.14.12]) +m4_define([cairo_version], [1.16.0]) -- cgit v1.2.3