summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormh0310.choi <mh0310.choi@samsung.com>2015-07-28 10:46:57 +0900
committermh0310.choi <mh0310.choi@samsung.com>2015-07-28 13:08:12 +0900
commit5e67a6f721eaedda61300baf0799199c7771ebd0 (patch)
tree6cd50b52498aab50e79b966cdccc2a137db316d9 /src
parentd3aeffba37161d2b76b29c4ea13369bd67a47a8e (diff)
downloadcairo-5e67a6f721eaedda61300baf0799199c7771ebd0.tar.gz
cairo-5e67a6f721eaedda61300baf0799199c7771ebd0.tar.bz2
cairo-5e67a6f721eaedda61300baf0799199c7771ebd0.zip
- from 1.12.14 to 1.14.2 Change-Id: I3b62d212041b337bbb926d579f9ce74f42a45c3b
Diffstat (limited to 'src')
-rw-r--r--[-rwxr-xr-x]src/.gitignore4
-rw-r--r--[-rwxr-xr-x]src/Makefile.am0
-rw-r--r--[-rwxr-xr-x]src/Makefile.am.analysis0
-rw-r--r--[-rwxr-xr-x]src/Makefile.sources25
-rw-r--r--[-rwxr-xr-x]src/Makefile.win320
-rw-r--r--[-rwxr-xr-x]src/Makefile.win32.features59
-rw-r--r--[-rwxr-xr-x]src/README0
-rw-r--r--[-rwxr-xr-x]src/cairo-analysis-surface-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-analysis-surface.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-arc-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-arc.c4
-rw-r--r--[-rwxr-xr-x]src/cairo-array-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-array.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-atomic-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-atomic.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-backend-private.h1
-rw-r--r--[-rwxr-xr-x]src/cairo-base64-stream.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-base85-stream.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-bentley-ottmann-rectangular.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-bentley-ottmann-rectilinear.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-bentley-ottmann.c234
-rw-r--r--[-rwxr-xr-x]src/cairo-beos-surface.cpp0
-rw-r--r--[-rwxr-xr-x]src/cairo-beos.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-botor-scan-converter.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-box-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-boxes-intersect.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-boxes-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-boxes.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-cache-private.h2
-rw-r--r--[-rwxr-xr-x]src/cairo-cache.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-cff-subset.c45
-rw-r--r--src/cairo-cgl-context.c224
-rw-r--r--[-rwxr-xr-x]src/cairo-clip-boxes.c11
-rw-r--r--[-rwxr-xr-x]src/cairo-clip-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-clip-polygon.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-clip-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-clip-region.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-clip-surface.c20
-rw-r--r--[-rwxr-xr-x]src/cairo-clip-tor-scan-converter.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-clip.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-cogl-context-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-cogl-context.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-cogl-gradient-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-cogl-gradient.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-cogl-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-cogl-surface.c8
-rw-r--r--[-rwxr-xr-x]src/cairo-cogl-utils-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-cogl-utils.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-cogl.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-color.c11
-rw-r--r--[-rwxr-xr-x]src/cairo-combsort-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-compiler-private.h12
-rw-r--r--[-rwxr-xr-x]src/cairo-composite-rectangles-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-composite-rectangles.c11
-rw-r--r--[-rwxr-xr-x]src/cairo-compositor-private.h24
-rw-r--r--[-rwxr-xr-x]src/cairo-compositor.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-contour-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-contour-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-contour.c1
-rw-r--r--src/cairo-convex-fill-private.h112
-rw-r--r--src/cairo-convex-fill.c219
-rw-r--r--[-rwxr-xr-x]src/cairo-damage-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-damage.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-debug.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-default-context-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-default-context.c245
-rw-r--r--[-rwxr-xr-x]src/cairo-deflate-stream.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-deprecated.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-device-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-device.c3
-rw-r--r--[-rwxr-xr-x]src/cairo-directfb-surface.c4
-rw-r--r--[-rwxr-xr-x]src/cairo-directfb.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-drm.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-egl-context.c25
-rw-r--r--[-rwxr-xr-x]src/cairo-error-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-error-private.h8
-rw-r--r--[-rwxr-xr-x]src/cairo-error.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-evas-gl-context.c12
-rw-r--r--[-rwxr-xr-x]src/cairo-fallback-compositor.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-features-uninstalled.pc.in0
-rw-r--r--[-rwxr-xr-x]src/cairo-features.pc.in0
-rw-r--r--[-rwxr-xr-x]src/cairo-filters-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-filters.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-fixed-private.h40
-rw-r--r--[-rwxr-xr-x]src/cairo-fixed-type-private.h2
-rw-r--r--[-rwxr-xr-x]src/cairo-fixed.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-font-face-twin-data.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-font-face-twin.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-font-face.c44
-rw-r--r--[-rwxr-xr-x]src/cairo-font-options.c21
-rw-r--r--[-rwxr-xr-x]src/cairo-fontconfig-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-freed-pool-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-freed-pool.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-freelist-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-freelist-type-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-freelist.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-ft-font.c232
-rw-r--r--[-rwxr-xr-x]src/cairo-ft-private.h2
-rw-r--r--[-rwxr-xr-x]src/cairo-ft.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-composite.c189
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-device.c197
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-dispatch-private.h8
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-dispatch.c2
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-ext-def-private.h8
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-filters.c12
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-glyphs.c79
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-gradient-private.h35
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-gradient.c2
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-hairline-stroke.c13
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-info.c78
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-msaa-compositor.c139
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-operand.c156
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-private.h126
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-shaders.c757
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-source.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-spans-compositor.c3
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-surface-legacy.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-surface.c173
-rw-r--r--[-rwxr-xr-x]src/cairo-gl-traps-compositor.c161
-rw-r--r--[-rwxr-xr-x]src/cairo-gl.h15
-rw-r--r--[-rwxr-xr-x]src/cairo-glx-context.c7
-rw-r--r--[-rwxr-xr-x]src/cairo-gstate-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-gstate.c53
-rw-r--r--[-rwxr-xr-x]src/cairo-hash-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-hash.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-hull.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-image-compositor.c400
-rw-r--r--[-rwxr-xr-x]src/cairo-image-filters-private.h4
-rw-r--r--[-rwxr-xr-x]src/cairo-image-filters.c16
-rw-r--r--[-rwxr-xr-x]src/cairo-image-info-private.h5
-rw-r--r--[-rwxr-xr-x]src/cairo-image-info.c157
-rw-r--r--[-rwxr-xr-x]src/cairo-image-mask-compositor.c3
-rw-r--r--[-rwxr-xr-x]src/cairo-image-source.c559
-rw-r--r--[-rwxr-xr-x]src/cairo-image-surface-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-image-surface-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-image-surface.c23
-rw-r--r--src/cairo-line-inline.h48
-rw-r--r--[-rwxr-xr-x]src/cairo-line-private.h (renamed from src/cairo-tg.h)55
-rw-r--r--src/cairo-line.c306
-rw-r--r--[-rwxr-xr-x]src/cairo-list-inline.h8
-rw-r--r--[-rwxr-xr-x]src/cairo-list-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-lzw.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-malloc-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-mask-compositor.c14
-rw-r--r--[-rwxr-xr-x]src/cairo-matrix.c37
-rw-r--r--[-rwxr-xr-x]src/cairo-mempool-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-mempool.c3
-rw-r--r--[-rwxr-xr-x]src/cairo-mesh-pattern-rasterizer.c11
-rw-r--r--[-rwxr-xr-x]src/cairo-misc.c20
-rw-r--r--[-rwxr-xr-x]src/cairo-mono-scan-converter.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-mutex-impl-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-mutex-list-private.h5
-rw-r--r--[-rwxr-xr-x]src/cairo-mutex-private.h2
-rw-r--r--[-rwxr-xr-x]src/cairo-mutex-type-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-mutex.c7
-rw-r--r--[-rwxr-xr-x]src/cairo-no-compositor.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-observer.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-os2-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-os2-surface.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-os2.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-output-stream-private.h5
-rw-r--r--[-rwxr-xr-x]src/cairo-output-stream.c44
-rw-r--r--[-rwxr-xr-x]src/cairo-paginated-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-paginated-surface-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-paginated-surface.c2
-rw-r--r--[-rwxr-xr-x]src/cairo-path-bounds.c2
-rw-r--r--[-rwxr-xr-x]src/cairo-path-fill.c1
-rw-r--r--[-rwxr-xr-x]src/cairo-path-fixed-private.h2
-rw-r--r--[-rwxr-xr-x]src/cairo-path-fixed.c90
-rw-r--r--[-rwxr-xr-x]src/cairo-path-in-fill.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-path-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-path-stroke-boxes.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-path-stroke-polygon.c10
-rw-r--r--[-rwxr-xr-x]src/cairo-path-stroke-traps.c59
-rw-r--r--[-rwxr-xr-x]src/cairo-path-stroke-tristrip.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-path-stroke.c87
-rw-r--r--[-rwxr-xr-x]src/cairo-path.c2
-rw-r--r--[-rwxr-xr-x]src/cairo-pattern-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-pattern-private.h11
-rw-r--r--[-rwxr-xr-x]src/cairo-pattern.c332
-rw-r--r--[-rwxr-xr-x]src/cairo-pdf-operators-private.h11
-rw-r--r--[-rwxr-xr-x]src/cairo-pdf-operators.c41
-rw-r--r--[-rwxr-xr-x]src/cairo-pdf-shading-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-pdf-shading.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-pdf-surface-private.h12
-rw-r--r--[-rwxr-xr-x]src/cairo-pdf-surface.c1168
-rw-r--r--[-rwxr-xr-x]src/cairo-pdf.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-pen.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-pixman-private.h (renamed from src/cairo-tg-private.h)48
-rw-r--r--[-rwxr-xr-x]src/cairo-png.c14
-rw-r--r--[-rwxr-xr-x]src/cairo-polygon-intersect.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-polygon-reduce.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-polygon.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-ps-surface-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-ps-surface.c149
-rw-r--r--[-rwxr-xr-x]src/cairo-ps.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-qt-surface.cpp39
-rw-r--r--[-rwxr-xr-x]src/cairo-qt.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-quartz-filters.c2
-rw-r--r--[-rwxr-xr-x]src/cairo-quartz-font.c13
-rw-r--r--[-rwxr-xr-x]src/cairo-quartz-image-surface.c6
-rw-r--r--[-rwxr-xr-x]src/cairo-quartz-image.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-quartz-private.h3
-rw-r--r--[-rwxr-xr-x]src/cairo-quartz-surface.c16
-rw-r--r--[-rwxr-xr-x]src/cairo-quartz.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-raster-source-pattern.c2
-rw-r--r--[-rwxr-xr-x]src/cairo-recording-surface-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-recording-surface-private.h12
-rw-r--r--[-rwxr-xr-x]src/cairo-recording-surface.c139
-rw-r--r--[-rwxr-xr-x]src/cairo-rectangle.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-rectangular-scan-converter.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-reference-count-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-region-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-region.c13
-rw-r--r--[-rwxr-xr-x]src/cairo-rtree-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-rtree.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-scaled-font-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-scaled-font-subsets-private.h15
-rw-r--r--[-rwxr-xr-x]src/cairo-scaled-font-subsets.c40
-rw-r--r--[-rwxr-xr-x]src/cairo-scaled-font.c4
-rw-r--r--[-rwxr-xr-x]src/cairo-script-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-script-surface.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-script.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-shape-mask-compositor.c27
-rw-r--r--[-rwxr-xr-x]src/cairo-skia-surface.cpp49
-rw-r--r--[-rwxr-xr-x]src/cairo-skia.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-slope-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-slope.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-spans-compositor-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-spans-compositor.c30
-rw-r--r--[-rwxr-xr-x]src/cairo-spans-private.h2
-rw-r--r--[-rwxr-xr-x]src/cairo-spans.c2
-rw-r--r--[-rwxr-xr-x]src/cairo-spline.c1
-rw-r--r--[-rwxr-xr-x]src/cairo-stroke-dash-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-stroke-dash.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-stroke-style.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-backend-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-clipper-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-clipper.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-fallback-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-fallback.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-observer-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-observer-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-observer.c17
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-offset-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-offset.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-scale-translate-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-scale-translate.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-shadow-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-shadow.c48
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-snapshot-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-snapshot-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-snapshot.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-subsurface-inline.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-subsurface-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-subsurface.c30
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-wrapper-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-surface-wrapper.c9
-rw-r--r--[-rwxr-xr-x]src/cairo-surface.c321
-rw-r--r--[-rwxr-xr-x]src/cairo-svg-surface-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-svg-surface.c21
-rw-r--r--[-rwxr-xr-x]src/cairo-svg.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-tee-surface-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-tee-surface.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-tee.h0
-rwxr-xr-xsrc/cairo-tg-allocator-private.h134
-rwxr-xr-xsrc/cairo-tg-composite-extents-private.h121
-rwxr-xr-xsrc/cairo-tg-journal-private.h229
-rwxr-xr-xsrc/cairo-tg-journal.c520
-rwxr-xr-xsrc/cairo-tg-surface.c1372
-rwxr-xr-xsrc/cairo-thread-local-private.h161
-rw-r--r--[-rwxr-xr-x]src/cairo-time-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-time.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-tor-scan-converter.c489
-rw-r--r--[-rwxr-xr-x]src/cairo-tor22-scan-converter.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-toy-font-face.c7
-rw-r--r--[-rwxr-xr-x]src/cairo-traps-compositor.c267
-rw-r--r--[-rwxr-xr-x]src/cairo-traps-private.h8
-rw-r--r--[-rwxr-xr-x]src/cairo-traps.c90
-rw-r--r--[-rwxr-xr-x]src/cairo-tristrip-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-tristrip.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-truetype-subset-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-truetype-subset.c37
-rw-r--r--[-rwxr-xr-x]src/cairo-type1-fallback.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-type1-glyph-names.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-type1-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-type1-subset.c51
-rw-r--r--[-rwxr-xr-x]src/cairo-type3-glyph-surface-private.h8
-rw-r--r--[-rwxr-xr-x]src/cairo-type3-glyph-surface.c6
-rw-r--r--[-rwxr-xr-x]src/cairo-types-private.h8
-rw-r--r--[-rwxr-xr-x]src/cairo-unicode.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-uninstalled.pc.in0
-rw-r--r--[-rwxr-xr-x]src/cairo-user-font-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-user-font.c2
-rw-r--r--[-rwxr-xr-x]src/cairo-version.c11
-rw-r--r--[-rwxr-xr-x]src/cairo-version.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-vg-surface.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-vg.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-wgl-context.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-wideint-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-wideint-type-private.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-wideint.c8
-rw-r--r--[-rwxr-xr-x]src/cairo-win32.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-connection-core.c34
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-connection-render.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-connection-shm.c6
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-connection.c29
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-private.h53
-rw-r--r--src/cairo-xcb-resources.c281
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-screen.c130
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-shm.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-surface-core.c4
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-surface-render.c148
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-surface.c41
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-core-compositor.c4
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-display.c12
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-fallback-compositor.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-private.h6
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-render-compositor.c39
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-screen.c0
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-source.c80
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-surface-private.h2
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-surface-shm.c13
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-surface.c5
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-visual.c3
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-xcb-surface.c33
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-xrender-private.h4
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib-xrender.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-xlib.h0
-rw-r--r--[-rwxr-xr-x]src/cairo-xml-surface.c78
-rw-r--r--[-rwxr-xr-x]src/cairo-xml.h0
-rw-r--r--[-rwxr-xr-x]src/cairo.c54
-rw-r--r--[-rwxr-xr-x]src/cairo.h66
-rw-r--r--[-rwxr-xr-x]src/cairo.pc.in0
-rw-r--r--[-rwxr-xr-x]src/cairoint.h77
-rwxr-xr-xsrc/check-def.sh2
-rw-r--r--[-rwxr-xr-x]src/check-doc-syntax.awk2
-rwxr-xr-xsrc/check-doc-syntax.sh2
-rw-r--r--[-rwxr-xr-x]src/check-has-hidden-symbols.c0
-rw-r--r--[-rwxr-xr-x]src/check-link.c0
-rwxr-xr-xsrc/check-preprocessor-syntax.sh4
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-bo.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-gallium-surface.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i915-glyphs.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i915-private.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i915-shader.c39
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i915-spans.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i915-surface.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i965-glyphs.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i965-private.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i965-shader.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i965-spans.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-i965-surface.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-brw-defines.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-brw-eu-emit.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-brw-eu-util.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-brw-eu.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-brw-eu.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-brw-structs.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-command-private.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-debug.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-ioctl-private.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-private.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel-surface.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-intel.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-ioctl-private.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-private.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-radeon-private.h0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-radeon-surface.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-radeon.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm-surface.c0
-rw-r--r--[-rwxr-xr-x]src/drm/cairo-drm.c9
-rw-r--r--[-rwxr-xr-x]src/skia/cairo-skia-context.cpp65
-rw-r--r--[-rwxr-xr-x]src/skia/cairo-skia-private.h23
-rw-r--r--[-rwxr-xr-x]src/skia/cairo-skia-surface.cpp17
-rw-r--r--[-rwxr-xr-x]src/test-base-compositor-surface.c0
-rw-r--r--[-rwxr-xr-x]src/test-compositor-surface-private.h0
-rw-r--r--[-rwxr-xr-x]src/test-compositor-surface.c4
-rw-r--r--[-rwxr-xr-x]src/test-compositor-surface.h0
-rw-r--r--[-rwxr-xr-x]src/test-null-compositor-surface.c2
-rw-r--r--[-rwxr-xr-x]src/test-null-compositor-surface.h0
-rw-r--r--[-rwxr-xr-x]src/test-paginated-surface.c0
-rw-r--r--[-rwxr-xr-x]src/test-paginated-surface.h0
-rw-r--r--[-rwxr-xr-x]src/win32/cairo-win32-debug.c0
-rw-r--r--[-rwxr-xr-x]src/win32/cairo-win32-device.c0
-rw-r--r--[-rwxr-xr-x]src/win32/cairo-win32-display-surface.c14
-rw-r--r--[-rwxr-xr-x]src/win32/cairo-win32-font.c97
-rw-r--r--[-rwxr-xr-x]src/win32/cairo-win32-gdi-compositor.c3
-rw-r--r--[-rwxr-xr-x]src/win32/cairo-win32-printing-surface.c9
-rw-r--r--[-rwxr-xr-x]src/win32/cairo-win32-private.h0
-rw-r--r--[-rwxr-xr-x]src/win32/cairo-win32-surface.c21
-rw-r--r--[-rwxr-xr-x]src/win32/cairo-win32-system.c0
396 files changed, 7571 insertions, 5985 deletions
diff --git a/src/.gitignore b/src/.gitignore
index fd53c8649..534263a15 100755..100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -31,3 +31,7 @@ check-has-hidden-symbols.i
check-link
check-skiplist
headers-standalone
+!cairo.pc.in
+!cairo-uninstalled.pc.in
+!cairo-features.pc.in
+!cairo-features-uninstalled.pc.in
diff --git a/src/Makefile.am b/src/Makefile.am
index acf0a8281..acf0a8281 100755..100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
diff --git a/src/Makefile.am.analysis b/src/Makefile.am.analysis
index fab4cf7a5..fab4cf7a5 100755..100644
--- a/src/Makefile.am.analysis
+++ b/src/Makefile.am.analysis
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 0c9bfbe54..558065cbe 100755..100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -86,6 +86,8 @@ cairo_private = \
cairo-image-info-private.h \
cairo-image-surface-inline.h \
cairo-image-surface-private.h \
+ cairo-line-inline.h \
+ cairo-line-private.h \
cairo-list-inline.h \
cairo-list-private.h \
cairo-malloc-private.h \
@@ -101,6 +103,7 @@ cairo_private = \
cairo-path-private.h \
cairo-pattern-inline.h \
cairo-pattern-private.h \
+ cairo-pixman-private.h \
cairo-private.h \
cairo-recording-surface-inline.h \
cairo-recording-surface-private.h \
@@ -130,11 +133,11 @@ cairo_private = \
cairo-time-private.h \
cairo-types-private.h \
cairo-traps-private.h \
+ cairo-convex-fill-private.h \
cairo-tristrip-private.h \
cairo-user-font-private.h \
cairo-wideint-private.h \
cairo-wideint-type-private.h \
- cairo-thread-local-private.h \
$(NULL)
cairo_sources = \
cairo-analysis-surface.c \
@@ -182,6 +185,7 @@ cairo_sources = \
cairo-image-info.c \
cairo-image-source.c \
cairo-image-surface.c \
+ cairo-line.c \
cairo-lzw.c \
cairo-matrix.c \
cairo-mask-compositor.c \
@@ -198,6 +202,7 @@ cairo_sources = \
cairo-path.c \
cairo-path-fill.c \
cairo-path-fixed.c \
+ cairo-convex-fill.c \
cairo-path-in-fill.c \
cairo-path-stroke.c \
cairo-path-stroke-boxes.c \
@@ -268,6 +273,7 @@ cairo_sources += $(_cairo_font_subset_sources)
cairo_egl_sources =
cairo_glx_sources =
cairo_wgl_sources =
+cairo_cgl_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
@@ -342,6 +348,7 @@ cairo_xcb_sources = \
cairo-xcb-surface.c \
cairo-xcb-surface-core.c \
cairo-xcb-surface-render.c \
+ cairo-xcb-resources.c \
$(NULL)
cairo_qt_headers = cairo-qt.h
@@ -418,6 +425,9 @@ cairo_glesv3_headers = $(cairo_gl_headers)
cairo_glesv3_private = $(cairo_gl_private)
cairo_glesv3_sources = $(cairo_gl_sources)
+cairo_evasgl_headers =
+cairo_evasgl_private =
+cairo_evasgl_sources =
if CAIRO_HAS_EVASGL_SURFACE
if CAIRO_HAS_GL_SURFACE
cairo_evasgl_headers =
@@ -440,10 +450,6 @@ cairo_evasgl_sources = $(cairo_gl_sources)
endif
endif
endif
-else
-cairo_evasgl_headers =
-cairo_evasgl_private =
-cairo_evasgl_sources =
endif
cairo_egl_sources += cairo-egl-context.c
@@ -451,6 +457,7 @@ cairo_glx_sources += cairo-glx-context.c
cairo_wgl_sources += cairo-wgl-context.c
cairo_evasgl_headers += cairo-evas-gl.h
cairo_evasgl_sources += cairo-evas-gl-context.c
+cairo_cgl_sources += cairo-cgl-context.c
cairo_directfb_headers = cairo-directfb.h
cairo_directfb_sources = cairo-directfb-surface.c
@@ -511,11 +518,3 @@ cairo_cogl_sources = cairo-cogl-surface.c \
cairo-cogl-gradient.c \
cairo-cogl-context.c \
cairo-cogl-utils.c
-
-cairo_tg_headers = cairo-tg.h
-cairo_tg_private = cairo-tg-private.h \
- cairo-tg-allocator-private.h \
- cairo-tg-journal-private.h \
- cairo-tg-composite-extents-private.h
-cairo_tg_sources = cairo-tg-surface.c \
- cairo-tg-journal.c
diff --git a/src/Makefile.win32 b/src/Makefile.win32
index 864791f37..864791f37 100755..100644
--- a/src/Makefile.win32
+++ b/src/Makefile.win32
diff --git a/src/Makefile.win32.features b/src/Makefile.win32.features
index 268117094..fe7627c9c 100755..100644
--- a/src/Makefile.win32.features
+++ b/src/Makefile.win32.features
@@ -21,24 +21,6 @@ enabled_cairo_sources = $(cairo_sources)
all_cairo_pkgconf = cairo.pc
enabled_cairo_pkgconf = cairo.pc
-all_cairo_private += $(cairo_tls_private) $(cairo_tls_headers)
-all_cairo_cxx_sources += $(cairo_tls_cxx_sources)
-all_cairo_sources += $(cairo_tls_sources)
-ifeq ($(CAIRO_HAS_TLS),1)
-enabled_cairo_private += $(cairo_tls_private) $(cairo_tls_headers)
-enabled_cairo_cxx_sources += $(cairo_tls_cxx_sources)
-enabled_cairo_sources += $(cairo_tls_sources)
-endif
-
-all_cairo_private += $(cairo_pthread_setspecific_private) $(cairo_pthread_setspecific_headers)
-all_cairo_cxx_sources += $(cairo_pthread_setspecific_cxx_sources)
-all_cairo_sources += $(cairo_pthread_setspecific_sources)
-ifeq ($(CAIRO_HAS_PTHREAD_SETSPECIFIC),1)
-enabled_cairo_private += $(cairo_pthread_setspecific_private) $(cairo_pthread_setspecific_headers)
-enabled_cairo_cxx_sources += $(cairo_pthread_setspecific_cxx_sources)
-enabled_cairo_sources += $(cairo_pthread_setspecific_sources)
-endif
-
supported_cairo_headers += $(cairo_xlib_headers)
all_cairo_headers += $(cairo_xlib_headers)
all_cairo_private += $(cairo_xlib_private)
@@ -407,22 +389,6 @@ ifeq ($(CAIRO_HAS_DIRECTFB_SURFACE),1)
enabled_cairo_pkgconf += cairo-directfb.pc
endif
-unsupported_cairo_headers += $(cairo_tg_headers)
-all_cairo_headers += $(cairo_tg_headers)
-all_cairo_private += $(cairo_tg_private)
-all_cairo_cxx_sources += $(cairo_tg_cxx_sources)
-all_cairo_sources += $(cairo_tg_sources)
-ifeq ($(CAIRO_HAS_TG_SURFACE),1)
-enabled_cairo_headers += $(cairo_tg_headers)
-enabled_cairo_private += $(cairo_tg_private)
-enabled_cairo_cxx_sources += $(cairo_tg_cxx_sources)
-enabled_cairo_sources += $(cairo_tg_sources)
-endif
-all_cairo_pkgconf += cairo-tg.pc
-ifeq ($(CAIRO_HAS_TG_SURFACE),1)
-enabled_cairo_pkgconf += cairo-tg.pc
-endif
-
unsupported_cairo_headers += $(cairo_vg_headers)
all_cairo_headers += $(cairo_vg_headers)
all_cairo_private += $(cairo_vg_private)
@@ -471,6 +437,22 @@ ifeq ($(CAIRO_HAS_GLX_FUNCTIONS),1)
enabled_cairo_pkgconf += cairo-glx.pc
endif
+supported_cairo_headers += $(cairo_cgl_headers)
+all_cairo_headers += $(cairo_cgl_headers)
+all_cairo_private += $(cairo_cgl_private)
+all_cairo_cxx_sources += $(cairo_cgl_cxx_sources)
+all_cairo_sources += $(cairo_cgl_sources)
+ifeq ($(CAIRO_HAS_CGL_FUNCTIONS),1)
+enabled_cairo_headers += $(cairo_cgl_headers)
+enabled_cairo_private += $(cairo_cgl_private)
+enabled_cairo_cxx_sources += $(cairo_cgl_cxx_sources)
+enabled_cairo_sources += $(cairo_cgl_sources)
+endif
+all_cairo_pkgconf += cairo-cgl.pc
+ifeq ($(CAIRO_HAS_CGL_FUNCTIONS),1)
+enabled_cairo_pkgconf += cairo-cgl.pc
+endif
+
supported_cairo_headers += $(cairo_wgl_headers)
all_cairo_headers += $(cairo_wgl_headers)
all_cairo_private += $(cairo_wgl_private)
@@ -674,15 +656,6 @@ enabled_cairo_private += $(cairo_user_private)
enabled_cairo_cxx_sources += $(cairo_user_cxx_sources)
enabled_cairo_sources += $(cairo_user_sources)
-all_cairo_private += $(cairo_openmp_private) $(cairo_openmp_headers)
-all_cairo_cxx_sources += $(cairo_openmp_cxx_sources)
-all_cairo_sources += $(cairo_openmp_sources)
-ifeq ($(CAIRO_HAS_OPENMP),1)
-enabled_cairo_private += $(cairo_openmp_private) $(cairo_openmp_headers)
-enabled_cairo_cxx_sources += $(cairo_openmp_cxx_sources)
-enabled_cairo_sources += $(cairo_openmp_sources)
-endif
-
all_cairo_private += $(cairo_pthread_private) $(cairo_pthread_headers)
all_cairo_cxx_sources += $(cairo_pthread_cxx_sources)
all_cairo_sources += $(cairo_pthread_sources)
diff --git a/src/README b/src/README
index 03e4455ea..03e4455ea 100755..100644
--- a/src/README
+++ b/src/README
diff --git a/src/cairo-analysis-surface-private.h b/src/cairo-analysis-surface-private.h
index 1e054c209..1e054c209 100755..100644
--- a/src/cairo-analysis-surface-private.h
+++ b/src/cairo-analysis-surface-private.h
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 6717f7369..6717f7369 100755..100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
diff --git a/src/cairo-arc-private.h b/src/cairo-arc-private.h
index a22c01ac9..a22c01ac9 100755..100644
--- a/src/cairo-arc-private.h
+++ b/src/cairo-arc-private.h
diff --git a/src/cairo-arc.c b/src/cairo-arc.c
index 5cbd11238..390397bae 100755..100644
--- a/src/cairo-arc.c
+++ b/src/cairo-arc.c
@@ -236,6 +236,10 @@ _cairo_arc_in_direction (cairo_t *cr,
step = -step;
}
+ cairo_line_to (cr,
+ xc + radius * cos (angle_min),
+ yc + radius * sin (angle_min));
+
for (i = 0; i < segments; i++, angle_min += step) {
_cairo_arc_segment (cr, xc, yc, radius,
angle_min, angle_min + step);
diff --git a/src/cairo-array-private.h b/src/cairo-array-private.h
index 35b29e5fc..35b29e5fc 100755..100644
--- a/src/cairo-array-private.h
+++ b/src/cairo-array-private.h
diff --git a/src/cairo-array.c b/src/cairo-array.c
index e37bb9980..e37bb9980 100755..100644
--- a/src/cairo-array.c
+++ b/src/cairo-array.c
diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h
index 327fed1d9..327fed1d9 100755..100644
--- a/src/cairo-atomic-private.h
+++ b/src/cairo-atomic-private.h
diff --git a/src/cairo-atomic.c b/src/cairo-atomic.c
index 909cfea49..909cfea49 100755..100644
--- a/src/cairo-atomic.c
+++ b/src/cairo-atomic.c
diff --git a/src/cairo-backend-private.h b/src/cairo-backend-private.h
index cc5d5f313..8129fa22c 100755..100644
--- a/src/cairo-backend-private.h
+++ b/src/cairo-backend-private.h
@@ -116,6 +116,7 @@ struct _cairo_backend {
cairo_status_t (*arc) (void *cr, double xc, double yc, double radius, double angle1, double angle2, cairo_bool_t forward);
cairo_status_t (*rectangle) (void *cr, double x, double y, double width, double height);
+ cairo_status_t (*rounded_rectangle) (void *cr, double x, double y, double width, double height, double r_top_left, double r_top_right, double r_bottom_left, double r_bottom_right);
void (*path_extents) (void *cr, double *x1, double *y1, double *x2, double *y2);
cairo_bool_t (*has_current_point) (void *cr);
diff --git a/src/cairo-base64-stream.c b/src/cairo-base64-stream.c
index 636431372..636431372 100755..100644
--- a/src/cairo-base64-stream.c
+++ b/src/cairo-base64-stream.c
diff --git a/src/cairo-base85-stream.c b/src/cairo-base85-stream.c
index f81affb49..f81affb49 100755..100644
--- a/src/cairo-base85-stream.c
+++ b/src/cairo-base85-stream.c
diff --git a/src/cairo-bentley-ottmann-rectangular.c b/src/cairo-bentley-ottmann-rectangular.c
index 5541bdc3a..5541bdc3a 100755..100644
--- a/src/cairo-bentley-ottmann-rectangular.c
+++ b/src/cairo-bentley-ottmann-rectangular.c
diff --git a/src/cairo-bentley-ottmann-rectilinear.c b/src/cairo-bentley-ottmann-rectilinear.c
index 7c0be69b7..7c0be69b7 100755..100644
--- a/src/cairo-bentley-ottmann-rectilinear.c
+++ b/src/cairo-bentley-ottmann-rectilinear.c
diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c
index 7259add0c..3f6f02422 100755..100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -38,9 +38,10 @@
/* Provide definitions for standalone compilation */
#include "cairoint.h"
+#include "cairo-combsort-inline.h"
#include "cairo-error-private.h"
#include "cairo-freelist-private.h"
-#include "cairo-combsort-inline.h"
+#include "cairo-line-inline.h"
#include "cairo-traps-private.h"
#define DEBUG_PRINT_STATE 0
@@ -307,156 +308,6 @@ _slope_compare (const cairo_bo_edge_t *a,
}
}
-/*
- * We need to compare the x-coordinates of a pair of lines for a particular y,
- * without loss of precision.
- *
- * The x-coordinate along an edge for a given y is:
- * X = A_x + (Y - A_y) * A_dx / A_dy
- *
- * So the inequality we wish to test is:
- * A_x + (Y - A_y) * A_dx / A_dy ∘ B_x + (Y - B_y) * B_dx / B_dy,
- * where ∘ is our inequality operator.
- *
- * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
- * all positive, so we can rearrange it thus without causing a sign change:
- * A_dy * B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx * A_dy
- * - (Y - A_y) * A_dx * B_dy
- *
- * Given the assumption that all the deltas fit within 32 bits, we can compute
- * this comparison directly using 128 bit arithmetic. For certain, but common,
- * input we can reduce this down to a single 32 bit compare by inspecting the
- * deltas.
- *
- * (And put the burden of the work on developing fast 128 bit ops, which are
- * required throughout the tessellator.)
- *
- * See the similar discussion for _slope_compare().
- */
-static int
-edges_compare_x_for_y_general (const cairo_bo_edge_t *a,
- const cairo_bo_edge_t *b,
- int32_t y)
-{
- /* XXX: We're assuming here that dx and dy will still fit in 32
- * bits. That's not true in general as there could be overflow. We
- * should prevent that before the tessellation algorithm
- * begins.
- */
- int32_t dx;
- int32_t adx, ady;
- int32_t bdx, bdy;
- enum {
- HAVE_NONE = 0x0,
- HAVE_DX = 0x1,
- HAVE_ADX = 0x2,
- HAVE_DX_ADX = HAVE_DX | HAVE_ADX,
- HAVE_BDX = 0x4,
- HAVE_DX_BDX = HAVE_DX | HAVE_BDX,
- HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
- HAVE_ALL = HAVE_DX | HAVE_ADX | HAVE_BDX
- } have_dx_adx_bdx = HAVE_ALL;
-
- /* don't bother solving for abscissa if the edges' bounding boxes
- * can be used to order them. */
- {
- int32_t amin, amax;
- int32_t bmin, bmax;
- if (a->edge.line.p1.x < a->edge.line.p2.x) {
- amin = a->edge.line.p1.x;
- amax = a->edge.line.p2.x;
- } else {
- amin = a->edge.line.p2.x;
- amax = a->edge.line.p1.x;
- }
- if (b->edge.line.p1.x < b->edge.line.p2.x) {
- bmin = b->edge.line.p1.x;
- bmax = b->edge.line.p2.x;
- } else {
- bmin = b->edge.line.p2.x;
- bmax = b->edge.line.p1.x;
- }
- if (amax < bmin) return -1;
- if (amin > bmax) return +1;
- }
-
- ady = a->edge.line.p2.y - a->edge.line.p1.y;
- adx = a->edge.line.p2.x - a->edge.line.p1.x;
- if (adx == 0)
- have_dx_adx_bdx &= ~HAVE_ADX;
-
- bdy = b->edge.line.p2.y - b->edge.line.p1.y;
- bdx = b->edge.line.p2.x - b->edge.line.p1.x;
- if (bdx == 0)
- have_dx_adx_bdx &= ~HAVE_BDX;
-
- dx = a->edge.line.p1.x - b->edge.line.p1.x;
- if (dx == 0)
- have_dx_adx_bdx &= ~HAVE_DX;
-
-#define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
-#define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->edge.line.p1.y)
-#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->edge.line.p1.y)
- switch (have_dx_adx_bdx) {
- default:
- case HAVE_NONE:
- return 0;
- case HAVE_DX:
- /* A_dy * B_dy * (A_x - B_x) ∘ 0 */
- return dx; /* ady * bdy is positive definite */
- case HAVE_ADX:
- /* 0 ∘ - (Y - A_y) * A_dx * B_dy */
- return adx; /* bdy * (y - a->top.y) is positive definite */
- case HAVE_BDX:
- /* 0 ∘ (Y - B_y) * B_dx * A_dy */
- return -bdx; /* ady * (y - b->top.y) is positive definite */
- case HAVE_ADX_BDX:
- /* 0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
- if ((adx ^ bdx) < 0) {
- return adx;
- } else if (a->edge.line.p1.y == b->edge.line.p1.y) { /* common origin */
- cairo_int64_t adx_bdy, bdx_ady;
-
- /* ∴ A_dx * B_dy ∘ B_dx * A_dy */
-
- adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
- bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
-
- return _cairo_int64_cmp (adx_bdy, bdx_ady);
- } else
- return _cairo_int128_cmp (A, B);
- case HAVE_DX_ADX:
- /* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */
- if ((-adx ^ dx) < 0) {
- return dx;
- } else {
- cairo_int64_t ady_dx, dy_adx;
-
- ady_dx = _cairo_int32x32_64_mul (ady, dx);
- dy_adx = _cairo_int32x32_64_mul (a->edge.line.p1.y - y, adx);
-
- return _cairo_int64_cmp (ady_dx, dy_adx);
- }
- case HAVE_DX_BDX:
- /* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */
- if ((bdx ^ dx) < 0) {
- return dx;
- } else {
- cairo_int64_t bdy_dx, dy_bdx;
-
- bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
- dy_bdx = _cairo_int32x32_64_mul (y - b->edge.line.p1.y, bdx);
-
- return _cairo_int64_cmp (bdy_dx, dy_bdx);
- }
- case HAVE_ALL:
- /* XXX try comparing (a->edge.line.p2.x - b->edge.line.p2.x) et al */
- return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
- }
-#undef B
-#undef A
-#undef L
-}
/*
* We need to compare the x-coordinate of a line for a particular y wrt to a
@@ -510,58 +361,6 @@ edge_compare_for_y_against_x (const cairo_bo_edge_t *a,
return _cairo_int64_cmp (L, R);
}
-static int
-edges_compare_x_for_y (const cairo_bo_edge_t *a,
- const cairo_bo_edge_t *b,
- int32_t y)
-{
- /* If the sweep-line is currently on an end-point of a line,
- * then we know its precise x value (and considering that we often need to
- * compare events at end-points, this happens frequently enough to warrant
- * special casing).
- */
- enum {
- HAVE_NEITHER = 0x0,
- HAVE_AX = 0x1,
- HAVE_BX = 0x2,
- HAVE_BOTH = HAVE_AX | HAVE_BX
- } have_ax_bx = HAVE_BOTH;
- int32_t ax, bx;
-
- if (y == a->edge.line.p1.y)
- ax = a->edge.line.p1.x;
- else if (y == a->edge.line.p2.y)
- ax = a->edge.line.p2.x;
- else
- have_ax_bx &= ~HAVE_AX;
-
- if (y == b->edge.line.p1.y)
- bx = b->edge.line.p1.x;
- else if (y == b->edge.line.p2.y)
- bx = b->edge.line.p2.x;
- else
- have_ax_bx &= ~HAVE_BX;
-
- switch (have_ax_bx) {
- default:
- case HAVE_NEITHER:
- return edges_compare_x_for_y_general (a, b, y);
- case HAVE_AX:
- return -edge_compare_for_y_against_x (b, y, ax);
- case HAVE_BX:
- return edge_compare_for_y_against_x (a, y, bx);
- case HAVE_BOTH:
- return ax - bx;
- }
-}
-
-static inline int
-_line_equal (const cairo_line_t *a, const cairo_line_t *b)
-{
- return a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
- a->p2.x == b->p2.x && a->p2.y == b->p2.y;
-}
-
static inline int
_cairo_bo_sweep_line_compare_edges (const cairo_bo_sweep_line_t *sweep_line,
const cairo_bo_edge_t *a,
@@ -569,28 +368,11 @@ _cairo_bo_sweep_line_compare_edges (const cairo_bo_sweep_line_t *sweep_line,
{
int cmp;
- /* compare the edges if not identical */
- if (! _line_equal (&a->edge.line, &b->edge.line)) {
- if (MAX (a->edge.line.p1.x, a->edge.line.p2.x) <
- MIN (b->edge.line.p1.x, b->edge.line.p2.x))
- return -1;
- else if (MIN (a->edge.line.p1.x, a->edge.line.p2.x) >
- MAX (b->edge.line.p1.x, b->edge.line.p2.x))
- return 1;
-
- cmp = edges_compare_x_for_y (a, b, sweep_line->current_y);
- if (cmp)
- return cmp;
-
- /* The two edges intersect exactly at y, so fall back on slope
- * comparison. We know that this compare_edges function will be
- * called only when starting a new edge, (not when stopping an
- * edge), so we don't have to worry about conditionally inverting
- * the sense of _slope_compare. */
- cmp = _slope_compare (a, b);
- if (cmp)
+ cmp = cairo_lines_compare_at_y (&a->edge.line,
+ &b->edge.line,
+ sweep_line->current_y);
+ if (cmp)
return cmp;
- }
/* We've got two collinear edges now. */
return b->edge.bottom - a->edge.bottom;
@@ -1090,7 +872,7 @@ _cairo_bo_event_queue_insert_if_intersect_below_current_y (cairo_bo_event_queue_
MIN (right->edge.line.p1.x, right->edge.line.p2.x))
return CAIRO_STATUS_SUCCESS;
- if (_line_equal (&left->edge.line, &right->edge.line))
+ if (cairo_lines_equal (&left->edge.line, &right->edge.line))
return CAIRO_STATUS_SUCCESS;
/* The names "left" and "right" here are correct descriptions of
@@ -1691,7 +1473,7 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
cairo_bo_event_t **event_ptrs;
cairo_bo_start_event_t *stack_event_y[64];
cairo_bo_start_event_t **event_y = NULL;
- int i, num_events, y, ymin = 0, ymax = 0;
+ int i, num_events, y, ymin, ymax;
cairo_status_t status;
num_events = polygon->num_edges;
diff --git a/src/cairo-beos-surface.cpp b/src/cairo-beos-surface.cpp
index c97641685..c97641685 100755..100644
--- a/src/cairo-beos-surface.cpp
+++ b/src/cairo-beos-surface.cpp
diff --git a/src/cairo-beos.h b/src/cairo-beos.h
index fdb89a6c4..fdb89a6c4 100755..100644
--- a/src/cairo-beos.h
+++ b/src/cairo-beos.h
diff --git a/src/cairo-botor-scan-converter.c b/src/cairo-botor-scan-converter.c
index 515305bf2..515305bf2 100755..100644
--- a/src/cairo-botor-scan-converter.c
+++ b/src/cairo-botor-scan-converter.c
diff --git a/src/cairo-box-inline.h b/src/cairo-box-inline.h
index d6b994127..d6b994127 100755..100644
--- a/src/cairo-box-inline.h
+++ b/src/cairo-box-inline.h
diff --git a/src/cairo-boxes-intersect.c b/src/cairo-boxes-intersect.c
index 96ae66334..96ae66334 100755..100644
--- a/src/cairo-boxes-intersect.c
+++ b/src/cairo-boxes-intersect.c
diff --git a/src/cairo-boxes-private.h b/src/cairo-boxes-private.h
index d1f9dfcd1..d1f9dfcd1 100755..100644
--- a/src/cairo-boxes-private.h
+++ b/src/cairo-boxes-private.h
diff --git a/src/cairo-boxes.c b/src/cairo-boxes.c
index 63b68ddfb..63b68ddfb 100755..100644
--- a/src/cairo-boxes.c
+++ b/src/cairo-boxes.c
diff --git a/src/cairo-cache-private.h b/src/cairo-cache-private.h
index 76b556194..24b6d0b20 100755..100644
--- a/src/cairo-cache-private.h
+++ b/src/cairo-cache-private.h
@@ -43,7 +43,7 @@
#include "cairo-types-private.h"
/**
- * cairo_cache_entry_t:
+ * _cairo_cache_entry:
*
* A #cairo_cache_entry_t contains both a key and a value for
* #cairo_cache_t. User-derived types for #cairo_cache_entry_t must
diff --git a/src/cairo-cache.c b/src/cairo-cache.c
index 5c4e4caa3..5c4e4caa3 100755..100644
--- a/src/cairo-cache.c
+++ b/src/cairo-cache.c
diff --git a/src/cairo-cff-subset.c b/src/cairo-cff-subset.c
index 6e60568e6..da49e8e1e 100755..100644
--- a/src/cairo-cff-subset.c
+++ b/src/cairo-cff-subset.c
@@ -295,7 +295,6 @@ decode_nibble (int n, char *buf)
static unsigned char *
decode_real (unsigned char *p, double *real)
{
- struct lconv *locale_data;
const char *decimal_point;
int decimal_point_len;
int n;
@@ -305,8 +304,7 @@ decode_real (unsigned char *p, double *real)
char *buf = buffer;
char *buf_end = buffer + sizeof (buffer);
- locale_data = localeconv ();
- decimal_point = locale_data->decimal_point;
+ decimal_point = cairo_get_locale_decimal_point ();
decimal_point_len = strlen (decimal_point);
assert (decimal_point_len != 0);
@@ -435,7 +433,7 @@ cff_index_read (cairo_array_t *index, unsigned char **ptr, unsigned char *end_pt
p = *ptr;
if (p + 2 > end_ptr)
return CAIRO_INT_STATUS_UNSUPPORTED;
- count = be16_to_cpu( *((uint16_t *)p) );
+ count = get_unaligned_be16 (p);
p += 2;
if (count > 0) {
offset_size = *p++;
@@ -905,6 +903,8 @@ cairo_cff_font_read_name (cairo_cff_font_t *font)
memcpy (font->ps_name, p, len);
font->ps_name[len] = 0;
+
+ status = _cairo_escape_ps_name (&font->ps_name);
}
cff_index_fini (&index);
@@ -990,14 +990,14 @@ cairo_cff_font_read_fdselect (cairo_cff_font_t *font, unsigned char *p)
for (i = 0; i < font->num_glyphs; i++)
font->fdselect[i] = *p++;
} else if (type == 3) {
- num_ranges = be16_to_cpu( *((uint16_t *)p) );
+ num_ranges = get_unaligned_be16 (p);
p += 2;
for (i = 0; i < num_ranges; i++)
{
- first = be16_to_cpu( *((uint16_t *)p) );
+ first = get_unaligned_be16 (p);
p += 2;
fd = *p++;
- last = be16_to_cpu( *((uint16_t *)p) );
+ last = get_unaligned_be16 (p);
for (j = first; j < last; j++)
font->fdselect[j] = fd;
}
@@ -1058,13 +1058,13 @@ cairo_cff_font_read_cid_fontdict (cairo_cff_font_t *font, unsigned char *ptr)
goto fail;
}
- font->fd_default_width = calloc (sizeof (int), font->num_fontdicts);
+ font->fd_default_width = calloc (font->num_fontdicts, sizeof (double));
if (unlikely (font->fd_default_width == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail;
}
- font->fd_nominal_width = calloc (sizeof (int), font->num_fontdicts);
+ font->fd_nominal_width = calloc (font->num_fontdicts, sizeof (double));
if (unlikely (font->fd_nominal_width == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto fail;
@@ -1757,7 +1757,7 @@ cairo_cff_font_get_gid_for_cid (cairo_cff_font_t *font, unsigned long cid, unsi
p = font->charset + 1;
g = 1;
while (g <= (unsigned)font->num_glyphs && p < font->data_end) {
- c = be16_to_cpu( *((uint16_t *)p) );
+ c = get_unaligned_be16 (p);
if (c == cid) {
*gid = g;
return CAIRO_STATUS_SUCCESS;
@@ -1772,7 +1772,7 @@ cairo_cff_font_get_gid_for_cid (cairo_cff_font_t *font, unsigned long cid, unsi
first_gid = 1;
p = font->charset + 1;
while (first_gid <= (unsigned)font->num_glyphs && p + 2 < font->data_end) {
- first_cid = be16_to_cpu( *((uint16_t *)p) );
+ first_cid = get_unaligned_be16 (p);
num_left = p[2];
if (cid >= first_cid && cid <= first_cid + num_left) {
*gid = first_gid + cid - first_cid;
@@ -1788,8 +1788,8 @@ cairo_cff_font_get_gid_for_cid (cairo_cff_font_t *font, unsigned long cid, unsi
first_gid = 1;
p = font->charset + 1;
while (first_gid <= (unsigned)font->num_glyphs && p + 3 < font->data_end) {
- first_cid = be16_to_cpu( *((uint16_t *)p) );
- num_left = be16_to_cpu( *((uint16_t *)(p+2)) );
+ first_cid = get_unaligned_be16 (p);
+ num_left = get_unaligned_be16 (p+2);
if (cid >= first_cid && cid <= first_cid + num_left) {
*gid = first_gid + cid - first_cid;
return CAIRO_STATUS_SUCCESS;
@@ -2366,7 +2366,7 @@ cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
unsigned int i;
cairo_int_status_t status;
unsigned int offset_array;
- uint32_t *offset_array_ptr;
+ unsigned char *offset_array_ptr;
int offset_base;
uint16_t count;
uint8_t offset_size = 4;
@@ -2387,7 +2387,7 @@ cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
if (unlikely (status))
return status;
offset_base = _cairo_array_num_elements (&font->output) - 1;
- *offset_array_ptr = cpu_to_be32(1);
+ put_unaligned_be32(1, offset_array_ptr);
offset_array += sizeof(uint32_t);
for (i = 0; i < font->num_subset_fontdicts; i++) {
status = cff_dict_write (font->fd_dict[font->fd_subset_map[i]],
@@ -2395,8 +2395,9 @@ cairo_cff_font_write_cid_fontdict (cairo_cff_font_t *font)
if (unlikely (status))
return status;
- offset_array_ptr = (uint32_t *) _cairo_array_index (&font->output, offset_array);
- *offset_array_ptr = cpu_to_be32(_cairo_array_num_elements (&font->output) - offset_base);
+ offset_array_ptr = _cairo_array_index (&font->output, offset_array);
+ put_unaligned_be32 (_cairo_array_num_elements (&font->output) - offset_base,
+ offset_array_ptr);
offset_array += sizeof(uint32_t);
}
@@ -2647,7 +2648,7 @@ cairo_cff_font_create_set_widths (cairo_cff_font_t *font)
unsigned int i;
tt_hhea_t hhea;
int num_hmetrics;
- unsigned char buf[10];
+ uint16_t short_entry;
int glyph_index;
cairo_int_status_t status;
@@ -2667,7 +2668,8 @@ cairo_cff_font_create_set_widths (cairo_cff_font_t *font)
status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
glyph_index * long_entry_size,
- buf, &short_entry_size);
+ (unsigned char *) &short_entry,
+ &short_entry_size);
if (unlikely (status))
return status;
}
@@ -2676,11 +2678,12 @@ cairo_cff_font_create_set_widths (cairo_cff_font_t *font)
status = font->backend->load_truetype_table (font->scaled_font_subset->scaled_font,
TT_TAG_hmtx,
(num_hmetrics - 1) * long_entry_size,
- buf, &short_entry_size);
+ (unsigned char *) &short_entry,
+ &short_entry_size);
if (unlikely (status))
return status;
}
- font->widths[i] = be16_to_cpu (*((int16_t*)buf));
+ font->widths[i] = be16_to_cpu (short_entry);
}
return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-cgl-context.c b/src/cairo-cgl-context.c
new file mode 100644
index 000000000..6f5e557f4
--- /dev/null
+++ b/src/cairo-cgl-context.c
@@ -0,0 +1,224 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Eric Anholt
+ * Copyright © 2009 Chris Wilson
+ * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2015 Samsung Research America, Inc. - Silicon Valley
+ *
+ * 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 Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl Worth <cworth@cworth.org>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ * Henry Songn <hsong@sisa.samsung.com>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-gl-private.h"
+
+#include "cairo-error-private.h"
+
+#include <dlfcn.h>
+
+typedef struct _cairo_cgl_context {
+ cairo_gl_context_t base;
+
+ CGLContextObj context;
+ CGLContextObj prev_context;
+} cairo_cgl_context_t;
+
+typedef struct _cairo_cgl_surface {
+ cairo_gl_surface_t base;
+
+ CGLContextObj context;
+} cairo_cgl_surface_t;
+
+static void *
+_cgl_query_current_state (cairo_cgl_context_t * ctx)
+{
+ ctx->prev_context = CGLGetCurrentContext ();
+}
+
+static void
+_cgl_acquire (void *abstract_ctx)
+{
+ cairo_cgl_context_t *ctx = abstract_ctx;
+ _cgl_query_current_state (ctx);
+
+ if (ctx->prev_context == ctx->context)
+ return;
+
+ _cairo_gl_context_reset (&ctx->base);
+
+ CGLLockContext (ctx->context);
+ CGLSetCurrentContext (ctx->context);
+}
+
+static void
+_cgl_make_current (void *abstract_ctx, cairo_gl_surface_t *abstract_surface)
+{
+ cairo_cgl_context_t *ctx = abstract_ctx;
+ cairo_cgl_surface_t *surface = (cairo_cgl_surface_t *) abstract_surface;
+
+ /* Set the window as the target of our context. */
+ if (ctx->context != surface->context) {
+ CGLLockContext (surface->context);
+ CGLSetCurrentContext (surface->context);
+ }
+}
+
+static void
+_cgl_release (void *abstract_ctx)
+{
+ cairo_cgl_context_t *ctx = abstract_ctx;
+
+ if (!ctx->base.thread_aware)
+ return;
+
+ CGLSetCurrentContext (NULL);
+ CGLUnlockContext (ctx->context);
+}
+
+static void
+_cgl_swap_buffers (void *abstract_ctx,
+ cairo_gl_surface_t *abstract_surface)
+{
+ cairo_cgl_context_t *ctx = abstract_ctx;
+ cairo_cgl_surface_t *surface = (cairo_cgl_surface_t *)abstract_surface;
+
+ /* is it possible to have different context? */
+ if (ctx->context == surface->context)
+ CGLFlushDrawable (surface->context);
+}
+
+static void
+_cgl_destroy (void *abstract_ctx)
+{
+ cairo_cgl_context_t *ctx = abstract_ctx;
+
+ CGLSetCurrentContext (NULL);
+ CGLReleaseContext (ctx->context);
+ CGLUnlockContext (ctx->context);
+}
+
+static cairo_gl_generic_func_t
+_cairo_cgl_get_proc_address (void *data, const char *name)
+{
+ return dlsym (RTLD_DEFAULT, name);
+}
+
+cairo_device_t *
+cairo_cgl_device_create (CGLContextObj context)
+{
+ cairo_cgl_context_t *ctx;
+ cairo_status_t status;
+
+ ctx = calloc (1, sizeof (cairo_cgl_context_t));
+ if (unlikely (ctx == NULL))
+ return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
+
+ ctx->context = CGLRetainContext (context);
+
+ ctx->base.acquire = _cgl_acquire;
+ ctx->base.release = _cgl_release;
+ ctx->base.make_current = _cgl_make_current;
+ ctx->base.swap_buffers = _cgl_swap_buffers;
+ ctx->base.destroy = _cgl_destroy;
+
+ _cgl_query_current_state (ctx);
+ if (ctx->context != ctx->prev_context) {
+ CGLLockContext (ctx->context);
+ CGLSetCurrentContext (ctx->context);
+ }
+
+ status = _cairo_gl_dispatch_init (&ctx->base.dispatch,
+ (cairo_gl_get_proc_addr_func_t) _cairo_cgl_get_proc_address,
+ NULL);
+
+ if (unlikely (status)) {
+ ctx->base.release (ctx);
+ CGLReleaseContext (ctx->context);
+ free (ctx);
+ return _cairo_gl_context_create_in_error (status);
+ }
+
+ status = _cairo_gl_context_init (&ctx->base);
+ if (unlikely (status)) {
+ ctx->base.release (ctx);
+ CGLReleaseContext (ctx->context);
+ free (ctx);
+ return _cairo_gl_context_create_in_error (status);
+ }
+
+ ctx->base.release (ctx);
+
+ return &ctx->base.base;
+}
+
+CGLContextObj
+cairo_cgl_device_get_context (cairo_device_t *device)
+{
+ cairo_cgl_context_t *ctx;
+
+ if (device->backend->type != CAIRO_DEVICE_TYPE_GL) {
+ _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
+ return NULL;
+ }
+
+ ctx = (cairo_cgl_context_t *) device;
+
+ return ctx->context;
+}
+
+cairo_surface_t *
+cairo_gl_surface_create_for_cgl (cairo_device_t *device,
+ int width,
+ int height)
+{
+ cairo_cgl_surface_t *surface;
+
+ if (unlikely (device->status))
+ return _cairo_surface_create_in_error (device->status);
+
+ if (device->backend->type != CAIRO_DEVICE_TYPE_GL)
+ 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));
+
+ surface = calloc (1, sizeof (cairo_cgl_surface_t));
+ if (unlikely (surface == NULL))
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+ _cairo_gl_surface_init (device, &surface->base,
+ CAIRO_CONTENT_COLOR_ALPHA, width, height);
+ surface->context = ((cairo_cgl_context_t *) device)->context;
+
+ return &surface->base.base;
+}
diff --git a/src/cairo-clip-boxes.c b/src/cairo-clip-boxes.c
index eae0919af..0501fa273 100755..100644
--- a/src/cairo-clip-boxes.c
+++ b/src/cairo-clip-boxes.c
@@ -173,7 +173,7 @@ _cairo_clip_intersect_rectangle_box (cairo_clip_t *clip,
clip->extents = *r;
} else {
if (! _cairo_rectangle_intersect (&clip->extents, r))
- clip = _cairo_clip_set_all_clipped (clip);
+ return _cairo_clip_set_all_clipped (clip);
}
if (clip->path == NULL)
clip->is_region = _cairo_box_is_pixel_aligned (box);
@@ -258,6 +258,9 @@ _cairo_clip_intersect_box (cairo_clip_t *clip,
{
cairo_rectangle_int_t r;
+ if (_cairo_clip_is_all_clipped (clip))
+ return clip;
+
_cairo_box_round_to_rectangle (box, &r);
if (r.width == 0 || r.height == 0)
return _cairo_clip_set_all_clipped (clip);
@@ -315,10 +318,12 @@ _cairo_clip_intersect_boxes (cairo_clip_t *clip,
_cairo_boxes_extents (boxes, &limits);
_cairo_box_round_to_rectangle (&limits, &extents);
- if (clip->path == NULL)
+ if (clip->path == NULL) {
clip->extents = extents;
- else if (! _cairo_rectangle_intersect (&clip->extents, &extents))
+ } else if (! _cairo_rectangle_intersect (&clip->extents, &extents)) {
clip = _cairo_clip_set_all_clipped (clip);
+ goto out;
+ }
if (clip->region) {
cairo_region_destroy (clip->region);
diff --git a/src/cairo-clip-inline.h b/src/cairo-clip-inline.h
index a9f232692..a9f232692 100755..100644
--- a/src/cairo-clip-inline.h
+++ b/src/cairo-clip-inline.h
diff --git a/src/cairo-clip-polygon.c b/src/cairo-clip-polygon.c
index f40faefba..f40faefba 100755..100644
--- a/src/cairo-clip-polygon.c
+++ b/src/cairo-clip-polygon.c
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index c2ed66419..c2ed66419 100755..100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
diff --git a/src/cairo-clip-region.c b/src/cairo-clip-region.c
index e3f4891e3..e3f4891e3 100755..100644
--- a/src/cairo-clip-region.c
+++ b/src/cairo-clip-region.c
diff --git a/src/cairo-clip-surface.c b/src/cairo-clip-surface.c
index f1c13a4ae..a92379eba 100755..100644
--- a/src/cairo-clip-surface.c
+++ b/src/cairo-clip-surface.c
@@ -134,11 +134,11 @@ _cairo_clip_get_surface (const cairo_clip_t *clip,
cairo_path_fixed_t path;
int i;
- surface = _cairo_surface_create_similar_solid (target,
- CAIRO_CONTENT_ALPHA,
- clip->extents.width,
- clip->extents.height,
- CAIRO_COLOR_TRANSPARENT);
+ surface = _cairo_surface_create_scratch (target,
+ CAIRO_CONTENT_ALPHA,
+ clip->extents.width,
+ clip->extents.height,
+ CAIRO_COLOR_TRANSPARENT);
if (unlikely (surface->status))
return surface;
@@ -164,11 +164,11 @@ _cairo_clip_get_surface (const cairo_clip_t *clip,
return _cairo_surface_create_in_error (status);
}
} else {
- surface = _cairo_surface_create_similar_solid (target,
- CAIRO_CONTENT_ALPHA,
- clip->extents.width,
- clip->extents.height,
- CAIRO_COLOR_WHITE);
+ surface = _cairo_surface_create_scratch (target,
+ CAIRO_CONTENT_ALPHA,
+ clip->extents.width,
+ clip->extents.height,
+ CAIRO_COLOR_WHITE);
if (unlikely (surface->status))
return surface;
}
diff --git a/src/cairo-clip-tor-scan-converter.c b/src/cairo-clip-tor-scan-converter.c
index e32a5a9d9..e32a5a9d9 100755..100644
--- a/src/cairo-clip-tor-scan-converter.c
+++ b/src/cairo-clip-tor-scan-converter.c
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index dcafaf229..dcafaf229 100755..100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
diff --git a/src/cairo-cogl-context-private.h b/src/cairo-cogl-context-private.h
index 0a7185ef1..0a7185ef1 100755..100644
--- a/src/cairo-cogl-context-private.h
+++ b/src/cairo-cogl-context-private.h
diff --git a/src/cairo-cogl-context.c b/src/cairo-cogl-context.c
index 0116b0a5a..0116b0a5a 100755..100644
--- a/src/cairo-cogl-context.c
+++ b/src/cairo-cogl-context.c
diff --git a/src/cairo-cogl-gradient-private.h b/src/cairo-cogl-gradient-private.h
index fa684d2c6..fa684d2c6 100755..100644
--- a/src/cairo-cogl-gradient-private.h
+++ b/src/cairo-cogl-gradient-private.h
diff --git a/src/cairo-cogl-gradient.c b/src/cairo-cogl-gradient.c
index f8c800416..f8c800416 100755..100644
--- a/src/cairo-cogl-gradient.c
+++ b/src/cairo-cogl-gradient.c
diff --git a/src/cairo-cogl-private.h b/src/cairo-cogl-private.h
index 13fe5a8dc..13fe5a8dc 100755..100644
--- a/src/cairo-cogl-private.h
+++ b/src/cairo-cogl-private.h
diff --git a/src/cairo-cogl-surface.c b/src/cairo-cogl-surface.c
index 27c3676de..c57fd7f43 100755..100644
--- a/src/cairo-cogl-surface.c
+++ b/src/cairo-cogl-surface.c
@@ -143,7 +143,7 @@ typedef struct _cairo_cogl_path_fill_meta {
* and translations but not for different scales.
*
* one idea is to track the diagonal lenghts of a unit rectangle
- * transformed through the original ctm use to tesselate the geometry
+ * transformed through the original ctm use to tessellate the geometry
* so we can check what the lengths are for any new ctm to know if
* this geometry is compatible.
*/
@@ -167,7 +167,7 @@ typedef struct _cairo_cogl_path_stroke_meta {
* and translations but not for different scales.
*
* one idea is to track the diagonal lenghts of a unit rectangle
- * transformed through the original ctm use to tesselate the geometry
+ * transformed through the original ctm use to tessellate the geometry
* so we can check what the lengths are for any new ctm to know if
* this geometry is compatible.
*/
@@ -805,7 +805,7 @@ _cairo_cogl_journal_flush (cairo_cogl_surface_t *surface)
_cairo_path_fixed_approximate_clip_extents (&path->path, &extents);
/* TODO - maintain a fifo of the last 10 used clips with cached
- * primitives to see if we can avoid tesselating the path and
+ * primitives to see if we can avoid tessellating the path and
* uploading the vertices...
*/
#if 0
@@ -2789,7 +2789,7 @@ cairo_cogl_device_create (CoglContext *cogl_context)
ERROR:
g_free (dev);
- return NULL;
+ return _cairo_device_create_in_error (CAIRO_STATUS_DEVICE_ERROR);
}
slim_hidden_def (cairo_cogl_device_create);
diff --git a/src/cairo-cogl-utils-private.h b/src/cairo-cogl-utils-private.h
index ee77f3034..ee77f3034 100755..100644
--- a/src/cairo-cogl-utils-private.h
+++ b/src/cairo-cogl-utils-private.h
diff --git a/src/cairo-cogl-utils.c b/src/cairo-cogl-utils.c
index 4f02aaa52..4f02aaa52 100755..100644
--- a/src/cairo-cogl-utils.c
+++ b/src/cairo-cogl-utils.c
diff --git a/src/cairo-cogl.h b/src/cairo-cogl.h
index f270d74d3..f270d74d3 100755..100644
--- a/src/cairo-cogl.h
+++ b/src/cairo-cogl.h
diff --git a/src/cairo-color.c b/src/cairo-color.c
index 9c852559e..c2a11a177 100755..100644
--- a/src/cairo-color.c
+++ b/src/cairo-color.c
@@ -78,18 +78,13 @@ _cairo_stock_color (cairo_stock_t stock)
}
/* Convert a double in [0.0, 1.0] to an integer in [0, 65535]
- * The conversion is designed to divide the input range into 65536
- * equally-sized regions. This is achieved by multiplying by 65536 and
- * then special-casing the result of an input value of 1.0 so that it
- * maps to 65535 instead of 65536.
+ * The conversion is designed to choose the integer i such that
+ * i / 65535.0 is as close as possible to the input value.
*/
uint16_t
_cairo_color_double_to_short (double d)
{
- uint32_t i;
- i = (uint32_t) (d * 65536);
- i -= (i >> 16);
- return i;
+ return d * 65535.0 + 0.5;
}
static void
diff --git a/src/cairo-combsort-inline.h b/src/cairo-combsort-inline.h
index d359faeb5..d359faeb5 100755..100644
--- a/src/cairo-combsort-inline.h
+++ b/src/cairo-combsort-inline.h
diff --git a/src/cairo-compiler-private.h b/src/cairo-compiler-private.h
index f3e971ebb..216e71b4e 100755..100644
--- a/src/cairo-compiler-private.h
+++ b/src/cairo-compiler-private.h
@@ -221,16 +221,14 @@
be needed for GCC but it seems fine for now. */
#define CAIRO_ENSURE_UNIQUE \
do { \
- char func[] = __FUNCTION__; \
char file[] = __FILE__; \
__asm { \
__asm jmp __internal_skip_line_no \
- __asm _emit (__LINE__ & 0xff) \
- __asm _emit ((__LINE__>>8) & 0xff) \
- __asm _emit ((__LINE__>>16) & 0xff) \
- __asm _emit ((__LINE__>>24) & 0xff) \
- __asm lea eax, func \
- __asm lea eax, file \
+ __asm _emit (__COUNTER__ & 0xff) \
+ __asm _emit ((__COUNTER__>>8) & 0xff) \
+ __asm _emit ((__COUNTER__>>16) & 0xff)\
+ __asm _emit ((__COUNTER__>>24) & 0xff)\
+ __asm lea eax, dword ptr file \
__asm __internal_skip_line_no: \
}; \
} while (0)
diff --git a/src/cairo-composite-rectangles-private.h b/src/cairo-composite-rectangles-private.h
index 108137427..108137427 100755..100644
--- a/src/cairo-composite-rectangles-private.h
+++ b/src/cairo-composite-rectangles-private.h
diff --git a/src/cairo-composite-rectangles.c b/src/cairo-composite-rectangles.c
index f288bb785..2f0013fa7 100755..100644
--- a/src/cairo-composite-rectangles.c
+++ b/src/cairo-composite-rectangles.c
@@ -61,7 +61,7 @@ _cairo_composite_rectangles_check_lazy_init (cairo_composite_rectangles_t *exten
if (type == CAIRO_PATTERN_TYPE_SURFACE) {
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
- cairo_surface_t *pattern_surface = surface_pattern->surface;
+ cairo_surface_t *pattern_surface = pattern_surface = surface_pattern->surface;
/* XXX: both source and target are GL surface */
if (cairo_surface_get_type (pattern_surface) == CAIRO_SURFACE_TYPE_GL &&
@@ -87,7 +87,7 @@ _cairo_composite_reduce_pattern (const cairo_pattern_t *src,
if (dst->base.type == CAIRO_PATTERN_TYPE_SOLID)
return;
- dst->base.filter = _cairo_pattern_analyze_filter (&dst->base, NULL),
+ dst->base.filter = _cairo_pattern_analyze_filter (&dst->base);
tx = ty = 0;
if (_cairo_matrix_is_pixman_translation (&dst->base.matrix,
@@ -244,6 +244,13 @@ _cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents,
_cairo_clip_get_extents (extents->clip)))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
+ if (! _cairo_rectangle_intersect (&extents->bounded,
+ _cairo_clip_get_extents (extents->clip)) &&
+ extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
+ {
+ return CAIRO_INT_STATUS_NOTHING_TO_DO;
+ }
+
if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
_cairo_pattern_sampled_area (&extents->source_pattern.base,
&extents->bounded,
diff --git a/src/cairo-compositor-private.h b/src/cairo-compositor-private.h
index 3a461bf06..d4230b1bc 100755..100644
--- a/src/cairo-compositor-private.h
+++ b/src/cairo-compositor-private.h
@@ -242,18 +242,18 @@ struct cairo_traps_compositor {
int dst_y,
unsigned int width,
unsigned int height);
- cairo_int_status_t
- (*lerp_color_glyph) (void *_dst,
- cairo_surface_t *abstract_src,
- cairo_surface_t *abstract_mask,
- int src_x,
- int src_y,
- int mask_x,
- int mask_y,
- int dst_x,
- int dst_y,
- unsigned int width,
- unsigned int height);
+ cairo_int_status_t
+ (*lerp_color_glyph) (void *_dst,
+ cairo_surface_t *abstract_src,
+ cairo_surface_t *abstract_mask,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height);
cairo_int_status_t
(*composite_boxes) (void *surface,
diff --git a/src/cairo-compositor.c b/src/cairo-compositor.c
index 0c4d34cc0..0c4d34cc0 100755..100644
--- a/src/cairo-compositor.c
+++ b/src/cairo-compositor.c
diff --git a/src/cairo-contour-inline.h b/src/cairo-contour-inline.h
index 7972c1ac5..7972c1ac5 100755..100644
--- a/src/cairo-contour-inline.h
+++ b/src/cairo-contour-inline.h
diff --git a/src/cairo-contour-private.h b/src/cairo-contour-private.h
index 1dfc46f3a..1dfc46f3a 100755..100644
--- a/src/cairo-contour-private.h
+++ b/src/cairo-contour-private.h
diff --git a/src/cairo-contour.c b/src/cairo-contour.c
index d356f4f65..9ad75bdbf 100755..100644
--- a/src/cairo-contour.c
+++ b/src/cairo-contour.c
@@ -332,7 +332,6 @@ _cairo_contour_simplify (cairo_contour_t *contour, double tolerance)
}
/* stage2: polygon simplification using Douglas-Peucker */
- simplified = FALSE;
do {
last = &contour->chain.points[0];
iter_init (&furthest, contour);
diff --git a/src/cairo-convex-fill-private.h b/src/cairo-convex-fill-private.h
new file mode 100644
index 000000000..ba76045b3
--- /dev/null
+++ b/src/cairo-convex-fill-private.h
@@ -0,0 +1,112 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2014 Samsung Research America, Silicon Valley
+ *
+ * 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 Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Srikanth Chevalam<chevalam.s@samsung.com>
+ * Suyambulingam Rathinasamy<suyambu.rm@samsung.com>
+ * Henry Song <henry.song@samsung.com>
+ */
+#ifndef __CAIRO_CONVEX_FILL_H_
+#define __CAIRO_CONVEX_FILL_H_
+
+#include "cairo-box-inline.h"
+#include "cairo-list-inline.h"
+#include "cairo-stroke-dash-private.h"
+#include "cairo-slope-private.h"
+
+#define NUM_SPLINE_CALLS 64
+
+typedef struct cairo_convex_fill_closure {
+ cairo_status_t (*add_triangle_fan) (void *closure,
+ const cairo_point_t *points,
+ int npoints);
+ double tolerance;
+ cairo_point_t current_point;
+ cairo_point_t start_point;
+ void *closure;
+ unsigned int pcount;
+ unsigned int capacity;
+ cairo_bool_t midp_added;
+ cairo_point_t embedded_points[NUM_SPLINE_CALLS];
+ cairo_point_t *convex_points;
+} cairo_convex_fill_closure_t;
+
+typedef cairo_warn cairo_status_t
+(*cairo_convex_fill_closure_add_triangle_fan) (void *closure,
+ const cairo_point_t *points,
+ int npoints);
+
+cairo_status_t
+_cairo_convex_fill_spline_to (void *closure,
+ const cairo_point_t *point,
+ const cairo_slope_t *tangent);
+
+
+cairo_status_t
+_cairo_convex_fill_curve_to (void *closure,
+ const cairo_point_t *b,
+ const cairo_point_t *c,
+ const cairo_point_t *d);
+
+cairo_status_t
+_cairo_convex_fill_move_to (void *closure,
+ const cairo_point_t *point);
+
+cairo_status_t
+_cairo_path_fixed_fill_to_convex (cairo_convex_fill_closure_add_triangle_fan add_triangle_fan,
+ const cairo_path_fixed_t *path,
+ cairo_path_fixed_move_to_func_t *move_to,
+ cairo_path_fixed_line_to_func_t *line_to,
+ cairo_path_fixed_curve_to_func_t *curve_to,
+ cairo_path_fixed_close_path_func_t *close_path,
+ void *closure);
+
+
+cairo_status_t
+_cairo_path_fixed_convex_fill_interpret (const cairo_path_fixed_t *path,
+ cairo_path_fixed_move_to_func_t *move_to,
+ cairo_path_fixed_line_to_func_t *line_to,
+ cairo_path_fixed_curve_to_func_t *curve_to,
+ cairo_path_fixed_close_path_func_t *close_path,
+ void *closure);
+
+cairo_status_t
+_cairo_convex_fill_line_to (void *closure,
+ const cairo_point_t *point);
+
+cairo_status_t
+_cairo_convex_fill_close_path (void *closure);
+
+cairo_status_t
+_add_triangle (void *closure,
+ const cairo_point_t triangle[3]);
+
+#endif
diff --git a/src/cairo-convex-fill.c b/src/cairo-convex-fill.c
new file mode 100644
index 000000000..e5fefe315
--- /dev/null
+++ b/src/cairo-convex-fill.c
@@ -0,0 +1,219 @@
+/* cairo - a vector graphics library with display and print output
+*
+* Copyright © 2014 Samsung Research America, Silicon Valley
+*
+* 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 Red Hat, Inc.
+*
+* Contributor(s):
+* Srikanth Chevalam<chevalam.s@samsung.com>
+* Suyambulingam Rathinasamy<suyambu.rm@samsung.com>
+* Henry Song <henry.song@samsung.com>
+*/
+
+#include "cairo-convex-fill-private.h"
+#include <sys/time.h>
+
+cairo_status_t
+_add_triangle (void *closure,
+ const cairo_point_t* triangle)
+{
+ cairo_convex_fill_closure_t *filler = closure;
+ int required_space = 1;
+ if (! filler->midp_added)
+ required_space = 2;
+
+ if(filler->capacity < filler->pcount + required_space) {
+ filler->capacity += NUM_SPLINE_CALLS;
+ if (filler->convex_points == filler->embedded_points) {
+ filler->convex_points = _cairo_malloc_ab (filler->capacity, sizeof(cairo_point_t));
+ memcpy (filler->convex_points, filler->embedded_points, sizeof(cairo_point_t) * NUM_SPLINE_CALLS);
+ }
+ else
+ filler->convex_points = _cairo_realloc_ab (filler->convex_points, filler->capacity, sizeof (cairo_point_t));
+ }
+
+ if (! filler->midp_added) {
+ filler->convex_points[filler->pcount++] = filler->start_point;
+ filler->midp_added = TRUE;
+ }
+ filler->convex_points[filler->pcount++] = *triangle;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_convex_fill_spline_to (void *closure,
+ const cairo_point_t *point,
+ const cairo_slope_t *tangent)
+{
+ cairo_convex_fill_closure_t *filler = closure;
+ if (filler->current_point.x == point->x &&
+ filler->current_point.y == point->y)
+ return CAIRO_STATUS_SUCCESS;
+
+ if ((filler->current_point.x != point->x ||
+ filler->current_point.y != point->y))
+ _add_triangle (filler, point);
+
+ filler->current_point = *point;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+
+cairo_status_t
+_cairo_convex_fill_move_to (void *closure,
+ const cairo_point_t *point)
+{
+ cairo_convex_fill_closure_t *path = closure;
+ path->current_point = *point;
+ path->start_point = path->current_point;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_convex_fill_line_to (void *closure,
+ const cairo_point_t *point)
+{
+ cairo_convex_fill_closure_t *filler = closure;
+
+ _add_triangle(filler, point);
+
+ filler->current_point = *point;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_convex_fill_close_path (void *closure)
+{
+ cairo_convex_fill_closure_t *filler = closure;
+ _cairo_convex_fill_line_to (closure, &filler->start_point);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_path_fixed_fill_to_convex (cairo_convex_fill_closure_add_triangle_fan add_triangle_fan,
+ const cairo_path_fixed_t *path,
+ cairo_path_fixed_move_to_func_t *move_to,
+ cairo_path_fixed_line_to_func_t *line_to,
+ cairo_path_fixed_curve_to_func_t *curve_to,
+ cairo_path_fixed_close_path_func_t *close_path,
+ void *closure)
+{
+ cairo_convex_fill_closure_t *filler = closure ;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ filler->current_point = path->current_point;
+ filler->start_point = filler->current_point;
+ filler->add_triangle_fan = add_triangle_fan;
+ filler->pcount = 0 ;
+ filler->capacity = NUM_SPLINE_CALLS;
+ filler->convex_points = filler->embedded_points;
+ //filler->convex_points = _cairo_malloc_ab (filler->capacity, sizeof(cairo_point_t));
+ status = _cairo_path_fixed_convex_fill_interpret (path,
+ move_to,
+ line_to,
+ curve_to,
+ close_path,
+ filler);
+ return status;
+}
+
+cairo_status_t
+_cairo_convex_fill_curve_to (void *closure,
+ const cairo_point_t *b,
+ const cairo_point_t *c,
+ const cairo_point_t *d)
+{
+ cairo_convex_fill_closure_t *filler = closure;
+ cairo_spline_t spline;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ if (! _cairo_spline_init (&spline,
+ (cairo_spline_add_point_func_t) _cairo_convex_fill_spline_to,
+ filler,
+ &filler->current_point, b, c, d))
+ return _cairo_convex_fill_line_to (closure, d);
+
+ status = _cairo_spline_decompose (&spline, filler->tolerance);
+
+ if (unlikely (status))
+ return status;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_path_fixed_convex_fill_interpret (const cairo_path_fixed_t *path,
+ cairo_path_fixed_move_to_func_t *move_to,
+ cairo_path_fixed_line_to_func_t *line_to,
+ cairo_path_fixed_curve_to_func_t *curve_to,
+ cairo_path_fixed_close_path_func_t *close_path,
+ void *closure)
+{
+ const cairo_path_buf_t *buf;
+ cairo_status_t status;
+ cairo_convex_fill_closure_t *filler = closure;
+
+ cairo_path_foreach_buf_start (buf, path) {
+ const cairo_point_t *points = buf->points;
+ unsigned int i;
+
+ for (i = 0; i < buf->num_ops; i++) {
+ switch (buf->op[i]) {
+ case CAIRO_PATH_OP_MOVE_TO:
+ status = (*move_to) (closure, &points[0]);
+ points += 1;
+ break;
+ case CAIRO_PATH_OP_LINE_TO:
+ status = (*line_to) (closure, &points[0]);
+ points += 1;
+ break;
+ case CAIRO_PATH_OP_CURVE_TO:
+ status = (*curve_to) (closure, &points[0], &points[1], &points[2]);
+ points += 3;
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ case CAIRO_PATH_OP_CLOSE_PATH:
+ status = (*close_path) (closure);
+ break;
+ }
+
+ if (unlikely (status))
+ return status;
+ }
+ } cairo_path_foreach_buf_end (buf, path);
+
+ if (filler->pcount) {
+ filler->add_triangle_fan (filler->closure,
+ filler->convex_points,
+ filler->pcount);
+ }
+ if (filler->convex_points != filler->embedded_points)
+ free (filler->convex_points);
+
+ return status;
+}
diff --git a/src/cairo-damage-private.h b/src/cairo-damage-private.h
index 97b177e86..97b177e86 100755..100644
--- a/src/cairo-damage-private.h
+++ b/src/cairo-damage-private.h
diff --git a/src/cairo-damage.c b/src/cairo-damage.c
index 63191fee9..63191fee9 100755..100644
--- a/src/cairo-damage.c
+++ b/src/cairo-damage.c
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
index 33d46aa3f..33d46aa3f 100755..100644
--- a/src/cairo-debug.c
+++ b/src/cairo-debug.c
diff --git a/src/cairo-default-context-private.h b/src/cairo-default-context-private.h
index fd159b496..fd159b496 100755..100644
--- a/src/cairo-default-context-private.h
+++ b/src/cairo-default-context-private.h
diff --git a/src/cairo-default-context.c b/src/cairo-default-context.c
index b7a38d2f0..4b63d53be 100755..100644
--- a/src/cairo-default-context.c
+++ b/src/cairo-default-context.c
@@ -139,7 +139,6 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
cairo_surface_t *group_surface;
cairo_clip_t *clip;
cairo_status_t status;
-
clip = _cairo_gstate_get_clip (cr->gstate);
if (_cairo_clip_is_all_clipped (clip)) {
group_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
@@ -153,6 +152,11 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
parent_surface = _cairo_gstate_get_target (cr->gstate);
+ if (unlikely (parent_surface->status))
+ return parent_surface->status;
+ if (unlikely (parent_surface->finished))
+ return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
+
/* Get the extents that we'll use in creating our new group surface */
bounded = _cairo_surface_get_extents (parent_surface, &extents);
if (clip)
@@ -165,11 +169,11 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
group_surface = cairo_recording_surface_create (content, NULL);
extents.x = extents.y = 0;
} else {
- group_surface = _cairo_surface_create_similar_solid (parent_surface,
- content,
- extents.width,
- extents.height,
- CAIRO_COLOR_TRANSPARENT);
+ group_surface = _cairo_surface_create_scratch (parent_surface,
+ content,
+ extents.width,
+ extents.height,
+ CAIRO_COLOR_TRANSPARENT);
}
status = group_surface->status;
if (unlikely (status))
@@ -184,6 +188,10 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
parent_surface->device_transform.x0 - extents.x,
parent_surface->device_transform.y0 - extents.y);
+ cairo_surface_set_device_scale (group_surface,
+ parent_surface->device_transform.xx,
+ parent_surface->device_transform.yy);
+
/* If we have a current path, we need to adjust it to compensate for
* the device offset just applied. */
_cairo_path_fixed_translate (cr->path,
@@ -209,7 +217,8 @@ _cairo_default_context_pop_group (void *abstract_cr)
cairo_default_context_t *cr = abstract_cr;
cairo_surface_t *group_surface;
cairo_pattern_t *group_pattern;
- cairo_matrix_t group_matrix, device_transform_matrix;
+ cairo_surface_t *parent_surface;
+ cairo_matrix_t group_matrix;
cairo_status_t status;
/* Verify that we are at the right nesting level */
@@ -223,29 +232,21 @@ _cairo_default_context_pop_group (void *abstract_cr)
status = _cairo_gstate_restore (&cr->gstate, &cr->gstate_freelist);
assert (status == CAIRO_STATUS_SUCCESS);
+ parent_surface = _cairo_gstate_get_target (cr->gstate);
+
group_pattern = cairo_pattern_create_for_surface (group_surface);
status = group_pattern->status;
if (unlikely (status))
goto done;
_cairo_gstate_get_matrix (cr->gstate, &group_matrix);
- /* Transform by group_matrix centered around device_transform so that when
- * we call _cairo_gstate_copy_transformed_pattern the result is a pattern
- * with a matrix equivalent to the device_transform of group_surface. */
- if (_cairo_surface_has_device_transform (group_surface)) {
- cairo_pattern_set_matrix (group_pattern, &group_surface->device_transform);
- _cairo_pattern_transform (group_pattern, &group_matrix);
- _cairo_pattern_transform (group_pattern, &group_surface->device_transform_inverse);
- } else {
- cairo_pattern_set_matrix (group_pattern, &group_matrix);
- }
+ cairo_pattern_set_matrix (group_pattern, &group_matrix);
/* If we have a current path, we need to adjust it to compensate for
* the device offset just removed. */
- cairo_matrix_multiply (&device_transform_matrix,
- &_cairo_gstate_get_target (cr->gstate)->device_transform,
- &group_surface->device_transform_inverse);
- _cairo_path_fixed_transform (cr->path, &device_transform_matrix);
+ _cairo_path_fixed_translate (cr->path,
+ _cairo_fixed_from_int (parent_surface->device_transform.x0 - group_surface->device_transform.x0),
+ _cairo_fixed_from_int (parent_surface->device_transform.y0 - group_surface->device_transform.y0));
done:
cairo_surface_destroy (group_surface);
@@ -267,7 +268,7 @@ _current_source_matches_solid (const cairo_pattern_t *pattern,
double red,
double green,
double blue,
- double alpha)
+ double alpha)
{
cairo_color_t color;
@@ -299,11 +300,8 @@ _cairo_default_context_set_source_rgba (void *abstract_cr, double red, double gr
_cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
pattern = cairo_pattern_create_rgba (red, green, blue, alpha);
- if (unlikely (pattern->status)) {
- status = pattern->status;
- cairo_pattern_destroy (pattern);
- return pattern->status;
- }
+ if (unlikely (pattern->status))
+ return pattern->status;
status = _cairo_default_context_set_source (cr, pattern);
cairo_pattern_destroy (pattern);
@@ -326,11 +324,8 @@ _cairo_default_context_set_source_surface (void *abstract_cr,
_cairo_default_context_set_source (cr, (cairo_pattern_t *) &_cairo_pattern_black);
pattern = cairo_pattern_create_for_surface (surface);
- if (unlikely (pattern->status)) {
- status = pattern->status;
- cairo_pattern_destroy (pattern);
- return status;
- }
+ if (unlikely (pattern->status))
+ return pattern->status;
cairo_matrix_init_translate (&matrix, -x, -y);
cairo_pattern_set_matrix (pattern, &matrix);
@@ -711,7 +706,6 @@ _cairo_default_context_line_to (void *abstract_cr, double x, double y)
{
cairo_default_context_t *cr = abstract_cr;
cairo_fixed_t x_fixed, y_fixed;
-
_cairo_gstate_user_to_backend (cr->gstate, &x, &y);
x_fixed = _cairo_fixed_from_double (x);
y_fixed = _cairo_fixed_from_double (y);
@@ -729,7 +723,6 @@ _cairo_default_context_curve_to (void *abstract_cr,
cairo_fixed_t x1_fixed, y1_fixed;
cairo_fixed_t x2_fixed, y2_fixed;
cairo_fixed_t x3_fixed, y3_fixed;
-
_cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
_cairo_gstate_user_to_backend (cr->gstate, &x2, &y2);
_cairo_gstate_user_to_backend (cr->gstate, &x3, &y3);
@@ -758,13 +751,16 @@ _cairo_default_context_arc (void *abstract_cr,
cairo_default_context_t *cr = abstract_cr;
cairo_status_t status;
+ cairo_fixed_t x_fixed, y_fixed;
+
+ cairo_bool_t path_empty = _cairo_path_fixed_is_empty (cr->path);
+
/* Do nothing, successfully, if radius is <= 0 */
if (radius <= 0.0) {
- cairo_fixed_t x_fixed, y_fixed;
-
_cairo_gstate_user_to_backend (cr->gstate, &xc, &yc);
x_fixed = _cairo_fixed_from_double (xc);
y_fixed = _cairo_fixed_from_double (yc);
+
status = _cairo_path_fixed_line_to (cr->path, x_fixed, y_fixed);
if (unlikely (status))
return status;
@@ -788,6 +784,16 @@ _cairo_default_context_arc (void *abstract_cr,
else
_cairo_arc_path_negative (&cr->base, xc, yc, radius, angle1, angle2);
+ if (path_empty) {
+ x_fixed = _cairo_fixed_from_double (xc + radius * cos (angle1));
+ y_fixed = _cairo_fixed_from_double (yc + radius * sin (angle1));
+ cr->path->start_point.x = x_fixed;
+ cr->path->start_point.y = y_fixed;
+ cr->path->is_convex = TRUE;
+ }
+ else
+ cr->path->is_convex = FALSE;
+
return CAIRO_STATUS_SUCCESS; /* any error will have already been set on cr */
}
@@ -885,6 +891,161 @@ _cairo_default_context_rectangle (void *abstract_cr,
return _cairo_default_context_close_path (cr);
}
+static cairo_status_t
+_cairo_default_context_rounded_rectangle_curve_to (void *abstract_cr,
+ double xc, double yc,
+ double radius,
+ double angle_a,
+ double angle_b)
+{
+ double sin_a, cos_a;
+ double sin_b, cos_b;
+ double h;
+
+ sin_a = radius * sin (angle_a);
+ cos_a = radius * cos (angle_a);
+ sin_b = radius * sin (angle_b);
+ cos_b = radius * cos (angle_b);
+ h = 4.0/3.0 * tan ((angle_b - angle_a) / 4.0);
+ return _cairo_default_context_curve_to (abstract_cr,
+ xc + cos_a - h * sin_a,
+ yc + sin_a + h * cos_a,
+ xc + cos_b + h * sin_b,
+ yc + sin_b - h * cos_b,
+ xc + cos_b, yc + sin_b);
+}
+
+static cairo_status_t
+_cairo_default_context_rounded_rectangle (void *abstract_cr,
+ double x, double y,
+ double width, double height,
+ double r_top_left, double r_top_right,
+ double r_bottom_left, double r_bottom_right)
+{
+ cairo_default_context_t *cr = abstract_cr;
+ cairo_status_t status;
+ double temp_scale, scale = 1.0;
+ double length;
+ cairo_bool_t path_empty;
+ double x_start, y_start;
+
+ if (width <= 0.0 || height <= 0.0)
+ return CAIRO_STATUS_SUCCESS;
+
+ path_empty = _cairo_path_fixed_is_empty (cr->path);
+
+ if (r_top_left <= 0.0)
+ r_top_left = 0.0;
+ if (r_top_right <= 0.0)
+ r_top_left = 0.0;
+ if (r_bottom_left < 0.0)
+ r_bottom_left = 0.0;
+ if (r_bottom_right <= 0.0)
+ r_bottom_right = 0.0;
+
+ length = r_top_left + r_top_right;
+ if (length > width) {
+ temp_scale = width / length;
+ scale = temp_scale;
+ }
+ length = r_top_right + r_bottom_right;
+ if (length > height) {
+ temp_scale = height / length;
+ if (temp_scale < scale)
+ scale = temp_scale;
+ }
+ length = r_bottom_right + r_bottom_left;
+ if (length > width) {
+ temp_scale = width / length;
+ if (temp_scale < scale)
+ scale = temp_scale;
+ }
+ length = r_bottom_left + r_top_left;
+ if (length > height) {
+ temp_scale = height / length;
+ if (temp_scale < scale)
+ scale = temp_scale;
+ }
+
+ if (scale != 0) {
+ r_top_left *= scale;
+ r_top_right *= scale;
+ r_bottom_left *= scale;
+ r_bottom_right *= scale;
+ }
+
+ status = _cairo_default_context_move_to (cr, x, y + r_top_left);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rounded_rectangle_curve_to (cr,
+ x + r_top_left,
+ y + r_top_left,
+ r_top_left,
+ M_PI,
+ 1.5 * M_PI);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rel_line_to (cr,
+ width - r_top_left - r_top_right,
+ 0);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rounded_rectangle_curve_to (cr,
+ x + width - r_top_right,
+ y + r_top_right,
+ r_top_right,
+ 1.5 *M_PI,
+ 2.0 * M_PI);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rel_line_to (cr, 0, height - r_top_right - r_bottom_right);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rounded_rectangle_curve_to (cr,
+ x + width - r_bottom_right,
+ y + height - r_bottom_right,
+ r_bottom_right,
+ 0,
+ 0.5 * M_PI);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rel_line_to (cr, -width + r_bottom_right + r_bottom_left, 0);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_rounded_rectangle_curve_to (cr,
+ x + r_bottom_left,
+ y + height - r_bottom_left,
+ r_bottom_left,
+ 0.5 * M_PI,
+ M_PI);
+ if (unlikely (status))
+ return status;
+
+ status = _cairo_default_context_close_path (cr);
+ if (unlikely (status))
+ return status;
+
+ if (path_empty) {
+ x_start = x;
+ y_start = y + r_top_left;
+ _cairo_gstate_user_to_backend (cr->gstate, &x_start, &y_start);
+ cr->path->start_point.x = _cairo_fixed_from_double (x_start);
+ cr->path->start_point.y = _cairo_fixed_from_double (y_start);
+ cr->path->is_convex = TRUE;
+ }
+ else
+ cr->path->is_convex = FALSE;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
static void
_cairo_default_context_path_extents (void *abstract_cr,
double *x1,
@@ -950,8 +1111,12 @@ _cairo_default_context_append_path (void *abstract_cr,
const cairo_path_t *path)
{
cairo_default_context_t *cr = abstract_cr;
+ cairo_bool_t can_apply_convex = _cairo_path_fixed_is_empty (cr->path);
- return _cairo_path_append_to_context (path, &cr->base);
+ cairo_status_t status = _cairo_path_append_to_context (path, &cr->base);
+ if (can_apply_convex && path->is_convex)
+ cr->path->is_convex = path->is_convex;
+ return status;
}
static cairo_status_t
@@ -1055,7 +1220,7 @@ _cairo_default_context_fill (void *abstract_cr)
{
cairo_default_context_t *cr = abstract_cr;
cairo_status_t status;
-
+
status = _cairo_gstate_fill (cr->gstate, cr->path);
if (unlikely (status))
return status;
@@ -1297,7 +1462,6 @@ _cairo_default_context_glyphs (void *abstract_cr,
cairo_glyph_text_info_t *info)
{
cairo_default_context_t *cr = abstract_cr;
-
return _cairo_gstate_show_text_glyphs (cr->gstate, glyphs, num_glyphs, info);
}
@@ -1307,7 +1471,6 @@ _cairo_default_context_glyph_path (void *abstract_cr,
int num_glyphs)
{
cairo_default_context_t *cr = abstract_cr;
-
return _cairo_gstate_glyph_path (cr->gstate,
glyphs, num_glyphs,
cr->path);
@@ -1320,7 +1483,6 @@ _cairo_default_context_glyph_extents (void *abstract_cr,
cairo_text_extents_t *extents)
{
cairo_default_context_t *cr = abstract_cr;
-
return _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents);
}
@@ -1458,6 +1620,7 @@ static const cairo_backend_t _cairo_default_context_backend = {
_cairo_default_context_close_path,
_cairo_default_context_arc,
_cairo_default_context_rectangle,
+ _cairo_default_context_rounded_rectangle,
_cairo_default_context_path_extents,
_cairo_default_context_has_current_point,
_cairo_default_context_get_current_point,
diff --git a/src/cairo-deflate-stream.c b/src/cairo-deflate-stream.c
index ae23bda94..ae23bda94 100755..100644
--- a/src/cairo-deflate-stream.c
+++ b/src/cairo-deflate-stream.c
diff --git a/src/cairo-deprecated.h b/src/cairo-deprecated.h
index 7a56aadbf..7a56aadbf 100755..100644
--- a/src/cairo-deprecated.h
+++ b/src/cairo-deprecated.h
diff --git a/src/cairo-device-private.h b/src/cairo-device-private.h
index 1c687d2fe..1c687d2fe 100755..100644
--- a/src/cairo-device-private.h
+++ b/src/cairo-device-private.h
diff --git a/src/cairo-device.c b/src/cairo-device.c
index e845912a3..b4d1f8422 100755..100644
--- a/src/cairo-device.c
+++ b/src/cairo-device.c
@@ -159,6 +159,7 @@ _cairo_device_create_in_error (cairo_status_t status)
case CAIRO_STATUS_INVALID_CONTENT:
case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
case CAIRO_STATUS_DEVICE_FINISHED:
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_device_t *) &_nil_device;
@@ -345,7 +346,7 @@ cairo_device_destroy (cairo_device_t *device)
while (! cairo_list_is_empty (&device->shadow_caches)) {
cairo_shadow_cache_t *shadow;
- shadow = cairo_list_first_entry (&device->shadow_caches,
+ shadow = cairo_list_first_entry (&device->shadow_caches,
cairo_shadow_cache_t,
link);
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index 16e367af8..5ac64ba98 100755..100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -197,7 +197,7 @@ _cairo_dfb_surface_map_to_image (void *abstract_surface,
_cairo_image_surface_init (&surface->image, image, surface->image.pixman_format);
}
- return _cairo_surface_map_to_image (&surface->image.base, extents);
+ return _cairo_image_surface_map_to_image (&surface->image.base, extents);
}
static cairo_int_status_t
@@ -205,7 +205,7 @@ _cairo_dfb_surface_unmap_image (void *abstract_surface,
cairo_image_surface_t *image)
{
cairo_dfb_surface_t *surface = abstract_surface;
- return _cairo_surface_unmap_image (&surface->image.base, image);
+ return _cairo_image_surface_unmap_image (&surface->image.base, image);
}
static cairo_status_t
diff --git a/src/cairo-directfb.h b/src/cairo-directfb.h
index e3d818c66..e3d818c66 100755..100644
--- a/src/cairo-directfb.h
+++ b/src/cairo-directfb.h
diff --git a/src/cairo-drm.h b/src/cairo-drm.h
index 907610dcd..907610dcd 100755..100644
--- a/src/cairo-drm.h
+++ b/src/cairo-drm.h
diff --git a/src/cairo-egl-context.c b/src/cairo-egl-context.c
index fa52a04ba..5b67d4b3c 100755..100644
--- a/src/cairo-egl-context.c
+++ b/src/cairo-egl-context.c
@@ -93,7 +93,6 @@ typedef struct _cairo_egl_context {
EGLSurface dummy_surface;
EGLSurface current_surface;
- EGLDisplay previous_display;
EGLContext previous_context;
EGLSurface previous_surface;
} cairo_egl_context_t;
@@ -110,8 +109,7 @@ _context_acquisition_changed_egl_state (cairo_egl_context_t *ctx,
EGLSurface current_surface)
{
return ctx->previous_context != ctx->context ||
- ctx->previous_surface != current_surface ||
- ctx->previous_display != ctx->display;
+ ctx->previous_surface != current_surface;
}
static EGLSurface
@@ -128,19 +126,8 @@ _egl_get_current_surface (cairo_egl_context_t *ctx)
static void
_egl_query_current_state (cairo_egl_context_t *ctx)
{
- ctx->previous_surface = eglGetCurrentSurface (EGL_DRAW);
ctx->previous_context = eglGetCurrentContext ();
- ctx->previous_display = eglGetCurrentDisplay ();
-
- /* If any of the values were none, assume they are all none. Not all
- drivers seem well behaved when it comes to using these values across
- multiple threads. */
- if (ctx->previous_surface == EGL_NO_SURFACE ||
- ctx->previous_context == EGL_NO_CONTEXT || ctx->previous_display == EGL_NO_DISPLAY) {
- ctx->previous_surface = EGL_NO_SURFACE;
- ctx->previous_context = EGL_NO_CONTEXT;
- ctx->previous_display = EGL_NO_DISPLAY;
- }
+ ctx->previous_surface = eglGetCurrentSurface (EGL_DRAW);
}
static void
@@ -272,7 +259,7 @@ _cairo_egl_get_proc_address (void *data, const char *name)
};
for (i = 0; func_map[i].name; i++) {
- if (! strncmp (func_map[i].name, name, strlen(name)))
+ if (! strcmp (func_map[i].name, name))
return func_map[i].func;
}
@@ -352,6 +339,12 @@ cairo_egl_device_create (EGLDisplay dpy, EGLContext egl)
return _cairo_gl_context_create_in_error (status);
}
+ /* Tune the default VBO size to reduce overhead on embedded devices.
+ * This smaller size means that flushing needs to be done more often,
+ * but it is less demanding of scarce memory on embedded devices.
+ */
+ ctx->base.vbo_size = 16*1024;
+
eglMakeCurrent (dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
ctx->current_surface = EGL_NO_SURFACE;
diff --git a/src/cairo-error-inline.h b/src/cairo-error-inline.h
index 9126c5e61..9126c5e61 100755..100644
--- a/src/cairo-error-inline.h
+++ b/src/cairo-error-inline.h
diff --git a/src/cairo-error-private.h b/src/cairo-error-private.h
index ea9c2ea31..178078ad6 100755..100644
--- a/src/cairo-error-private.h
+++ b/src/cairo-error-private.h
@@ -46,10 +46,13 @@
CAIRO_BEGIN_DECLS
-/* Sure wish C had a real enum type so that this would be distinct
+/* _cairo_int_status: internal status
+ *
+ * Sure wish C had a real enum type so that this would be distinct
* from #cairo_status_t. Oh well, without that, I'll use this bogus 100
* offset. We want to keep it fit in int8_t as the compiler may choose
- * that for #cairo_status_t */
+ * that for #cairo_status_t
+ */
enum _cairo_int_status {
CAIRO_INT_STATUS_SUCCESS = 0,
@@ -90,6 +93,7 @@ enum _cairo_int_status {
CAIRO_INT_STATUS_DEVICE_ERROR,
CAIRO_INT_STATUS_INVALID_MESH_CONSTRUCTION,
CAIRO_INT_STATUS_DEVICE_FINISHED,
+ CAIRO_INT_STATUS_JBIG2_GLOBAL_MISSING,
CAIRO_INT_STATUS_LAST_STATUS,
diff --git a/src/cairo-error.c b/src/cairo-error.c
index 1b9bd76be..1b9bd76be 100755..100644
--- a/src/cairo-error.c
+++ b/src/cairo-error.c
diff --git a/src/cairo-evas-gl-context.c b/src/cairo-evas-gl-context.c
index 3f256cbc2..3cd4e0e0b 100755..100644
--- a/src/cairo-evas-gl-context.c
+++ b/src/cairo-evas-gl-context.c
@@ -180,7 +180,7 @@ _cairo_evas_gl_get_proc_addr (void *data, const char *name)
}
return evas_gl_proc_address_get (gl, name);
-}
+}
static cairo_bool_t
_context_acquisition_changed_evas_gl_state (cairo_evas_gl_context_t *ctx,
@@ -204,8 +204,8 @@ _evas_gl_get_current_surface (cairo_evas_gl_context_t *ctx)
static void
_evas_gl_query_current_state (cairo_evas_gl_context_t *ctx)
{
- ctx->queried_context = evas_gl_current_context_get (ctx->evas_gl);
- ctx->current_surface = evas_gl_current_surface_get (ctx->evas_gl);
+ ctx->queried_context = evas_gl_current_context_get (ctx->evas_gl);
+ ctx->current_surface = evas_gl_current_surface_get (ctx->evas_gl);
}
static void
@@ -394,13 +394,13 @@ cairo_gl_surface_create_for_evas_gl (cairo_device_t *device,
static cairo_bool_t is_evas_gl_device (cairo_device_t *device)
{
- return (device->backend != NULL &&
+ return (device->backend != NULL &&
device->backend->type == CAIRO_DEVICE_TYPE_GL);
}
static cairo_evas_gl_context_t *to_evas_gl_context (cairo_device_t *device)
{
- return (cairo_evas_gl_context_t *) device;
+ return (cairo_evas_gl_context_t *) device;
}
cairo_public Evas_GL *
@@ -412,7 +412,7 @@ cairo_evas_gl_device_get_gl (cairo_device_t *device)
return NULL;
}
- if (! is_evas_gl_device (device)) {
+ if (! is_evas_gl_device (device)) {
_cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
return NULL;
}
diff --git a/src/cairo-fallback-compositor.c b/src/cairo-fallback-compositor.c
index 3f6199fe2..3f6199fe2 100755..100644
--- a/src/cairo-fallback-compositor.c
+++ b/src/cairo-fallback-compositor.c
diff --git a/src/cairo-features-uninstalled.pc.in b/src/cairo-features-uninstalled.pc.in
index b9cd9d3ad..b9cd9d3ad 100755..100644
--- a/src/cairo-features-uninstalled.pc.in
+++ b/src/cairo-features-uninstalled.pc.in
diff --git a/src/cairo-features.pc.in b/src/cairo-features.pc.in
index 9a4b657c8..9a4b657c8 100755..100644
--- a/src/cairo-features.pc.in
+++ b/src/cairo-features.pc.in
diff --git a/src/cairo-filters-private.h b/src/cairo-filters-private.h
index 89b7037d6..89b7037d6 100755..100644
--- a/src/cairo-filters-private.h
+++ b/src/cairo-filters-private.h
diff --git a/src/cairo-filters.c b/src/cairo-filters.c
index dfacda58b..dfacda58b 100755..100644
--- a/src/cairo-filters.c
+++ b/src/cairo-filters.c
diff --git a/src/cairo-fixed-private.h b/src/cairo-fixed-private.h
index b6cc6be7d..9ff8f7503 100755..100644
--- a/src/cairo-fixed-private.h
+++ b/src/cairo-fixed-private.h
@@ -40,12 +40,13 @@
#include "cairo-fixed-type-private.h"
#include "cairo-wideint-private.h"
+#include "cairoint.h"
/* Implementation */
#if (CAIRO_FIXED_BITS != 32)
# error CAIRO_FIXED_BITS must be 32, and the type must be a 32-bit type.
-# error To remove this limitation, you will have to fix the tesselator.
+# error To remove this limitation, you will have to fix the tessellator.
#endif
#define CAIRO_FIXED_ONE ((cairo_fixed_t)(1 << CAIRO_FIXED_FRAC_BITS))
@@ -311,7 +312,7 @@ _cairo_fixed_mul_div_floor (cairo_fixed_t a, cairo_fixed_t b, cairo_fixed_t c)
return _cairo_int64_32_div (_cairo_int32x32_64_mul (a, b), c);
}
-
+/* compute y from x so that (x,y), p1, and p2 are collinear */
static inline cairo_fixed_t
_cairo_edge_compute_intersection_y_for_x (const cairo_point_t *p1,
const cairo_point_t *p2,
@@ -332,6 +333,7 @@ _cairo_edge_compute_intersection_y_for_x (const cairo_point_t *p1,
return y;
}
+/* compute x from y so that (x,y), p1, and p2 are collinear */
static inline cairo_fixed_t
_cairo_edge_compute_intersection_x_for_y (const cairo_point_t *p1,
const cairo_point_t *p2,
@@ -352,6 +354,40 @@ _cairo_edge_compute_intersection_x_for_y (const cairo_point_t *p1,
return x;
}
+/* Intersect two segments based on the algorithm described at
+ * http://paulbourke.net/geometry/pointlineplane/. This implementation
+ * uses floating point math. */
+static inline cairo_bool_t
+_slow_segment_intersection (const cairo_point_t *seg1_p1,
+ const cairo_point_t *seg1_p2,
+ const cairo_point_t *seg2_p1,
+ const cairo_point_t *seg2_p2,
+ cairo_point_t *intersection)
+{
+ double denominator, u_a, u_b;
+ double seg1_dx, seg1_dy, seg2_dx, seg2_dy, seg_start_dx, seg_start_dy;
+
+ seg1_dx = _cairo_fixed_to_double (seg1_p2->x - seg1_p1->x);
+ seg1_dy = _cairo_fixed_to_double (seg1_p2->y - seg1_p1->y);
+ seg2_dx = _cairo_fixed_to_double (seg2_p2->x - seg2_p1->x);
+ seg2_dy = _cairo_fixed_to_double (seg2_p2->y - seg2_p1->y);
+ denominator = (seg2_dy * seg1_dx) - (seg2_dx * seg1_dy);
+ if (denominator == 0)
+ return FALSE;
+
+ seg_start_dx = _cairo_fixed_to_double (seg1_p1->x - seg2_p1->x);
+ seg_start_dy = _cairo_fixed_to_double (seg1_p1->y - seg2_p1->y);
+ u_a = ((seg2_dx * seg_start_dy) - (seg2_dy * seg_start_dx)) / denominator;
+ u_b = ((seg1_dx * seg_start_dy) - (seg1_dy * seg_start_dx)) / denominator;
+
+ if (u_a <= 0 || u_a >= 1 || u_b <= 0 || u_b >= 1)
+ return FALSE;
+
+ intersection->x = seg1_p1->x + _cairo_fixed_from_double ((u_a * seg1_dx));
+ intersection->y = seg1_p1->y + _cairo_fixed_from_double ((u_a * seg1_dy));
+ return TRUE;
+}
+
#else
# error Please define multiplication and other operands for your fixed-point type size
#endif
diff --git a/src/cairo-fixed-type-private.h b/src/cairo-fixed-type-private.h
index 2bbd5f786..e9f26f615 100755..100644
--- a/src/cairo-fixed-type-private.h
+++ b/src/cairo-fixed-type-private.h
@@ -50,7 +50,7 @@ typedef cairo_int128_t cairo_fixed_64_64_t;
typedef cairo_int128_t cairo_fixed_96_32_t;
/* Eventually, we should allow changing this, but I think
- * there are some assumptions in the tesselator about the
+ * there are some assumptions in the tessellator about the
* size of a fixed type. For now, it must be 32.
*/
#define CAIRO_FIXED_BITS 32
diff --git a/src/cairo-fixed.c b/src/cairo-fixed.c
index 03e055923..03e055923 100755..100644
--- a/src/cairo-fixed.c
+++ b/src/cairo-fixed.c
diff --git a/src/cairo-font-face-twin-data.c b/src/cairo-font-face-twin-data.c
index ff09cb2be..ff09cb2be 100755..100644
--- a/src/cairo-font-face-twin-data.c
+++ b/src/cairo-font-face-twin-data.c
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 22f87394a..22f87394a 100755..100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
diff --git a/src/cairo-font-face.c b/src/cairo-font-face.c
index b93bd8caa..3bcd2a1e6 100755..100644
--- a/src/cairo-font-face.c
+++ b/src/cairo-font-face.c
@@ -115,7 +115,7 @@ cairo_font_face_t *
cairo_font_face_reference (cairo_font_face_t *font_face)
{
if (font_face == NULL ||
- CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
+ CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return font_face;
/* We would normally assert that we have a reference here but we
@@ -128,6 +128,28 @@ cairo_font_face_reference (cairo_font_face_t *font_face)
}
slim_hidden_def (cairo_font_face_reference);
+static inline cairo_bool_t
+__put(cairo_reference_count_t *v)
+{
+ int c, old;
+
+ c = CAIRO_REFERENCE_COUNT_GET_VALUE(v);
+ while (c != 1 && (old = _cairo_atomic_int_cmpxchg_return_old(&v->ref_count, c, c - 1)) != c)
+ c = old;
+
+ return c != 1;
+}
+
+cairo_bool_t
+_cairo_font_face_destroy (void *abstract_face)
+{
+#if 0 /* Nothing needs to be done, we can just drop the last reference */
+ cairo_font_face_t *font_face = abstract_face;
+ return _cairo_reference_count_dec_and_test (&font_face->ref_count);
+#endif
+ return TRUE;
+}
+
/**
* cairo_font_face_destroy:
* @font_face: a #cairo_font_face_t
@@ -142,22 +164,19 @@ void
cairo_font_face_destroy (cairo_font_face_t *font_face)
{
if (font_face == NULL ||
- CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
+ CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return;
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count));
- if (! _cairo_reference_count_dec_and_test (&font_face->ref_count))
- return;
-
- if (font_face->backend->destroy)
- font_face->backend->destroy (font_face);
-
/* We allow resurrection to deal with some memory management for the
* FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
* need to effectively mutually reference each other
*/
- if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count))
+ if (__put (&font_face->ref_count))
+ return;
+
+ if (! font_face->backend->destroy (font_face))
return;
_cairo_user_data_array_fini (&font_face->user_data);
@@ -201,7 +220,7 @@ unsigned int
cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
{
if (font_face == NULL ||
- CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
+ CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
return 0;
return CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->ref_count);
@@ -309,10 +328,11 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
- if (! _cairo_reference_count_dec_and_test (&unscaled_font->ref_count))
+ if (__put (&unscaled_font->ref_count))
return;
- unscaled_font->backend->destroy (unscaled_font);
+ if (! unscaled_font->backend->destroy (unscaled_font))
+ return;
free (unscaled_font);
}
diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c
index 7b26853ad..d8883a5b5 100755..100644
--- a/src/cairo-font-options.c
+++ b/src/cairo-font-options.c
@@ -73,7 +73,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->color = CAIRO_FONT_COLOR_DEFAULT;
+ options->color = CAIRO_FONT_COLOR_DEFAULT;
}
void
@@ -86,7 +86,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->color = other->color;
+ options->color = other->color;
}
/**
@@ -228,7 +228,7 @@ 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->color != CAIRO_FONT_COLOR_DEFAULT)
+ if (other->color != CAIRO_FONT_COLOR_DEFAULT)
options->color = other->color;
}
slim_hidden_def (cairo_font_options_merge);
@@ -264,7 +264,7 @@ cairo_font_options_equal (const 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->color == other->color);
+ options->color == other->color);
}
slim_hidden_def (cairo_font_options_equal);
@@ -293,7 +293,7 @@ cairo_font_options_hash (const cairo_font_options_t *options)
(options->lcd_filter << 8) |
(options->hint_style << 12) |
(options->hint_metrics << 16) |
- (options->color << 20));
+ (options->color << 20));
}
slim_hidden_def (cairo_font_options_hash);
@@ -539,22 +539,23 @@ cairo_font_options_get_hint_metrics (const cairo_font_options_t *options)
return options->hint_metrics;
}
+
void
cairo_font_options_set_font_color (cairo_font_options_t *options,
- cairo_font_color_t font_color)
+ cairo_font_color_t font_color)
{
- if (cairo_font_options_status (options))
+ if (cairo_font_options_status (options))
return;
- options->color = font_color;
+ options->color = font_color;
}
slim_hidden_def (cairo_font_options_set_font_color);
cairo_font_color_t
cairo_font_options_get_font_color (const cairo_font_options_t *options)
{
- if (cairo_font_options_status ((cairo_font_options_t *) options))
+ if (cairo_font_options_status ((cairo_font_options_t *) options))
return CAIRO_FONT_COLOR_DEFAULT;
- return options->color;
+ return options->color;
}
diff --git a/src/cairo-fontconfig-private.h b/src/cairo-fontconfig-private.h
index ea873abe7..ea873abe7 100755..100644
--- a/src/cairo-fontconfig-private.h
+++ b/src/cairo-fontconfig-private.h
diff --git a/src/cairo-freed-pool-private.h b/src/cairo-freed-pool-private.h
index 0ec6de3d1..0ec6de3d1 100755..100644
--- a/src/cairo-freed-pool-private.h
+++ b/src/cairo-freed-pool-private.h
diff --git a/src/cairo-freed-pool.c b/src/cairo-freed-pool.c
index cfdc8e96b..cfdc8e96b 100755..100644
--- a/src/cairo-freed-pool.c
+++ b/src/cairo-freed-pool.c
diff --git a/src/cairo-freelist-private.h b/src/cairo-freelist-private.h
index 8fe6516f3..8fe6516f3 100755..100644
--- a/src/cairo-freelist-private.h
+++ b/src/cairo-freelist-private.h
diff --git a/src/cairo-freelist-type-private.h b/src/cairo-freelist-type-private.h
index 4dd056461..4dd056461 100755..100644
--- a/src/cairo-freelist-type-private.h
+++ b/src/cairo-freelist-type-private.h
diff --git a/src/cairo-freelist.c b/src/cairo-freelist.c
index d596eab81..d596eab81 100755..100644
--- a/src/cairo-freelist.c
+++ b/src/cairo-freelist.c
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 43df78e0b..868ccc2c8 100755..100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -45,6 +45,7 @@
#include "cairo-image-surface-private.h"
#include "cairo-ft-private.h"
#include "cairo-pattern-private.h"
+#include "cairo-pixman-private.h"
#include <float.h>
@@ -54,11 +55,11 @@
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_IMAGE_H
+#include FT_BITMAP_H
#include FT_TRUETYPE_TABLES_H
#include FT_XFREE86_H
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
#include FT_SYNTHESIS_H
-#define USE_FT_OUTLINE_EMBOLDEN 1
#endif
#if HAVE_FT_LIBRARY_SETLCDFILTER
@@ -587,23 +588,20 @@ _cairo_ft_unscaled_font_create_from_face (FT_Face face,
return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face, out);
}
-static void
+static cairo_bool_t
_cairo_ft_unscaled_font_destroy (void *abstract_font)
{
cairo_ft_unscaled_font_t *unscaled = abstract_font;
cairo_ft_unscaled_font_map_t *font_map;
- if (unscaled == NULL)
- return;
-
font_map = _cairo_ft_unscaled_font_map_lock ();
/* All created objects must have been mapped in the font map. */
assert (font_map != NULL);
- if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled->base.ref_count)) {
+ if (! _cairo_reference_count_dec_and_test (&unscaled->base.ref_count)) {
/* somebody recreated the font whilst we waited for the lock */
_cairo_ft_unscaled_font_map_unlock ();
- return;
+ return FALSE;
}
_cairo_hash_table_remove (font_map->hash_table,
@@ -625,6 +623,7 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font)
_cairo_ft_unscaled_font_map_unlock ();
_cairo_ft_unscaled_font_fini (unscaled);
+ return TRUE;
}
static cairo_bool_t
@@ -740,19 +739,26 @@ _compute_transform (cairo_ft_font_transform_t *sf,
if (unscaled && (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) {
double min_distance = DBL_MAX;
+ cairo_bool_t magnify = TRUE;
int i;
- int best_i = 0;
double best_x_size = 0;
double best_y_size = 0;
for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
- double x_size = unscaled->face->available_sizes[i].y_ppem / 64.;
+ double x_size = unscaled->face->available_sizes[i].x_ppem / 64.;
double y_size = unscaled->face->available_sizes[i].y_ppem / 64.;
- double distance = fabs (y_size - y_scale);
+ double distance = y_size - y_scale;
+
+ /*
+ * distance is positive if current strike is larger than desired
+ * size, and negative if smaller.
+ *
+ * We like to prefer down-scaling to upscaling.
+ */
- if (distance <= min_distance) {
- min_distance = distance;
- best_i = i;
+ if ((magnify && distance >= 0) || fabs (distance) <= min_distance) {
+ magnify = distance < 0;
+ min_distance = fabs (distance);
best_x_size = x_size;
best_y_size = y_size;
}
@@ -1114,15 +1120,17 @@ _fill_xrender_bitmap(FT_Bitmap *target,
*/
static cairo_status_t
_get_bitmap_surface (FT_Bitmap *bitmap,
+ FT_Library library,
cairo_bool_t own_buffer,
cairo_font_options_t *font_options,
cairo_image_surface_t **surface)
{
- int width, height, stride;
+ unsigned int width, height;
unsigned char *data;
int format = CAIRO_FORMAT_A8;
+ int stride;
cairo_image_surface_t *image;
- cairo_bool_t component_alpha = TRUE;
+ cairo_bool_t component_alpha = TRUE;
width = bitmap->width;
height = bitmap->rows;
@@ -1179,8 +1187,18 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
case FT_PIXEL_MODE_LCD:
case FT_PIXEL_MODE_LCD_V:
case FT_PIXEL_MODE_GRAY:
- if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
+ if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL ||
+ bitmap->pixel_mode == FT_PIXEL_MODE_GRAY)
+ {
stride = bitmap->pitch;
+
+ /* We don't support stride not multiple of 4. */
+ if (stride & 3)
+ {
+ assert (!own_buffer);
+ goto convert;
+ }
+
if (own_buffer) {
data = bitmap->buffer;
} else {
@@ -1193,49 +1211,91 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
format = CAIRO_FORMAT_A8;
} else {
- /* color glyph is rendered as bitmap, does not come from
- * _fill_xrender_bitmap */
- if (! own_buffer) {
- stride = bitmap->pitch;
- data = _cairo_malloc_ab (height, stride);
- if (!data)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- memcpy (data, bitmap->buffer, stride * height);
- format = CAIRO_FORMAT_A8;
- } else {
- /* if we get there, the data from the source bitmap
- * really comes from _fill_xrender_bitmap, and is
- * made of 32-bit ARGB or ABGR values */
- assert (own_buffer != 0);
- assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
-
- data = bitmap->buffer;
- stride = bitmap->pitch;
- format = CAIRO_FORMAT_ARGB32;
- }
- }
- break;
- // color font
- /*
- case FT_PIXEL_MODE_BGRA:
+ /* color glyph is rendered as bitmap, does not come from
+ * _fill_xrender_bitmap */
+ if (! own_buffer) {
stride = bitmap->pitch;
- if (own_buffer) {
- data = bitmap->buffer;
- } else {
- data = _cairo_malloc_ab (height, stride);
- if (!data)
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- memcpy (data, bitmap->buffer, stride * height);
- }
+ data = _cairo_malloc_ab (height, stride);
+ if (!data)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ memcpy (data, bitmap->buffer, stride * height);
+ format = CAIRO_FORMAT_A8;
+ } else {
+ /* if we get there, the data from the source bitmap
+ * really comes from _fill_xrender_bitmap, and is
+ * made of 32-bit ARGB or ABGR values */
+ assert (own_buffer != 0);
+ assert (bitmap->pixel_mode != FT_PIXEL_MODE_GRAY);
+ data = bitmap->buffer;
+ stride = bitmap->pitch;
format = CAIRO_FORMAT_ARGB32;
- component_alpha = FALSE;
+ }
+ }
break;
- */
+ // color font
+ #if 0 // TODO(suyambu.rm) Build error for Tizen 3.0
+ case FT_PIXEL_MODE_BGRA:
+ stride = bitmap->pitch;
+
+ if (own_buffer) {
+ data = bitmap->buffer;
+ } else {
+ data = _cairo_malloc_ab (height, stride);
+ if (!data)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ memcpy (data, bitmap->buffer, stride * height);
+ }
+
+ format = CAIRO_FORMAT_ARGB32;
+ component_alpha = FALSE;
+ break;
+ #endif
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
+ convert:
+ if (!own_buffer && library)
+ {
+ /* This is pretty much the only case that we can get in here. */
+ /* Convert to 8bit grayscale. */
+
+ FT_Bitmap tmp;
+ FT_Int align;
+
+ format = CAIRO_FORMAT_A8;
+
+ align = cairo_format_stride_for_width (format, bitmap->width);
+
+ FT_Bitmap_New( &tmp );
+
+ if (FT_Bitmap_Convert( library, bitmap, &tmp, align ))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ FT_Bitmap_Done( library, bitmap );
+ *bitmap = tmp;
+
+ stride = bitmap->pitch;
+ data = _cairo_malloc_ab (height, stride);
+ if (!data)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ if (bitmap->num_grays != 256)
+ {
+ unsigned int x, y;
+ unsigned int mul = 255 / (bitmap->num_grays - 1);
+ FT_Byte *p = bitmap->buffer;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++)
+ p[x] *= mul;
+ p += bitmap->pitch;
+ }
+ }
+
+ memcpy (data, bitmap->buffer, stride * height);
+ break;
+ }
/* These could be triggered by very rare types of TrueType fonts */
default:
if (own_buffer)
@@ -1429,7 +1489,7 @@ _render_glyph_outline (FT_Face face,
/* Note:
* _get_bitmap_surface will free bitmap.buffer if there is an error
*/
- status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
+ status = _get_bitmap_surface (&bitmap, NULL, TRUE, font_options, surface);
if (unlikely (status))
return status;
@@ -1470,6 +1530,7 @@ _render_glyph_bitmap (FT_Face face,
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
status = _get_bitmap_surface (&glyphslot->bitmap,
+ glyphslot->library,
FALSE, font_options,
surface);
if (unlikely (status))
@@ -1511,7 +1572,7 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
* the "shape" portion of the font transform
*/
original_to_transformed = *shape;
-
+
cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
orig_width = (*surface)->width;
orig_height = (*surface)->height;
@@ -2193,10 +2254,23 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
vertical_layout = TRUE;
}
- #ifdef FT_LOAD_COLOR
- /*Color-glyph support */
- load_flags |= FT_LOAD_COLOR;
- #endif
+#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; */
+
+ /* Color-glyph support */
+ if (scaled_font->ft_options.base.color == CAIRO_FONT_COLOR_DEFAULT)
+ load_flags |= FT_LOAD_COLOR;
+#endif
error = FT_Load_Glyph (face,
_cairo_scaled_glyph_index(scaled_glyph),
@@ -2215,22 +2289,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
*/
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
-#if USE_FT_OUTLINE_EMBOLDEN
- {
- /*UX team request us to use 64 instead 34*/
- FT_Pos xstr;
- if(face && face->size)
- xstr = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) / 64;
- else
- goto FAIL;
- if(face->glyph)
- FT_Outline_Embolden(&face->glyph->outline, xstr);
- else
- goto FAIL;
- }
-#else
FT_GlyphSlot_Embolden (glyph);
-#endif // USE_FT_OUTLINE_EMBOLDEN
#endif
#if HAVE_FT_GLYPHSLOT_OBLIQUE
@@ -2384,22 +2443,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
}
#if HAVE_FT_GLYPHSLOT_EMBOLDEN
if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
-#if USE_FT_OUTLINE_EMBOLDEN
- {
- /*UX team request us to use 64 instead 34*/
- FT_Pos xstr;
- if(face && face->size)
- xstr = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) / 64;
- else
- goto FAIL;
- if(face->glyph)
- FT_Outline_Embolden(&face->glyph->outline, xstr);
- else
- goto FAIL;
- }
-#else
- FT_GlyphSlot_Embolden (glyph);
-#endif // USE_FT_OUTLINE_EMBOLDEN
+ FT_GlyphSlot_Embolden (glyph);
#endif
#if HAVE_FT_GLYPHSLOT_OBLIQUE
if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE)
@@ -2752,7 +2796,7 @@ _cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
}
#endif
-static void
+static cairo_bool_t
_cairo_ft_font_face_destroy (void *abstract_face)
{
cairo_ft_font_face_t *font_face = abstract_face;
@@ -2778,12 +2822,10 @@ _cairo_ft_font_face_destroy (void *abstract_face)
font_face->unscaled->faces == font_face &&
CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
{
- cairo_font_face_reference (&font_face->base);
-
_cairo_unscaled_font_destroy (&font_face->unscaled->base);
font_face->unscaled = NULL;
- return;
+ return FALSE;
}
if (font_face->unscaled) {
@@ -2815,6 +2857,8 @@ _cairo_ft_font_face_destroy (void *abstract_face)
cairo_font_face_destroy (font_face->resolved_font_face);
}
#endif
+
+ return TRUE;
}
static cairo_font_face_t *
diff --git a/src/cairo-ft-private.h b/src/cairo-ft-private.h
index 392151866..0dc811472 100755..100644
--- a/src/cairo-ft-private.h
+++ b/src/cairo-ft-private.h
@@ -37,8 +37,8 @@
#ifndef CAIRO_FT_PRIVATE_H
#define CAIRO_FT_PRIVATE_H
-#include "cairo-ft.h"
#include "cairoint.h"
+#include "cairo-ft.h"
#if CAIRO_HAS_FT_FONT
diff --git a/src/cairo-ft.h b/src/cairo-ft.h
index 29c43c965..29c43c965 100755..100644
--- a/src/cairo-ft.h
+++ b/src/cairo-ft.h
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index c9f7782d1..57d7ddf31 100755..100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -76,7 +76,7 @@ _cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup,
_cairo_gl_operand_copy (&setup->src, source);
if (source->type == CAIRO_GL_OPERAND_TEXTURE ||
source->type == CAIRO_GL_OPERAND_GAUSSIAN)
- status = _cairo_gl_surface_resolve_multisampling (source->texture.surface);
+ status = _cairo_gl_surface_resolve_multisampling (source->texture.surface);
}
void
@@ -96,7 +96,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_INT_STATUS_SUCCESS;
return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst,
sample, extents, use_texgen, FALSE);
@@ -112,7 +112,7 @@ _cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup,
_cairo_gl_operand_copy (&setup->mask, mask);
if (mask->type == CAIRO_GL_OPERAND_TEXTURE ||
mask->type == CAIRO_GL_OPERAND_GAUSSIAN)
- status = _cairo_gl_surface_resolve_multisampling (mask->texture.surface);
+ status = _cairo_gl_surface_resolve_multisampling (mask->texture.surface);
}
}
@@ -146,7 +146,7 @@ static void
_cairo_gl_composite_bind_to_shader (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
{
- _cairo_gl_shader_bind_matrix4f(ctx, CAIRO_GL_UNIFORM_PROJECTION_MATRIX,
+ _cairo_gl_shader_bind_matrix4f(ctx, ctx->current_shader->mvp_location,
ctx->modelviewprojection_matrix);
_cairo_gl_operand_bind_to_shader (ctx, &setup->src, CAIRO_GL_TEX_SOURCE);
_cairo_gl_operand_bind_to_shader (ctx, &setup->mask, CAIRO_GL_TEX_MASK);
@@ -259,7 +259,7 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
if (operand->constant.encode_as_attribute) {
dispatch->VertexAttribPointer (CAIRO_GL_COLOR_ATTRIB_INDEX, 4,
GL_FLOAT, GL_FALSE, ctx->vertex_size,
- ctx->vb + vertex_offset);
+ ctx->vbo ? (GLvoid *)vertex_offset : (GLvoid *)(ctx->vb + vertex_offset));
dispatch->EnableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
}
break;
@@ -278,7 +278,7 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
if (! operand->texture.texgen) {
dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
GL_FLOAT, GL_FALSE, ctx->vertex_size,
- ctx->vb + offset);
+ ctx->vbo ? (GLvoid *)offset : (GLvoid *)(ctx->vb + offset));
dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
offset += 2 * sizeof (GLfloat);
}
@@ -287,12 +287,12 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
dispatch->VertexAttribPointer (CAIRO_GL_START_COORD0_ATTRIB_INDEX + tex_unit,
2, GL_FLOAT, GL_FALSE,
ctx->vertex_size,
- ctx->vb + offset);
+ ctx->vbo ? (GLvoid *)offset : (GLvoid *)(ctx->vb + offset));
dispatch->EnableVertexAttribArray (CAIRO_GL_START_COORD0_ATTRIB_INDEX + tex_unit);
dispatch->VertexAttribPointer (CAIRO_GL_STOP_COORD0_ATTRIB_INDEX + tex_unit,
2, GL_FLOAT, GL_FALSE,
ctx->vertex_size,
- ctx->vb + offset + 2 * sizeof (float));
+ ctx->vbo ? (GLvoid *)(offset + 2 * sizeof (float)) : (GLvoid *)(ctx->vb + offset + 2 * sizeof (float)));
dispatch->EnableVertexAttribArray (CAIRO_GL_STOP_COORD0_ATTRIB_INDEX + tex_unit);
}
break;
@@ -312,7 +312,7 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
if (! operand->gradient.texgen) {
dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
GL_FLOAT, GL_FALSE, ctx->vertex_size,
- ctx->vb + vertex_offset);
+ ctx->vbo ? (GLvoid *)vertex_offset : (GLvoid *)(ctx->vb + vertex_offset));
dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
}
break;
@@ -341,7 +341,7 @@ _cairo_gl_context_setup_spans (cairo_gl_context_t *ctx,
dispatch->VertexAttribPointer (CAIRO_GL_COLOR_ATTRIB_INDEX, 4,
GL_UNSIGNED_BYTE, GL_TRUE, vertex_size,
- ctx->vb + vertex_offset);
+ ctx->vbo ? (GLvoid *)vertex_offset : (GLvoid *)(ctx->vb + vertex_offset));
dispatch->EnableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
ctx->spans = TRUE;
}
@@ -617,7 +617,7 @@ _cairo_gl_composite_setup_vbo (cairo_gl_context_t *ctx,
if (_cairo_gl_context_is_flushed (ctx)) {
ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2,
GL_FLOAT, GL_FALSE, size_per_vertex,
- ctx->vb);
+ ctx->vbo ? 0 : ctx->vb);
ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX);
}
@@ -655,17 +655,18 @@ _cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup,
_enable_stencil_buffer (ctx);
_enable_scissor_buffer (ctx);
+
+ /* We only want to clear the part of the stencil buffer
+ * that we are about to use. It also does not hurt to
+ * scissor around the painted clip. */
_cairo_gl_scissor_to_rectangle (dst, _cairo_clip_get_extents (clip));
if (clip_is_equal)
goto activate_stencil_buffer_and_return;
- /* Clear the stencil buffer, but only the areas that we are
- * going to be drawing to. */
- if (old_clip) {
- _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
- }
-
+ if (old_clip) {
+ _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
+ }
setup->dst->clip_on_stencil_buffer = _cairo_clip_copy (setup->clip);
ctx->dispatch.ClearStencil (0);
@@ -783,6 +784,7 @@ _cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup,
ctx->pre_shader = NULL;
return status;
}
+
if (ctx->current_shader != shader)
_cairo_gl_composite_flush (ctx);
@@ -842,10 +844,12 @@ _cairo_gl_composite_begin (cairo_gl_composite_t *setup,
setup->dst->content_cleared = FALSE;
_cairo_gl_context_set_destination (ctx, setup->dst, setup->multisample);
+
if (ctx->states_cache.blend_enabled == FALSE) {
ctx->dispatch.Enable (GL_BLEND);
ctx->states_cache.blend_enabled = TRUE;
}
+
status = _cairo_gl_set_operands_and_operator (setup, ctx);
if (unlikely (status))
goto FAIL;
@@ -869,18 +873,24 @@ _cairo_gl_composite_draw_tristrip (cairo_gl_context_t *ctx)
cairo_array_t* indices = &ctx->tristrip_indices;
const unsigned short *indices_array = _cairo_array_index_const (indices, 0);
+ if (ctx->ibo) {
+ ctx->dispatch.BufferSubData (GL_ELEMENT_ARRAY_BUFFER, 0,
+ _cairo_array_num_elements (indices) * sizeof (unsigned short),
+ (GLvoid *) indices_array);
+ }
+
if (ctx->pre_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);
- ctx->dispatch.DrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
+ ctx->dispatch.DrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, ctx->ibo ? 0 : indices_array);
_cairo_gl_set_shader (ctx, prev_shader);
_cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE);
}
- ctx->dispatch.DrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
+ ctx->dispatch.DrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, ctx->ibo ? 0 :indices_array);
_cairo_array_truncate (indices, 0);
}
@@ -894,18 +904,24 @@ _cairo_gl_composite_draw_line (cairo_gl_context_t *ctx)
if (ctx->draw_mode == CAIRO_GL_LINES)
type = GL_LINES;
+ if (ctx->ibo) {
+ ctx->dispatch.BufferSubData (GL_ELEMENT_ARRAY_BUFFER, 0,
+ _cairo_array_num_elements (indices) * sizeof (unsigned short),
+ (GLvoid *) indices_array);
+ }
+
if (ctx->pre_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);
- ctx->dispatch.DrawElements (type, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
+ ctx->dispatch.DrawElements (type, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, ctx->ibo ? 0 : indices_array);
_cairo_gl_set_shader (ctx, prev_shader);
_cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE);
}
- ctx->dispatch.DrawElements (type, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
+ ctx->dispatch.DrawElements (type, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, ctx->ibo ? 0 : indices_array);
_cairo_array_truncate (indices, 0);
}
@@ -954,6 +970,11 @@ _cairo_gl_composite_draw_triangles_with_clip_region (cairo_gl_context_t *ctx,
static void
_cairo_gl_composite_unmap_vertex_buffer (cairo_gl_context_t *ctx)
{
+ if (ctx->vbo) {
+ ctx->dispatch.BufferSubData (GL_ARRAY_BUFFER, 0,
+ ctx->vb_offset,
+ (const GLvoid *)ctx->vb);
+ }
ctx->vb_offset = 0;
}
@@ -966,7 +987,11 @@ _cairo_gl_composite_flush (cairo_gl_context_t *ctx)
if (_cairo_gl_context_is_flushed (ctx))
return;
+ /* ensure we are binding to vbo and ibo */
+ _cairo_gl_ensure_drawbuffers (ctx);
+
count = ctx->vb_offset / ctx->vertex_size;
+
_cairo_gl_composite_unmap_vertex_buffer (ctx);
if (ctx->primitive_type == CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS) {
@@ -996,7 +1021,8 @@ _cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx,
ctx->primitive_type = primitive_type;
}
- if (ctx->vb_offset + n_vertices * ctx->vertex_size > CAIRO_GL_VBO_SIZE)
+ assert(ctx->vbo_size > 0);
+ if (ctx->vb_offset + n_vertices * ctx->vertex_size > ctx->vbo_size)
_cairo_gl_composite_flush (ctx);
}
@@ -1141,17 +1167,17 @@ _cairo_gl_composite_emit_solid_span (cairo_gl_context_t *ctx,
v = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
- v[15 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[15 + 20*src_use_atlas + 20*mask_use_atlas] =
v[ 6 + 8*src_use_atlas + 8*mask_use_atlas] =
v[ 0 ] = x1;
v[10 + 12*src_use_atlas + 12*mask_use_atlas] =
v[ 4 + 4*src_use_atlas + 4*mask_use_atlas] =
v[ 1 ] = y1;
v[12 + 16*src_use_atlas + 16*mask_use_atlas] =
- v[ 9 + 12*src_use_atlas + 12*mask_use_atlas] =
+ v[ 9 + 12*src_use_atlas + 12*mask_use_atlas] =
v[ 3 + 4*src_use_atlas + 4*mask_use_atlas] = x2;
- v[16 + 20*src_use_atlas + 20*mask_use_atlas] =
- v[13 + 16*src_use_atlas + 16*mask_use_atlas] =
+ v[16 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[13 + 16*src_use_atlas + 16*mask_use_atlas] =
v[ 7 + 8*src_use_atlas + 8*mask_use_atlas] = y2;
fi.bytes[0] = 0;
@@ -1159,77 +1185,77 @@ _cairo_gl_composite_emit_solid_span (cairo_gl_context_t *ctx,
fi.bytes[2] = 0;
fi.bytes[3] = alpha;
v[17 + 24*src_use_atlas + 24*mask_use_atlas] =
- v[14 + 20*src_use_atlas + 20*mask_use_atlas] =
- v[11 + 16*src_use_atlas + 16*mask_use_atlas] =
- v[ 8 + 12*src_use_atlas + 12*mask_use_atlas] =
- v[ 5 + 8*src_use_atlas + 8*mask_use_atlas] =
+ v[14 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[11 + 16*src_use_atlas + 16*mask_use_atlas] =
+ v[ 8 + 12*src_use_atlas + 12*mask_use_atlas] =
+ v[ 5 + 8*src_use_atlas + 8*mask_use_atlas] =
v[ 2 + 4*src_use_atlas + 4*mask_use_atlas ] = fi.f;
if (src_use_atlas) {
v[ 2 ] =
- v[ 5 + 4*src_use_atlas + 4*mask_use_atlas] =
- v[ 8 + 8*src_use_atlas + 8*mask_use_atlas] =
+ v[ 5 + 4*src_use_atlas + 4*mask_use_atlas] =
+ v[ 8 + 8*src_use_atlas + 8*mask_use_atlas] =
v[11 + 12*src_use_atlas + 12*mask_use_atlas] =
v[14 + 16*src_use_atlas + 16*mask_use_atlas] =
- v[17 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[17 + 20*src_use_atlas + 20*mask_use_atlas] =
ctx->operands[CAIRO_GL_TEX_SOURCE].texture.p1.x;
v[ 3 ] =
- v[ 6 + 4*src_use_atlas + 4*mask_use_atlas] =
- v[ 9 + 8*src_use_atlas + 8*mask_use_atlas] =
+ v[ 6 + 4*src_use_atlas + 4*mask_use_atlas] =
+ v[ 9 + 8*src_use_atlas + 8*mask_use_atlas] =
v[12 + 12*src_use_atlas + 12*mask_use_atlas] =
v[15 + 16*src_use_atlas + 16*mask_use_atlas] =
- v[18 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[18 + 20*src_use_atlas + 20*mask_use_atlas] =
ctx->operands[CAIRO_GL_TEX_SOURCE].texture.p1.y;
-
+
v[ 4 ] =
- v[ 7 + 4*src_use_atlas + 4*mask_use_atlas] =
- v[10 + 8*src_use_atlas + 8*mask_use_atlas] =
+ v[ 7 + 4*src_use_atlas + 4*mask_use_atlas] =
+ v[10 + 8*src_use_atlas + 8*mask_use_atlas] =
v[13 + 12*src_use_atlas + 12*mask_use_atlas] =
v[16 + 16*src_use_atlas + 16*mask_use_atlas] =
- v[19 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[19 + 20*src_use_atlas + 20*mask_use_atlas] =
ctx->operands[CAIRO_GL_TEX_SOURCE].texture.p2.x;
v[ 5 ] =
- v[ 8 + 4*src_use_atlas + 4*mask_use_atlas] =
- v[11 + 8*src_use_atlas + 8*mask_use_atlas] =
+ v[ 8 + 4*src_use_atlas + 4*mask_use_atlas] =
+ v[11 + 8*src_use_atlas + 8*mask_use_atlas] =
v[14 + 12*src_use_atlas + 12*mask_use_atlas] =
v[17 + 16*src_use_atlas + 16*mask_use_atlas] =
- v[20 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[20 + 20*src_use_atlas + 20*mask_use_atlas] =
ctx->operands[CAIRO_GL_TEX_SOURCE].texture.p2.y;
}
if (mask_use_atlas) {
v[ 2 + 4*src_use_atlas ] =
- v[ 5 + 8*src_use_atlas + 4*mask_use_atlas] =
- v[ 8 + 12*src_use_atlas + 8*mask_use_atlas] =
+ v[ 5 + 8*src_use_atlas + 4*mask_use_atlas] =
+ v[ 8 + 12*src_use_atlas + 8*mask_use_atlas] =
v[11 + 16*src_use_atlas + 12*mask_use_atlas] =
v[14 + 20*src_use_atlas + 16*mask_use_atlas] =
- v[17 + 24*src_use_atlas + 20*mask_use_atlas] =
+ v[17 + 24*src_use_atlas + 20*mask_use_atlas] =
ctx->operands[CAIRO_GL_TEX_MASK].texture.p1.x;
v[ 3 + 4*src_use_atlas ] =
- v[ 6 + 4*src_use_atlas + 4*mask_use_atlas] =
- v[ 9 + 8*src_use_atlas + 8*mask_use_atlas] =
+ v[ 6 + 4*src_use_atlas + 4*mask_use_atlas] =
+ v[ 9 + 8*src_use_atlas + 8*mask_use_atlas] =
v[12 + 12*src_use_atlas + 12*mask_use_atlas] =
v[15 + 16*src_use_atlas + 16*mask_use_atlas] =
- v[18 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[18 + 20*src_use_atlas + 20*mask_use_atlas] =
ctx->operands[CAIRO_GL_TEX_MASK].texture.p1.y;
-
+
v[ 4 + 4*src_use_atlas ] =
- v[ 7 + 4*src_use_atlas + 4*mask_use_atlas] =
- v[10 + 8*src_use_atlas + 8*mask_use_atlas] =
+ v[ 7 + 4*src_use_atlas + 4*mask_use_atlas] =
+ v[10 + 8*src_use_atlas + 8*mask_use_atlas] =
v[13 + 12*src_use_atlas + 12*mask_use_atlas] =
v[16 + 16*src_use_atlas + 16*mask_use_atlas] =
- v[19 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[19 + 20*src_use_atlas + 20*mask_use_atlas] =
ctx->operands[CAIRO_GL_TEX_MASK].texture.p2.x;
v[ 5 + 4*src_use_atlas ] =
- v[ 8 + 4*src_use_atlas + 4*mask_use_atlas] =
- v[11 + 8*src_use_atlas + 8*mask_use_atlas] =
+ v[ 8 + 4*src_use_atlas + 4*mask_use_atlas] =
+ v[11 + 8*src_use_atlas + 8*mask_use_atlas] =
v[14 + 12*src_use_atlas + 12*mask_use_atlas] =
v[17 + 16*src_use_atlas + 16*mask_use_atlas] =
- v[20 + 20*src_use_atlas + 20*mask_use_atlas] =
+ v[20 + 20*src_use_atlas + 20*mask_use_atlas] =
ctx->operands[CAIRO_GL_TEX_MASK].texture.p2.y;
}
@@ -1309,17 +1335,17 @@ _cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx,
static inline void
_cairo_gl_composite_emit_color_glyph_vertex (cairo_gl_context_t *ctx,
- GLfloat x, GLfloat y,
- GLfloat glyph_x, GLfloat glyph_y)
+ GLfloat x, GLfloat y,
+ GLfloat glyph_x, GLfloat glyph_y)
{
- GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
+ GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
- *vb++ = x;
- *vb++ = y;
- *vb++ = glyph_x;
- *vb++ = glyph_y;
+ *vb++ = x;
+ *vb++ = y;
+ *vb++ = glyph_x;
+ *vb++ = glyph_y;
- ctx->vb_offset += ctx->vertex_size;
+ ctx->vb_offset += ctx->vertex_size;
}
static void
@@ -1348,26 +1374,26 @@ _cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx,
static void
_cairo_gl_composite_emit_color_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)
{
- if (ctx->draw_mode != CAIRO_GL_VERTEX) {
+ if (ctx->draw_mode != CAIRO_GL_VERTEX) {
_cairo_gl_composite_flush (ctx);
ctx->draw_mode = CAIRO_GL_VERTEX;
- }
+ }
- _cairo_gl_composite_prepare_buffer (ctx, 6,
- CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
+ _cairo_gl_composite_prepare_buffer (ctx, 6,
+ CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
- _cairo_gl_composite_emit_color_glyph_vertex (ctx, x1, y1, glyph_x1, glyph_y1);
- _cairo_gl_composite_emit_color_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
- _cairo_gl_composite_emit_color_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
+ _cairo_gl_composite_emit_color_glyph_vertex (ctx, x1, y1, glyph_x1, glyph_y1);
+ _cairo_gl_composite_emit_color_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
+ _cairo_gl_composite_emit_color_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
- _cairo_gl_composite_emit_color_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
- _cairo_gl_composite_emit_color_glyph_vertex (ctx, x2, y2, glyph_x2, glyph_y2);
- _cairo_gl_composite_emit_color_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
+ _cairo_gl_composite_emit_color_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
+ _cairo_gl_composite_emit_color_glyph_vertex (ctx, x2, y2, glyph_x2, glyph_y2);
+ _cairo_gl_composite_emit_color_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
}
static void
@@ -1400,13 +1426,12 @@ _cairo_gl_composite_emit_solid_glyph (cairo_gl_context_t *ctx,
cairo_gl_emit_glyph_t
_cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx,
- const cairo_bool_t is_color_glyph)
+ const cairo_bool_t is_color_glyph)
{
-
- if ( is_color_glyph) {
+ if ( is_color_glyph) {
/* color glyph ignore all source and mask */
return _cairo_gl_composite_emit_color_glyph;
- }
+ }
switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) {
default:
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index a22ac63bb..dbb6f162f 100755..100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -215,6 +215,15 @@ _gl_destroy (void *device)
cairo_region_destroy (ctx->clip_region);
free (ctx->vb);
+ if (ctx->vao) {
+ ctx->dispatch.DeleteVertexArrays (1, &ctx->vao);
+ }
+ if (ctx->vbo) {
+ ctx->dispatch.DeleteBuffers (1, &ctx->vbo);
+ }
+ if (ctx->ibo) {
+ ctx->dispatch.DeleteBuffers (1, &ctx->ibo);
+ }
ctx->destroy (ctx);
@@ -269,6 +278,11 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
cairo_bool_t is_gles = (gl_flavor == CAIRO_GL_FLAVOR_ES2 ||
gl_flavor == CAIRO_GL_FLAVOR_ES3);
+ if (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 30) &&
+ gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+ ctx->is_gl33 = TRUE;
+ else
+ ctx->is_gl33 = FALSE;
_cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
/* XXX The choice of compositor should be made automatically at runtime.
@@ -293,7 +307,8 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
/* Check for required extensions */
if (is_desktop) {
- if (_cairo_gl_has_extension (&ctx->dispatch, "GL_ARB_texture_non_power_of_two")) {
+ if (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) ||
+ _cairo_gl_has_extension (&ctx->dispatch, "GL_ARB_texture_non_power_of_two")) {
ctx->tex_target = GL_TEXTURE_2D;
ctx->has_npot_repeat = TRUE;
} else if (_cairo_gl_has_extension (&ctx->dispatch, "GL_ARB_texture_rectangle")) {
@@ -326,7 +341,9 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
_cairo_gl_has_extension (&ctx->dispatch, "GL_MESA_pack_invert");
ctx->has_packed_depth_stencil =
- (is_desktop && _cairo_gl_has_extension (&ctx->dispatch, "GL_EXT_packed_depth_stencil")) ||
+ (is_desktop &&
+ (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) ||
+ _cairo_gl_has_extension (&ctx->dispatch, "GL_EXT_packed_depth_stencil"))) ||
(is_gles && _cairo_gl_has_extension (&ctx->dispatch, "GL_OES_packed_depth_stencil"));
ctx->num_samples = 1;
@@ -336,51 +353,51 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
if (is_desktop && ctx->has_packed_depth_stencil &&
(gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) ||
_cairo_gl_has_extension (&ctx->dispatch, "GL_ARB_framebuffer_object") ||
- (_cairo_gl_has_extension (&ctx->dispatch, "GL_EXT_framebuffer_blit") &&
- _cairo_gl_has_extension (&ctx->dispatch, "GL_EXT_framebuffer_multisample")))) {
- ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
+ (_cairo_gl_has_extension (&ctx->dispatch, "GL_EXT_framebuffer_blit") &&
+ _cairo_gl_has_extension (&ctx->dispatch, "GL_EXT_framebuffer_multisample")))) {
+ ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
}
#endif
#if (CAIRO_HAS_GLESV2_SURFACE || CAIRO_HAS_EVASGL_SURFACE) && GL_MAX_SAMPLES_EXT
if (is_gles && ctx->has_packed_depth_stencil &&
_cairo_gl_has_extension (&ctx->dispatch, "GL_EXT_multisampled_render_to_texture")) {
- ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
- ctx->msaa_type = CAIRO_GL_EXT_MULTISAMPLE_TO_TEXTURE;
+ ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
+ ctx->msaa_type = CAIRO_GL_EXT_MULTISAMPLE_TO_TEXTURE;
}
#endif
#if (CAIRO_HAS_GLESV2_SURFACE || CAIRO_HAS_EVASGL_SURFACE) && GL_MAX_SAMPLES_IMG
if (ctx->msaa_type == CAIRO_GL_NONE_MULTISAMPLE_TO_TEXTURE &&
- is_gles &&
- ctx->has_packed_depth_stencil &&
+ is_gles &&
+ ctx->has_packed_depth_stencil &&
_cairo_gl_has_extension (&ctx->dispatch, "GL_IMG_multisampled_render_to_texture")) {
- ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES_IMG, &ctx->num_samples);
- ctx->msaa_type = CAIRO_GL_IMG_MULTISAMPLE_TO_TEXTURE;
+ ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES_IMG, &ctx->num_samples);
+ ctx->msaa_type = CAIRO_GL_IMG_MULTISAMPLE_TO_TEXTURE;
}
#endif
#if (CAIRO_HAS_GLESV2_SURFACE || CAIRO_HAS_EVASGL_SURFACE) && GL_MAX_SAMPLES_ANGLE
if (ctx->msaa_type == CAIRO_GL_NONE_MULTISAMPLE_TO_TEXTURE &&
- is_gles &&
- ctx->has_packed_depth_stencil &&
+ is_gles &&
+ ctx->has_packed_depth_stencil &&
_cairo_gl_has_extension (&ctx->dispatch, "GL_ANGLE_framebuffer_blit") &&
- _cairo_gl_has_extension (&ctx->dispatch, "GL_ANGLE_framebuffer_multisample")) {
- ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES_ANGLE, &ctx->num_samples);
+ _cairo_gl_has_extension (&ctx->dispatch, "GL_ANGLE_framebuffer_multisample")) {
+ ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES_ANGLE, &ctx->num_samples);
ctx->has_angle_multisampling = TRUE;
}
#endif
#if CAIRO_HAS_GLESV3_SURFACE || CAIRO_HAS_EVASGL_SURFACE
if (ctx->msaa_type == CAIRO_GL_NONE_MULTISAMPLE_TO_TEXTURE &&
- is_gles && ctx->has_packed_depth_stencil) {
- ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES, &ctx->num_samples);
- /* this is work around for evasgl. At this moment, if
- we still get samples == 1, it means gles2 does not have any
+ is_gles && ctx->has_packed_depth_stencil) {
+ ctx->dispatch.GetIntegerv(GL_MAX_SAMPLES, &ctx->num_samples);
+ /* this is work around for evasgl. At this moment, if
+ we still get samples == 1, it means gles2 does not have any
support for extensions we have supported
- */
- if (gl_flavor == CAIRO_GL_FLAVOR_ES2)
- ctx->num_samples = 1;
+ */
+ if (gl_flavor == CAIRO_GL_FLAVOR_ES2)
+ ctx->num_samples = 1;
}
#endif
@@ -410,18 +427,45 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
if (unlikely (status))
return status;
- ctx->vb = malloc (CAIRO_GL_VBO_SIZE);
+ ctx->vbo_size = _cairo_gl_get_vbo_size();
+
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP &&
+ gl_version > CAIRO_GL_VERSION_ENCODE (3, 0)) {
+ ctx->dispatch.GenVertexArrays (1, &ctx->vao);
+ ctx->dispatch.BindVertexArray (ctx->vao);
+
+ ctx->dispatch.GenBuffers (1, &ctx->vbo);
+ ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, ctx->vbo);
+ ctx->dispatch.BufferData (GL_ARRAY_BUFFER, ctx->vbo_size,
+ NULL, GL_DYNAMIC_DRAW);
+
+ ctx->dispatch.GenBuffers (1, &ctx->ibo);
+ ctx->dispatch.BindBuffer (GL_ELEMENT_ARRAY_BUFFER, ctx->ibo);
+ ctx->dispatch.BufferData (GL_ELEMENT_ARRAY_BUFFER,
+ ctx->vbo_size * 2,
+ NULL, GL_DYNAMIC_DRAW);
+ ctx->states_cache.bound_vao = ctx->vao;
+ ctx->states_cache.bound_vbo = ctx->vbo;
+ ctx->states_cache.bound_ibo = ctx->ibo;
+ } else {
+ ctx->vbo = 0;
+ ctx->vao = 0;
+ ctx->ibo = 0;
+ }
+
+ ctx->vb = malloc (ctx->vbo_size);
+
if (unlikely (ctx->vb == NULL)) {
- _cairo_cache_fini (&ctx->gradients);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ _cairo_cache_fini (&ctx->gradients);
+ ctx->dispatch.DeleteVertexArrays (1, &ctx->vao);
+ ctx->dispatch.DeleteBuffers (1, &ctx->vbo);
+ ctx->dispatch.DeleteBuffers (1, &ctx->ibo);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
}
ctx->primitive_type = CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES;
_cairo_array_init (&ctx->tristrip_indices, sizeof (unsigned short));
- /* PBO for any sort of texture upload */
- dispatch->GenBuffers (1, &ctx->texture_load_pbo);
-
ctx->max_framebuffer_size = 0;
ctx->dispatch.GetIntegerv (GL_MAX_RENDERBUFFER_SIZE, &ctx->max_framebuffer_size);
ctx->max_texture_size = 0;
@@ -655,7 +699,9 @@ _cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx,
ctx->dispatch.ClearColor (0, 0, 0, 0);
// reset cached clear colors
memset (&ctx->states_cache.clear_red, 0, sizeof (GLclampf) * 4);
+
ctx->dispatch.Clear (GL_COLOR_BUFFER_BIT);
+
}
static cairo_bool_t
@@ -666,7 +712,7 @@ _cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
if (surface->msaa_depth_stencil)
return TRUE;
- _cairo_gl_ensure_multisampling (ctx, surface);
+ //_cairo_gl_ensure_framebuffer (ctx, surface);
dispatch->GenRenderbuffers (1, &surface->msaa_depth_stencil);
dispatch->BindRenderbuffer (GL_RENDERBUFFER,
@@ -805,8 +851,6 @@ bind_multisample_framebuffer (cairo_gl_context_t *ctx,
GLbitfield mask;
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
- stencil_test_enabled = ctx->states_cache.stencil_test_enabled;
- scissor_test_enabled = ctx->states_cache.scissor_test_enabled;
has_stencil_cache = surface->clip_on_stencil_buffer ? TRUE : FALSE;
mask = GL_COLOR_BUFFER_BIT;
@@ -832,34 +876,37 @@ bind_multisample_framebuffer (cairo_gl_context_t *ctx,
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_EVASGL_SURFACE
/* we must disable scissor and stencil test */
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
- _disable_stencil_buffer (ctx);
- _disable_scissor_buffer (ctx);
+ stencil_test_enabled = ctx->states_cache.stencil_test_enabled;
+ scissor_test_enabled = ctx->states_cache.scissor_test_enabled;
+ _disable_stencil_buffer (ctx);
+ _disable_scissor_buffer (ctx);
ctx->dispatch.Enable (GL_MULTISAMPLE);
- if (has_stencil_cache)
- mask |= GL_STENCIL_BUFFER_BIT;
-
- /* 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
- multisampling framebuffer. */
- ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->msaa_fb);
- ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->fb);
- ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
- 0, 0, surface->width, surface->height,
- mask, GL_NEAREST);
- surface->content_synced = TRUE;
+ if (has_stencil_cache)
+ mask |= GL_STENCIL_BUFFER_BIT;
+
+ /* 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
+ multisampling framebuffer. */
+ ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->msaa_fb);
+ ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->fb);
+ ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
+ 0, 0, surface->width, surface->height,
+ mask, GL_NEAREST);
+ surface->content_synced = TRUE;
}
#endif
+
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_EVASGL_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
- /* re-enable stencil and scissor test */
- if (scissor_test_enabled)
- _enable_scissor_buffer (ctx);
- if (stencil_test_enabled)
- _enable_stencil_buffer (ctx);
+ /* re-enable stencil and scissor test */
+ if (stencil_test_enabled)
+ _enable_stencil_buffer (ctx);
+ if (scissor_test_enabled)
+ _enable_scissor_buffer (ctx);
}
#endif
}
@@ -869,14 +916,14 @@ bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
cairo_bool_t has_stencil_cache = surface->clip_on_stencil_buffer ? TRUE : FALSE;
- cairo_bool_t stencil_test_enabled = ctx->states_cache.stencil_test_enabled;
- cairo_bool_t scissor_test_enabled = ctx->states_cache.scissor_test_enabled;
+ cairo_bool_t stencil_test_enabled;
+ cairo_bool_t scissor_test_enabled;
GLbitfield mask = GL_COLOR_BUFFER_BIT;
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
! ctx->has_angle_multisampling)
return;
-
+
_cairo_gl_ensure_framebuffer (ctx, surface);
if (! surface->msaa_active) {
@@ -890,9 +937,11 @@ bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
_cairo_gl_composite_flush (ctx);
- /* we must disable scissor and stencil test */
- _disable_stencil_buffer (ctx);
+ stencil_test_enabled = ctx->states_cache.stencil_test_enabled;
+ scissor_test_enabled = ctx->states_cache.scissor_test_enabled;
+ _disable_stencil_buffer (ctx);
_disable_scissor_buffer (ctx);
+
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_EVASGL_FLAVOR
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
ctx->dispatch.Disable (GL_MULTISAMPLE);
@@ -906,12 +955,12 @@ bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
non-multisampling framebuffer. */
#if CAIRO_HAS_GLESV2_SURFACE || CAIRO_HAS_EVASGL_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) {
- ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER_ANGLE, surface->fb);
- ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER_ANGLE, surface->msaa_fb);
+ ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER_ANGLE, surface->fb);
+ ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER_ANGLE, surface->msaa_fb);
}
#if CAIRO_HAS_EVASGL_SURFACE
else {
- ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->fb);
+ ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->fb);
ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->msaa_fb);
}
#endif
@@ -925,11 +974,12 @@ bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
surface->content_synced = TRUE;
+
/* re-enable stencil and scissor test */
- if (scissor_test_enabled)
- _enable_scissor_buffer (ctx);
if (stencil_test_enabled)
_enable_stencil_buffer (ctx);
+ if (scissor_test_enabled)
+ _enable_scissor_buffer (ctx);
}
void
@@ -1018,8 +1068,8 @@ _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
if (! _cairo_gl_surface_is_texture (surface)) {
#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_EVASGL_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP &&
- ctx->dispatch.DrawBuffer &&
- ctx->dispatch.ReadBuffer) {
+ ctx->dispatch.DrawBuffer &&
+ ctx->dispatch.ReadBuffer) {
ctx->dispatch.DrawBuffer (GL_BACK_LEFT);
ctx->dispatch.ReadBuffer (GL_BACK_LEFT);
}
@@ -1046,22 +1096,11 @@ void
cairo_gl_device_set_thread_aware (cairo_device_t *device,
cairo_bool_t thread_aware)
{
- if ((! device)||(cairo_device_status(device)!= CAIRO_STATUS_SUCCESS)) {
- fprintf (stderr, "cairo_gl_device_set_thread_aware(): cairo_device is NULL or not available\n");
- _cairo_error_throw (CAIRO_STATUS_DEVICE_ERROR);
- return;
- }
if (device->backend->type != CAIRO_DEVICE_TYPE_GL) {
_cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
return;
}
- if(thread_aware == 0 || thread_aware == 1){
- ((cairo_gl_context_t *) device)->thread_aware = thread_aware;
- }
- else{
- _cairo_device_set_error (device, CAIRO_STATUS_INVALID_STATUS);
- return;
- }
+ ((cairo_gl_context_t *) device)->thread_aware = thread_aware;
}
void _cairo_gl_context_reset (cairo_gl_context_t *ctx)
@@ -1085,8 +1124,12 @@ void _cairo_gl_context_reset (cairo_gl_context_t *ctx)
ctx->states_cache.depth_mask = FALSE;
- /* FIXME: this is hack to fix mali driver*/
- ctx->dispatch.Disable (GL_DITHER);
+ /* FIXME: this is hack to fix mali driver */
+ ctx->dispatch.Disable (GL_DITHER);
+
+ ctx->current_shader = NULL;
- ctx->current_shader = NULL;
+ ctx->states_cache.bound_vbo = 0;
+ ctx->states_cache.bound_vao = 0;
+ ctx->states_cache.bound_ibo = 0;
}
diff --git a/src/cairo-gl-dispatch-private.h b/src/cairo-gl-dispatch-private.h
index 5996ebdc7..5d4144f03 100755..100644
--- a/src/cairo-gl-dispatch-private.h
+++ b/src/cairo-gl-dispatch-private.h
@@ -78,6 +78,7 @@ cairo_private cairo_gl_dispatch_entry_t dispatch_core_entries[] = {
DISPATCH_ENTRY_CORE (ClearStencil),
DISPATCH_ENTRY_CORE (ColorMask),
DISPATCH_ENTRY_CORE (DeleteTextures),
+ DISPATCH_ENTRY_CORE (DepthMask),
DISPATCH_ENTRY_CORE (Disable),
DISPATCH_ENTRY_CORE (DrawArrays),
DISPATCH_ENTRY_CORE (DrawElements),
@@ -89,6 +90,7 @@ cairo_private cairo_gl_dispatch_entry_t dispatch_core_entries[] = {
DISPATCH_ENTRY_CORE (GetFloatv),
DISPATCH_ENTRY_CORE (GetIntegerv),
DISPATCH_ENTRY_CORE (GetString),
+ DISPATCH_ENTRY_CORE (GetStringi),
DISPATCH_ENTRY_CORE (PixelStorei),
DISPATCH_ENTRY_CORE (ReadPixels),
DISPATCH_ENTRY_CORE (Scissor),
@@ -102,17 +104,21 @@ cairo_private cairo_gl_dispatch_entry_t dispatch_core_entries[] = {
DISPATCH_ENTRY_CORE (DrawBuffer),
DISPATCH_ENTRY_CORE (ReadBuffer),
#endif
- DISPATCH_ENTRY_CORE (DepthMask),
DISPATCH_ENTRY_CORE (Viewport),
DISPATCH_ENTRY_LAST
};
cairo_private cairo_gl_dispatch_entry_t dispatch_buffers_entries[] = {
DISPATCH_ENTRY_ARB (GenBuffers),
+ DISPATCH_ENTRY_ARB (DeleteBuffers),
DISPATCH_ENTRY_ARB (BindBuffer),
DISPATCH_ENTRY_ARB (BufferData),
+ DISPATCH_ENTRY_ARB (BufferSubData),
DISPATCH_ENTRY_ARB_OES (MapBuffer),
DISPATCH_ENTRY_ARB_OES (UnmapBuffer),
+ DISPATCH_ENTRY_ARB (GenVertexArrays),
+ DISPATCH_ENTRY_ARB (DeleteVertexArrays),
+ DISPATCH_ENTRY_ARB (BindVertexArray),
DISPATCH_ENTRY_LAST
};
diff --git a/src/cairo-gl-dispatch.c b/src/cairo-gl-dispatch.c
index aaa234661..c38fe8cad 100755..100644
--- a/src/cairo-gl-dispatch.c
+++ b/src/cairo-gl-dispatch.c
@@ -111,7 +111,7 @@ _cairo_gl_dispatch_init_entries (cairo_gl_dispatch_t *dispatch,
static cairo_status_t
_cairo_gl_dispatch_init_buffers (cairo_gl_dispatch_t *dispatch,
cairo_gl_get_proc_addr_func_t get_proc_addr,
- void *data,
+ void *data,
int gl_version, cairo_gl_flavor_t gl_flavor)
{
cairo_gl_dispatch_name_t dispatch_name;
diff --git a/src/cairo-gl-ext-def-private.h b/src/cairo-gl-ext-def-private.h
index a261947be..9c11a9691 100755..100644
--- a/src/cairo-gl-ext-def-private.h
+++ b/src/cairo-gl-ext-def-private.h
@@ -140,4 +140,12 @@
#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
#endif
+#ifndef GL_NUM_EXTENSIONS
+#define GL_NUM_EXTENSIONS 0x821D
+#endif
+
+#ifndef GL_VERTEX_ARRAY_BINDING
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#endif
+
#endif /* CAIRO_GL_EXT_DEF_PRIVATE_H */
diff --git a/src/cairo-gl-filters.c b/src/cairo-gl-filters.c
index 7ddc4a246..612e599d5 100755..100644
--- a/src/cairo-gl-filters.c
+++ b/src/cairo-gl-filters.c
@@ -165,14 +165,12 @@ gaussian_filter_stage_1 (cairo_bool_t x_axis,
if (is_opaque)
_cairo_gl_shader_bind_float (ctx_out,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_ALPHA, CAIRO_GL_TEX_SOURCE),
- 1.0);
+ ctx_out->current_shader->alpha_location[CAIRO_GL_TEX_SOURCE],
+ 1.0);
else
_cairo_gl_shader_bind_float (ctx_out,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_ALPHA, CAIRO_GL_TEX_SOURCE),
- 0.0);
+ ctx_out->current_shader->alpha_location[CAIRO_GL_TEX_SOURCE],
+ 0.0);
rect.x = 0;
rect.y = 0;
@@ -212,7 +210,7 @@ gaussian_filter_stage_2 (cairo_bool_t y_axis,
col = original_pattern->base.x_radius * 2 + 1;
memset (&stage_2_src->operand.texture.coef[0], 0, sizeof (float) * row);
- compute_y_coef_to_float (original_pattern->base.convolution_matrix,
+ compute_y_coef_to_float (original_pattern->base.convolution_matrix,
row, col, &stage_2_src->operand.texture.coef[2]);
stage_2_src->operand.texture.y_radius = original_pattern->base.y_radius;
stage_2_src->operand.texture.x_radius = 1;
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 8e5892e6e..b28eef3bc 100755..100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -178,8 +178,8 @@ _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_bool_t has_component_alpha,
- cairo_gl_glyph_cache_t **cache_out)
+ cairo_bool_t has_component_alpha,
+ cairo_gl_glyph_cache_t **cache_out)
{
cairo_gl_glyph_cache_t *cache;
cairo_content_t content;
@@ -189,13 +189,12 @@ cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx,
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_ARGB32:
case CAIRO_FORMAT_RGB24:
- if (has_component_alpha) {
- cache = &ctx->glyph_cache[0];
- } else {
- cache = &ctx->glyph_cache[2];
- }
+ if (has_component_alpha) {
+ cache = &ctx->glyph_cache[0];
+ } else {
+ cache = &ctx->glyph_cache[2];
+ }
content = CAIRO_CONTENT_COLOR_ALPHA;
- break;
break;
case CAIRO_FORMAT_A8:
case CAIRO_FORMAT_A1:
@@ -275,7 +274,7 @@ render_glyphs (cairo_gl_surface_t *dst,
cairo_format_t last_format = CAIRO_FORMAT_INVALID;
cairo_gl_glyph_cache_t *cache = NULL;
cairo_gl_context_t *ctx;
- cairo_gl_emit_glyph_t emit;
+ cairo_gl_emit_glyph_t emit = NULL;
cairo_gl_composite_t setup;
cairo_int_status_t status;
int i = 0;
@@ -325,34 +324,35 @@ render_glyphs (cairo_gl_surface_t *dst,
{
continue;
}
+
if (! *has_component_alpha)
- *has_component_alpha = pixman_image_get_component_alpha (scaled_glyph->surface->pixman_image);
+ *has_component_alpha = pixman_image_get_component_alpha (scaled_glyph->surface->pixman_image);
/* color glyph has ARGB32 format and dst mask surface is ALPHA */
if (scaled_glyph->surface->format == CAIRO_FORMAT_ARGB32 &&
- dst->base.content == CAIRO_CONTENT_ALPHA &&
- *has_component_alpha == FALSE)
- return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+ dst->base.content == CAIRO_CONTENT_ALPHA &&
+ *has_component_alpha == FALSE)
+ return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
if (scaled_glyph->surface->format != last_format) {
status = cairo_gl_context_get_glyph_cache (ctx,
scaled_glyph->surface->format,
- *has_component_alpha,
+ *has_component_alpha,
&cache);
if (unlikely (status))
goto FINISH;
last_format = scaled_glyph->surface->format;
- if (! *has_component_alpha &&
+ if (! *has_component_alpha &&
cache->surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) {
/* we have color glyph */
_cairo_gl_composite_set_source_operand (&setup, &cache->surface->operand);
*is_color_glyph = TRUE;
- } else {
+ } else {
_cairo_gl_composite_set_mask_operand (&setup, &cache->surface->operand);
*is_color_glyph = FALSE;
- }
+ }
/* XXX Shoot me. */
if (dst->msaa_active)
@@ -407,6 +407,7 @@ render_glyphs (cairo_gl_surface_t *dst,
goto FINISH;
}
glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph);
+ assert (emit);
emit (ctx,
x1, y1, x2, y2,
glyph->p1.x, glyph->p1.y,
@@ -433,7 +434,7 @@ render_glyphs_via_mask (cairo_gl_surface_t *dst,
cairo_status_t status;
cairo_bool_t has_component_alpha;
cairo_gl_context_t *ctx;
- cairo_bool_t is_color_glyph;
+ cairo_bool_t is_color_glyph;
int width = info->extents.width;
int height = info->extents.height;
@@ -505,27 +506,27 @@ render_glyphs_via_mask (cairo_gl_surface_t *dst,
clip_extents.height = info->extents.height;
clip = _cairo_clip_intersect_rectangle (clip, &clip_extents);
- if(is_color_glyph) {
- if(op == CAIRO_OPERATOR_SOURCE) {
- /* do dest_out then add*/
- status = _cairo_surface_paint (&dst->base,
- CAIRO_OPERATOR_DEST_OUT,
- &mask_pattern.base,
- clip);
- status = _cairo_surface_paint (&dst->base,
- CAIRO_OPERATOR_ADD,
- &mask_pattern.base, clip);
- } else {
- status = _cairo_surface_paint (&dst->base,op,
- &mask_pattern.base,
- clip);
- }
- }
+ if (is_color_glyph) {
+ if (op == CAIRO_OPERATOR_SOURCE) {
+ /* do dest_out then add */
+ status = _cairo_surface_paint (&dst->base,
+ CAIRO_OPERATOR_DEST_OUT,
+ &mask_pattern.base,
+ clip);
+ status = _cairo_surface_paint (&dst->base,
+ CAIRO_OPERATOR_ADD,
+ &mask_pattern.base, clip);
+ } else {
+ status = _cairo_surface_paint (&dst->base, op,
+ &mask_pattern.base,
+ clip);
+ }
+ }
else
- status = _cairo_surface_mask (&dst->base, op,
- &source_pattern.base,
- &mask_pattern.base,
- clip);
+ status = _cairo_surface_mask (&dst->base, op,
+ &source_pattern.base,
+ &mask_pattern.base,
+ clip);
_cairo_clip_destroy (clip);
@@ -567,7 +568,7 @@ _cairo_gl_composite_glyphs_with_clip (void *_dst,
{
cairo_gl_surface_t *dst = _dst;
cairo_bool_t has_component_alpha;
- cairo_bool_t is_color_glyph;
+ cairo_bool_t is_color_glyph;
TRACE ((stderr, "%s\n", __FUNCTION__));
diff --git a/src/cairo-gl-gradient-private.h b/src/cairo-gl-gradient-private.h
index 024549e5d..d66f3dc3b 100755..100644
--- a/src/cairo-gl-gradient-private.h
+++ b/src/cairo-gl-gradient-private.h
@@ -3,6 +3,7 @@
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
* Copyright © 2005,2010 Red Hat, Inc
+ * Copyright © 2011,2015 Samsung Research America, Inc - Silicon Valley
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -36,6 +37,7 @@
* Carl Worth <cworth@cworth.org>
* Chris Wilson <chris@chris-wilson.co.uk>
* Eric Anholt <eric@anholt.net>
+ * Henry Songt <hsong@sisa.samsung.com>
*/
#ifndef CAIRO_GL_GRADIENT_PRIVATE_H
@@ -51,21 +53,26 @@
#include "cairo-gl.h"
-#if 0
#if CAIRO_HAS_EVASGL_SURFACE
-#include <Evas_GL.h>
+ #include <Evas_GL.h>
#else
- #if CAIRO_HAS_GL_SURFACE
- #include <GL/gl.h>
- #include <GL/glext.h>
- #elif CAIRO_HAS_GLESV2_SURFACE
- #include <GLES2/gl2.h>
- #include <GLES2/gl2ext.h>
- #elif CAIRO_HAS_GLESV3_SURFACE
- #include <GLES3/gl3.h>
- #include <GLES3/gl3ext.h>
- #endif
-#endif
+ #if CAIRO_HAS_GL_SURFACE
+ #if CAIRO_HAS_CGL_FUNCTIONS
+ #include <OpenGL/gl.h>
+ #include <OpenGL/glext.h>
+ #else
+ #include <GL/gl.h>
+ #include <GL/glext.h>
+ #endif
+ #elif CAIRO_HAS_GLESV2_SURFACE
+ #include <GLES2/gl2.h>
+ #include <GLES2/gl2ext.h>
+ #elif CAIRO_HAS_GLESV3_SURFACE
+ #include <GLES3/gl3.h>
+ #include <GLES3/gl3ext.h>
+ #elif CAIRO_HAS_EVASGL_SURFACE
+ #include <Evas_GL.h>
+ #endif
#endif
#define CAIRO_GL_GRADIENT_CACHE_SIZE 4096
@@ -77,7 +84,7 @@ typedef struct _cairo_gl_gradient {
cairo_cache_entry_t cache_entry;
cairo_reference_count_t ref_count;
cairo_device_t *device; /* NB: we don't hold a reference */
- unsigned int tex;
+ GLuint tex;
unsigned int n_stops;
const cairo_gradient_stop_t *stops;
cairo_gradient_stop_t stops_embedded[1];
diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index ddf869ead..2f8c725b6 100755..100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -290,7 +290,7 @@ _cairo_gl_gradient_create (cairo_gl_context_t *ctx,
ctx->dispatch.TexImage2D (ctx->tex_target, 0, internal_format,
tex_width, 1, 0,
- GL_BGRA, GL_UNSIGNED_BYTE, data);
+ GL_BGRA, GL_UNSIGNED_BYTE, data);
free (data);
diff --git a/src/cairo-gl-hairline-stroke.c b/src/cairo-gl-hairline-stroke.c
index 9ff59e502..7ce75d7c7 100755..100644
--- a/src/cairo-gl-hairline-stroke.c
+++ b/src/cairo-gl-hairline-stroke.c
@@ -46,6 +46,8 @@ _add_cap (cairo_gl_hairline_closure_t *hairline,
cairo_bool_t lead_cap,
cairo_point_t *outp)
{
+ // Do we really need cap?
+/*
double dx, dy;
if (hairline->cap_style == CAIRO_LINE_CAP_BUTT)
@@ -57,7 +59,7 @@ _add_cap (cairo_gl_hairline_closure_t *hairline,
cairo_matrix_transform_distance (hairline->ctm, &dx, &dy);
outp->x += _cairo_fixed_from_double (dx);
outp->y += _cairo_fixed_from_double (dy);
-
+*/
return TRUE;
}
@@ -121,20 +123,21 @@ _cairo_gl_hairline_style_is_hairline (const cairo_stroke_style_t *style,
x = fabs (x - 1.0);
y = fabs (y - 1.0);
+ // do not consider line join
return style->line_width == 1.0 &&
- (style->line_join != CAIRO_LINE_JOIN_MITER ||
- style->miter_limit <= 10.0) &&
(x <= SCALE_TOLERANCE && y <= SCALE_TOLERANCE);
}
static cairo_status_t
_path_add_first_and_last_cap (cairo_gl_hairline_closure_t *hairline)
{
+ // Do we really need caps and join for single point line?
+/*
cairo_point_t p[2];
cairo_status_t status = CAIRO_STATUS_SUCCESS;
cairo_bool_t needs_to_cap;
- /* check last point */
+ // check last point
if (hairline->initialized) {
if (! hairline->line_last_capped) {
p[0] = hairline->line_last_point;
@@ -166,7 +169,7 @@ _path_add_first_and_last_cap (cairo_gl_hairline_closure_t *hairline)
}
}
}
-
+*/
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-gl-info.c b/src/cairo-gl-info.c
index 33dc0cc56..fffea58b1 100755..100644
--- a/src/cairo-gl-info.c
+++ b/src/cairo-gl-info.c
@@ -32,6 +32,29 @@
#include "cairoint.h"
#include "cairo-gl-private.h"
+#include <errno.h>
+int _cairo_glsl_get_version (cairo_gl_dispatch_t *dispatch)
+{
+ int major, minor;
+ const char *version = (const char *) dispatch->GetString (GL_SHADING_LANGUAGE_VERSION);
+ const char *dot = version == NULL ? NULL : strchr (version, '.');
+ const char *major_start = dot;
+
+ /* Sanity check */
+ if (dot == NULL || dot == version || *(dot + 1) == '\0') {
+ major = 0;
+ minor = 0;
+ } else {
+ /* Find the start of the major version in the string */
+ while (major_start > version && *major_start != ' ')
+ --major_start;
+ major = strtol (major_start, NULL, 10);
+ minor = strtol (dot + 1, NULL, 10);
+ }
+
+ return CAIRO_GL_VERSION_ENCODE (major, minor);
+}
+
int _cairo_gl_get_version (cairo_gl_dispatch_t *dispatch)
{
int major, minor;
@@ -78,21 +101,54 @@ _cairo_gl_get_flavor (cairo_gl_dispatch_t *dispatch)
return flavor;
}
+unsigned long
+_cairo_gl_get_vbo_size (void)
+{
+ unsigned long vbo_size;
+
+ const char *env = getenv ("CAIRO_GL_VBO_SIZE");
+ if (env == NULL) {
+ vbo_size = CAIRO_GL_VBO_SIZE_DEFAULT;
+ } else {
+ errno = 0;
+ vbo_size = strtol (env, NULL, 10);
+ assert (errno == 0);
+ assert (vbo_size > 0);
+ }
+
+ return vbo_size;
+}
+
cairo_bool_t
_cairo_gl_has_extension (cairo_gl_dispatch_t *dispatch, const char *ext)
{
- const char *extensions = (const char *) dispatch->GetString (GL_EXTENSIONS);
- size_t len = strlen (ext);
- const char *ext_ptr = extensions;
+ int version = _cairo_gl_get_version (dispatch);
+ if (version >= CAIRO_GL_VERSION_ENCODE (3, 0)) {
+ GLuint max_num_extensions;
+ int i;
+ dispatch->GetIntegerv (GL_NUM_EXTENSIONS, &max_num_extensions);
- if (unlikely (ext_ptr == NULL))
- return 0;
+ for (i = 0; i < max_num_extensions; i++) {
+ const char *extension = (const char *) dispatch->GetStringi (GL_EXTENSIONS, i);
+ if (strstr (extension, ext) == 0)
+ return TRUE;
+ }
+ return FALSE;
+ } else {
+ const char *extensions = (const char *) dispatch->GetString (GL_EXTENSIONS);
+ size_t len = strlen (ext);
+ const char *ext_ptr = extensions;
+
- while ((ext_ptr = strstr (ext_ptr, ext)) != NULL) {
- if (ext_ptr[len] == ' ' || ext_ptr[len] == '\0')
- break;
- ext_ptr += len;
- }
+ if (unlikely (ext_ptr == NULL))
+ return 0;
+
+ while ((ext_ptr = strstr (ext_ptr, ext)) != NULL) {
+ if (ext_ptr[len] == ' ' || ext_ptr[len] == '\0')
+ break;
+ ext_ptr += len;
+ }
- return (ext_ptr != NULL);
+ return (ext_ptr != NULL);
+ }
}
diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 7ce5c7a4b..99d8cc01a 100755..100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -47,6 +47,7 @@
#include "cairo-gl-private.h"
#include "cairo-path-private.h"
#include "cairo-traps-private.h"
+#include "cairo-convex-fill-private.h"
static cairo_bool_t
can_use_msaa_compositor (cairo_gl_surface_t *surface,
@@ -151,8 +152,8 @@ _draw_traps (cairo_gl_context_t *ctx,
static cairo_int_status_t
_draw_int_rect (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup,
- cairo_rectangle_int_t *rect)
+ cairo_gl_composite_t *setup,
+ cairo_rectangle_int_t *rect)
{
int quad[8];
@@ -536,10 +537,12 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
status = _draw_int_rect (ctx, &setup, &composite->bounded);
else
status = _draw_traps (ctx, &setup, &traps);
+ if (unlikely (status))
+ goto finish;
/* Now draw the second pass. */
status = _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD,
- FALSE /* assume_component_alpha */);
+ FALSE /* assume_component_alpha */);
if (unlikely (status))
goto finish;
status = _cairo_gl_composite_set_source (&setup,
@@ -716,7 +719,7 @@ _cairo_gl_msaa_compositor_mask (const cairo_compositor_t *compositor,
if (clip) {
cairo_clip_t *clip_copy = _cairo_clip_copy (clip);
-
+
clip_copy = _cairo_clip_intersect_rectangle (clip_copy, &rect);
status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup,
clip_copy);
@@ -769,6 +772,59 @@ _stroke_shaper_add_triangle_fan (void *closure,
}
static cairo_status_t
+_fill_add_triangle_fan (void *closure,
+ const cairo_point_t *points,
+ int npoints)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ int n = npoints - 1, idx = 1;
+ cairo_bool_t done = FALSE;
+ struct _tristrip_composite_info *info = closure;
+ cairo_point_t triangle[3], quad[4];
+ cairo_point_t midp = points[0];
+
+ if (n <= 1)
+ return status;
+ else if (n <= 2) {
+ triangle[0] = midp;
+ triangle[1] = points[idx];
+ triangle[2] = points[++idx];
+ return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx, &info->setup, triangle);
+ }
+ else {
+ quad[0] = midp;
+ quad[1] = points[idx];
+ quad[2] = points[++idx];
+ quad[3] = points[++idx];
+ n -= 3;
+ status = _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup, quad);
+ }
+
+ while (! done) {
+ if (n == 0)
+ break;
+ if (n == 1) {
+ triangle[0] = midp;
+ triangle[1] = points[idx];
+ triangle[2] = points[++idx];
+ status = _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx, &info->setup, triangle);
+ break;
+ }
+ else {
+ quad[0] = midp;
+ quad[1] = points[idx];
+ quad[2] = points[++idx];
+ quad[3] = points[++idx];
+ n -= 2;
+ status = _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup, quad);
+ if (unlikely (status))
+ break;
+ }
+ }
+ return status;
+}
+
+static cairo_status_t
_stroke_shaper_add_quad (void *closure,
const cairo_point_t quad[4])
{
@@ -918,9 +974,9 @@ _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t *compositor,
if (stroke_extents.width != 0 &&
stroke_extents.height != 0) {
- if ((stroke_extents.width / stroke_extents.height > 10 &&
+ if ((stroke_extents.width / stroke_extents.height > 10 &&
stroke_extents.height < 10) ||
- (stroke_extents.height / stroke_extents.width > 10 &&
+ (stroke_extents.height / stroke_extents.width > 10 &&
stroke_extents.width < 10)) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -981,14 +1037,23 @@ _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t *compositor,
if (_cairo_gl_hairline_style_is_hairline (style, ctm)) {
cairo_gl_hairline_closure_t closure;
+ /* prevent overlapping is very expensive, we should avoid it
+ at all cost. In case of hairline, the overlapping occurs
+ on a single pixel and is almost indistinguishable. To
+ trade-off quality vs performance, for hairline, we disable
+ overlapping
+ */
+ /*
if (! (_is_continuous_arc (path, style) ||
- _is_continuous_single_line (path, style))) {
+ _is_continuous_single_line (path, style) ||
+ path->is_convex)) {
status = _prevent_overlapping_strokes (info.ctx, &info.setup,
composite, path,
style, ctm);
if (unlikely (status))
goto finish;
}
+ */
closure.ctx = info.ctx;
@@ -1045,7 +1110,6 @@ _draw_simple_quad_path (cairo_gl_context_t *ctx,
cairo_point_t triangle[3];
cairo_int_status_t status;
const cairo_point_t *points;
-
points = cairo_path_head (path)->points;
triangle[0] = points[0];
@@ -1076,6 +1140,7 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor,
cairo_traps_t traps;
cairo_bool_t draw_path_with_traps;
cairo_rectangle_int_t fill_extents;
+ struct _tristrip_composite_info info;
if (! can_use_msaa_compositor (dst, antialias))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -1084,9 +1149,9 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor,
_cairo_path_fixed_approximate_fill_extents (path, &fill_extents);
if (fill_extents.width != 0 && fill_extents.height != 0) {
- if ((fill_extents.width / fill_extents.height > 10 &&
+ if ((fill_extents.width / fill_extents.height > 10 &&
fill_extents.height < 10) ||
- (fill_extents.height / fill_extents.width > 10 &&
+ (fill_extents.height / fill_extents.width > 10 &&
fill_extents.width < 10)) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -1122,13 +1187,6 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor,
draw_path_with_traps = ! _cairo_path_fixed_is_simple_quad (path);
- if (draw_path_with_traps) {
- _cairo_traps_init (&traps);
- status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
- if (unlikely (status))
- goto cleanup_traps;
- }
-
status = _cairo_gl_composite_init (&setup,
composite->op,
dst,
@@ -1147,15 +1205,44 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor,
_cairo_gl_msaa_compositor_set_clip (composite, &setup);
if (antialias != CAIRO_ANTIALIAS_NONE)
_cairo_gl_composite_set_multisample (&setup);
-
+
status = _cairo_gl_composite_begin (&setup, &ctx);
if (unlikely (status))
goto cleanup_setup;
- if (! draw_path_with_traps)
+ if(path->is_convex) {
+
+ cairo_convex_fill_closure_t filler;
+ filler.tolerance = tolerance;
+ info.ctx = ctx;
+ info.setup = setup;
+ filler.closure = &info;
+ filler.midp_added = FALSE;
+ status = _cairo_path_fixed_fill_to_convex((*_fill_add_triangle_fan),
+ path,
+ _cairo_convex_fill_move_to,
+ _cairo_convex_fill_line_to,
+ _cairo_convex_fill_curve_to,
+ _cairo_convex_fill_close_path,
+ &filler);
+ if (unlikely (status))
+ goto cleanup_setup;
+
+ }
+ else if (draw_path_with_traps) {
+ _cairo_traps_init (&traps);
+ status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
+ if (unlikely (status))
+ goto cleanup_traps;
+ }
+
+ if (!path->is_convex && ! draw_path_with_traps)
status = _draw_simple_quad_path (ctx, &setup, path);
else
- status = _draw_traps (ctx, &setup, &traps);
+ {
+ if(!path->is_convex)
+ status = _draw_traps (ctx, &setup, &traps);
+ }
if (unlikely (status))
goto cleanup_setup;
@@ -1168,7 +1255,7 @@ cleanup_setup:
status = _cairo_gl_context_release (ctx, status);
cleanup_traps:
- if (draw_path_with_traps)
+ if (draw_path_with_traps && !path->is_convex)
_cairo_traps_fini (&traps);
return status;
@@ -1215,7 +1302,13 @@ _cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t *compositor,
return _paint_back_unbounded_surface (compositor, composite, surface);
}
-
+/*
+ if (scaled_font->options.antialias != CAIRO_ANTIALIAS_NONE) {
+ status = _blit_texture_to_renderbuffer (dst);
+ if (unlikely (status))
+ return status;
+ }
+*/
src = _cairo_gl_pattern_to_source (&dst->base,
composite->original_source_pattern,
FALSE,
@@ -1253,6 +1346,7 @@ _cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t *compositor,
dst->content_synced = FALSE;
finish:
+ if (src)
cairo_surface_destroy (src);
return status;
@@ -1264,7 +1358,6 @@ _cairo_gl_msaa_compositor_init (cairo_compositor_t *compositor,
{
compositor->delegate = delegate;
compositor->lazy_init = TRUE;
-
compositor->paint = _cairo_gl_msaa_compositor_paint;
compositor->mask = _cairo_gl_msaa_compositor_mask;
compositor->fill = _cairo_gl_msaa_compositor_fill;
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index 8c21e6985..2bbd99b74 100755..100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -119,7 +119,7 @@ _cairo_gl_copy_texture (cairo_gl_surface_t *surface,
/* paint image to dst */
_cairo_pattern_init_for_surface (&pattern, &image->base);
- cairo_matrix_init_translate (&pattern.base.matrix,
+ cairo_matrix_init_translate (&pattern.base.matrix,
-dst_x + src_x, -dst_y + src_y);
rect.x = dst_x;
@@ -231,7 +231,7 @@ _cairo_gl_image_cache_replace_image (cairo_gl_image_t *image_node,
{
cairo_int_status_t status;
/* Paint image to cache. */
- status = _cairo_gl_copy_texture (dst, cache_surface,
+ status = _cairo_gl_copy_texture (dst, cache_surface,
image, image_node->node.x,
image_node->node.y,
0, 0,
@@ -256,7 +256,7 @@ _cairo_gl_image_cache_add_image (cairo_gl_context_t *ctx,
if (! image->base.device ||
(image->width >= IMAGE_CACHE_MAX_SIZE ||
- image->height >= IMAGE_CACHE_MAX_SIZE))
+ image->height >= IMAGE_CACHE_MAX_SIZE))
return CAIRO_INT_STATUS_UNSUPPORTED;
else if (! _cairo_gl_surface_is_texture (image))
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -350,7 +350,7 @@ _cairo_gl_image_cache_add_image (cairo_gl_context_t *ctx,
status = _cairo_gl_copy_texture (dst, ctx->image_cache->surface,
image, node->x, node->y,
0, 0,
- image->width, image->height,
+ image->width, image->height,
FALSE, &ctx);
if (unlikely (status))
return status;
@@ -528,7 +528,7 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
operand->texture.texgen = use_texgen;
- if (blur_surface == surface &&
+ if (blur_surface == surface &&
surface->needs_to_cache &&
surface->base.device) {
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
@@ -562,11 +562,10 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
operand->texture.p2.x = (double) blur_extents.width / (double) blur_surface->width;
operand->texture.p2.y = (double) blur_extents.height / (double) blur_surface->height;
- operand->texture.p1.x += 0.5 / blur_surface->width;
- operand->texture.p1.y += 0.5 / blur_surface->height;
- operand->texture.p2.x -= 0.5 / blur_surface->width;
- operand->texture.p2.y -= 0.5 / blur_surface->height;
-
+ operand->texture.p1.x += 0.5 / blur_surface->width;
+ operand->texture.p1.y += 0.5 / blur_surface->height;
+ operand->texture.p2.x -= 0.5 / blur_surface->width;
+ operand->texture.p2.y -= 0.5 / blur_surface->height;
operand->texture.surface = blur_surface;
operand->texture.owns_surface = NULL;
@@ -597,19 +596,18 @@ _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
operand->texture.p2.x = image_node->p2.x;
operand->texture.p2.y = image_node->p2.y;
- operand->texture.p1.x += 0.5 / ctx->image_cache->surface->width;
- operand->texture.p1.y += 0.5 / ctx->image_cache->surface->height;
- operand->texture.p2.x -= 0.5 / ctx->image_cache->surface->width;
- operand->texture.p2.y -= 0.5 / ctx->image_cache->surface->height;
-
+ operand->texture.p1.x += 0.5 / ctx->image_cache->surface->width;
+ operand->texture.p1.y += 0.5 / ctx->image_cache->surface->height;
+ operand->texture.p2.x -= 0.5 / ctx->image_cache->surface->width;
+ operand->texture.p2.y -= 0.5 / ctx->image_cache->surface->height;
cairo_matrix_multiply (&attributes->matrix,
&matrix,
&ctx->image_cache->surface->operand.texture.attributes.matrix);
}
+ cairo_surface_destroy (&blur_surface->base);
status = CAIRO_STATUS_SUCCESS;
- cairo_surface_destroy (&blur_surface->base);
if (ctx_acquired)
return _cairo_gl_context_release (ctx, status);
@@ -674,8 +672,8 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
operand->texture.texgen = use_texgen;
- if (surface->base.device &&
- blur_surface == surface &&
+ if (surface->base.device &&
+ blur_surface == surface &&
surface->needs_to_cache) {
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (status == CAIRO_INT_STATUS_SUCCESS) {
@@ -703,11 +701,10 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
operand->texture.p2.x = (double) blur_extents.width / (double) blur_surface->width;
operand->texture.p2.y = (double) blur_extents.height / (double) blur_surface->height;
- operand->texture.p1.x += 0.5 / blur_surface->width;
- operand->texture.p1.y += 0.5 / blur_surface->height;
- operand->texture.p2.x -= 0.5 / blur_surface->width;
- operand->texture.p2.y -= 0.5 / blur_surface->height;
-
+ operand->texture.p1.x += 0.5 / blur_surface->width;
+ operand->texture.p1.y += 0.5 / blur_surface->height;
+ operand->texture.p2.x -= 0.5 / blur_surface->width;
+ operand->texture.p2.y -= 0.5 / blur_surface->height;
operand->texture.surface = blur_surface;
operand->texture.owns_surface = NULL;
@@ -733,11 +730,10 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
operand->texture.p2.x = image_node->p2.x;
operand->texture.p2.y = image_node->p2.y;
- operand->texture.p1.x += 0.5 / ctx->image_cache->surface->width;
- operand->texture.p1.y += 0.5 / ctx->image_cache->surface->height;
- operand->texture.p2.x -= 0.5 / ctx->image_cache->surface->width;
- operand->texture.p2.y -= 0.5 / ctx->image_cache->surface->height;
-
+ operand->texture.p1.x += 0.5 / ctx->image_cache->surface->width;
+ operand->texture.p1.y += 0.5 / ctx->image_cache->surface->height;
+ operand->texture.p2.x -= 0.5 / ctx->image_cache->surface->width;
+ operand->texture.p2.y -= 0.5 / ctx->image_cache->surface->height;
operand->texture.surface = ctx->image_cache->surface;
operand->texture.owns_surface = NULL;
@@ -749,9 +745,9 @@ _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
&ctx->image_cache->surface->operand.texture.attributes.matrix);
}
- cairo_surface_destroy (&blur_surface->base);
status = CAIRO_STATUS_SUCCESS;
+ cairo_surface_destroy (&blur_surface->base);
if (ctx_acquired)
return _cairo_gl_context_release (ctx, status);
@@ -825,7 +821,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
operand->texture.attributes.matrix.x0 -= extents->x * operand->texture.attributes.matrix.xx;
operand->texture.attributes.matrix.y0 -= extents->y * operand->texture.attributes.matrix.yy;
- if (_cairo_gl_surface_is_texture (dst) &&
+ if (_cairo_gl_surface_is_texture (dst) &&
dst->width <= IMAGE_CACHE_MAX_SIZE &&
dst->height <= IMAGE_CACHE_MAX_SIZE &&
! dst->force_no_cache)
@@ -1128,7 +1124,7 @@ _cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand)
cairo_bool_t
_cairo_gl_operand_get_use_atlas (cairo_gl_operand_t *operand)
{
- if (operand->type != CAIRO_GL_OPERAND_TEXTURE &&
+ if (operand->type != CAIRO_GL_OPERAND_TEXTURE &&
operand->type != CAIRO_GL_OPERAND_GAUSSIAN)
return FALSE;
@@ -1201,30 +1197,27 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
return;
_cairo_gl_shader_bind_vec4 (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_CONSTANT, tex_unit),
- operand->constant.color[0],
- operand->constant.color[1],
- operand->constant.color[2],
- operand->constant.color[3]);
- return;
+ 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:
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
_cairo_gl_shader_bind_float (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_A, tex_unit),
+ ctx->current_shader->a_location[tex_unit],
operand->gradient.a);
/* fall through */
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
- _cairo_gl_shader_bind_vec3 (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_CIRCLE_D, tex_unit),
+ _cairo_gl_shader_bind_vec3 (ctx,
+ ctx->current_shader->circle_d_location[tex_unit],
operand->gradient.circle_d.center.x,
operand->gradient.circle_d.center.y,
operand->gradient.circle_d.radius);
_cairo_gl_shader_bind_float (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_RADIUS_0, tex_unit),
+ ctx->current_shader->radius_0_location[tex_unit],
operand->gradient.radius_0);
/* fall through */
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
@@ -1252,8 +1245,7 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
}
if (operand->type != CAIRO_GL_OPERAND_GAUSSIAN)
_cairo_gl_shader_bind_vec2 (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_TEXDIMS, tex_unit),
+ ctx->current_shader->texdims_location[tex_unit],
width, height);
}
@@ -1266,60 +1258,52 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
float y_axis = 0.0;
float temp_width;
float near_zero = 0.00001;
+ _cairo_gl_shader_bind_float (ctx,
+ ctx->current_shader->blur_x_axis_location[tex_unit],
+ x_axis);
+
+ _cairo_gl_shader_bind_float (ctx,
+ ctx->current_shader->blur_y_axis_location[tex_unit],
+ y_axis);
- _cairo_gl_shader_bind_float (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLUR_X_AXIS, tex_unit),
- x_axis);
- _cairo_gl_shader_bind_float (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLUR_Y_AXIS, tex_unit),
- y_axis);
_cairo_gl_shader_bind_int (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLUR_RADIUS, tex_unit),
- operand->texture.x_radius);
+ ctx->current_shader->blur_radius_location[tex_unit],
+ operand->texture.x_radius);
temp_width = cairo_gl_surface_get_width (&operand->texture.surface->base);
temp_width = (temp_width == 0) ? near_zero : temp_width;
_cairo_gl_shader_bind_float (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLUR_STEP, tex_unit),
- 1.0 / temp_width);
+ ctx->current_shader->blur_step_location[tex_unit],
+ 1.0 / temp_width);
_cairo_gl_shader_bind_float_array (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLURS, tex_unit),
- operand->texture.x_radius * 2 + 1,
- &operand->texture.coef[0]);
+ ctx->current_shader->blurs_location [tex_unit],
+ operand->texture.x_radius * 2 + 1,
+ operand->texture.coef);
}
else if (operand->type == CAIRO_GL_OPERAND_GAUSSIAN &&
operand->pass == 2) {
float x_axis = 0.0;
float y_axis = 1.0;
+ _cairo_gl_shader_bind_float (ctx,
+ ctx->current_shader->blur_x_axis_location[tex_unit],
+ x_axis);
+
+ _cairo_gl_shader_bind_float (ctx,
+ ctx->current_shader->blur_y_axis_location[tex_unit],
+ y_axis);
- _cairo_gl_shader_bind_float (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLUR_X_AXIS, tex_unit),
- x_axis);
- _cairo_gl_shader_bind_float (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLUR_Y_AXIS, tex_unit),
- y_axis);
_cairo_gl_shader_bind_int (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLUR_RADIUS, tex_unit),
- operand->texture.y_radius);
+ ctx->current_shader->blur_radius_location[tex_unit],
+ operand->texture.y_radius);
- _cairo_gl_shader_bind_float (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLUR_STEP, tex_unit),
- 1.0 / cairo_gl_surface_get_height (&operand->texture.surface->base));
+ _cairo_gl_shader_bind_float (ctx,
+ ctx->current_shader->blur_step_location[tex_unit],
+ 1.0 / cairo_gl_surface_get_height (&operand->texture.surface->base));
_cairo_gl_shader_bind_float_array (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_BLURS, tex_unit),
+ ctx->current_shader->blurs_location[tex_unit],
operand->texture.y_radius * 2 + 1,
&operand->texture.coef[0]);
}
@@ -1332,12 +1316,10 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
if (operand->gradient.texgen)
texgen = &operand->gradient.m;
}
-
if (texgen) {
- _cairo_gl_shader_bind_matrix (ctx,
- _cairo_gl_shader_uniform_for_texunit (
- CAIRO_GL_UNIFORM_TEXGEN, tex_unit),
- texgen);
+ _cairo_gl_shader_bind_matrix(ctx,
+ ctx->current_shader->texgen_location[tex_unit],
+ texgen);
}
}
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index c46a3e8cc..ad08abd9f 100755..100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -4,6 +4,7 @@
* Copyright © 2009 Chris Wilson
* Copyright © 2005,2010 Red Hat, Inc
* Copyright © 2011 Linaro Limited
+ * Copyright © 2011,2015 Samsung Research America, Inc - Silicon Valley
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -39,6 +40,7 @@
* Eric Anholt <eric@anholt.net>
* T. Zachary Laine <whatwasthataddress@gmail.com>
* Alexandros Frantzis <alexandros.frantzis@linaro.org>
+ * Henry Song <hsong@sisa.samsung.com>
*/
#ifndef CAIRO_GL_PRIVATE_H
@@ -62,11 +64,16 @@
#include <assert.h>
#if CAIRO_HAS_EVASGL_SURFACE
-#include <Evas_GL.h>
+ #include <Evas_GL.h>
#else
#if CAIRO_HAS_GL_SURFACE
+ #if CAIRO_HAS_CGL_FUNCTIONS
+ #include <OpenGL/gl.h>
+ #include <OpenGL/glext.h>
+ #else
#include <GL/gl.h>
#include <GL/glext.h>
+ #endif
#elif CAIRO_HAS_GLESV2_SURFACE
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
@@ -76,7 +83,6 @@
#endif
#endif
-
#include "cairo-gl-ext-def-private.h"
#define DEBUG_GL 0
@@ -104,8 +110,9 @@
/* VBO size that we allocate, smaller size means we gotta flush more often,
* but larger means hogging more memory and can cause trouble for drivers
- * (especially on embedded devices). */
-#define CAIRO_GL_VBO_SIZE (16*1024)
+ * (especially on embedded devices). Use the CAIRO_GL_VBO_SIZE environment
+ * variable to set this to a different size. */
+#define CAIRO_GL_VBO_SIZE_DEFAULT (1024*1024)
#define MIN_IMAGE_CACHE_WIDTH 512
#define MIN_IMAGE_CACHE_HEIGHT 512
@@ -142,7 +149,7 @@ typedef enum cairo_gl_flavor {
CAIRO_GL_FLAVOR_ES3 = 3
} cairo_gl_flavor_t;
-/* The order here is sensitive because of the logic of
+/* The order here is sensitive because of the logic of
*_cairo_gl_shader_uniform_for_texunit. */
typedef enum cairo_gl_uniform_t {
CAIRO_GL_UNIFORM_TEXDIMS, /* "source_texdims" */
@@ -310,7 +317,19 @@ typedef enum cairo_gl_tex {
typedef struct cairo_gl_shader {
GLuint fragment_shader;
GLuint program;
- GLint uniforms[CAIRO_GL_UNIFORM_MAX];
+ GLint mvp_location;
+ GLint constant_location[2];
+ GLint a_location[2];
+ GLint circle_d_location[2];
+ GLint radius_0_location[2];
+ GLint texdims_location[2];
+ GLint texgen_location[2];
+ GLint blur_radius_location[2];
+ GLint blurs_location[2];
+ GLint blur_step_location[2];
+ GLint blur_x_axis_location[2];
+ GLint blur_y_axis_location[2];
+ GLint alpha_location[2];
} cairo_gl_shader_t;
typedef struct _cairo_gl_image_cache {
@@ -406,7 +425,7 @@ typedef struct _cairo_gl_dispatch {
void (*ClearStencil) (GLint s);
void (*ColorMask) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
void (*DeleteTextures) (GLsizei n, const GLuint *textures);
- void (*DepthMask)(GLboolean flag);
+ void (*DepthMask) (GLboolean flag);
void (*Disable) (GLenum cap);
void (*DrawArrays) (GLenum mode, GLint first, GLsizei count);
void (*DrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
@@ -418,6 +437,7 @@ typedef struct _cairo_gl_dispatch {
void (*GetFloatv) (GLenum pname, GLfloat *data);
void (*GetIntegerv) (GLenum pname, GLint *data);
const GLubyte *(*GetString) (GLenum pname);
+ const GLubyte *(*GetStringi) (GLenum pname, GLuint i);
void (*PixelStorei) (GLenum pname, GLint param);
void (*ReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type, GLvoid *data);
@@ -442,11 +462,17 @@ typedef struct _cairo_gl_dispatch {
/* Buffers */
void (*GenBuffers) (GLsizei n, GLuint *buffers);
+ void (*DeleteBuffers) (GLsizei n, const GLuint *buffers);
void (*BindBuffer) (GLenum target, GLuint buffer);
void (*BufferData) (GLenum target, GLsizeiptr size,
const GLvoid* data, GLenum usage);
+ void (*BufferSubData) (GLenum target, GLintptr offset,
+ GLsizeiptr size, const GLvoid *data);
GLvoid *(*MapBuffer) (GLenum target, GLenum access);
GLboolean (*UnmapBuffer) (GLenum target);
+ void (*GenVertexArrays) (GLsizei n, GLuint *arrays);
+ void (*BindVertexArray) (GLuint array);
+ void (*DeleteVertexArrays) (GLsizei n, const GLuint *arrays);
/* Shaders */
GLuint (*CreateShader) (GLenum type);
@@ -540,6 +566,9 @@ typedef struct _cairo_gl_states {
cairo_bool_t scissor_test_enabled;
cairo_bool_t stencil_test_enabled;
+ GLuint bound_vbo;
+ GLuint bound_vao;
+ GLuint bound_ibo;
} cairo_gl_states_t;
struct _cairo_gl_context {
@@ -547,7 +576,6 @@ struct _cairo_gl_context {
const cairo_compositor_t *compositor;
- GLuint texture_load_pbo;
GLint max_framebuffer_size;
GLint max_texture_size;
GLint max_textures;
@@ -556,6 +584,9 @@ struct _cairo_gl_context {
GLint num_samples;
cairo_bool_t supports_msaa;
char *vb;
+ GLuint vbo;
+ GLuint vao;
+ GLuint ibo;
cairo_bool_t has_shader_support;
@@ -565,9 +596,9 @@ struct _cairo_gl_context {
cairo_cache_t gradients;
- /* cache[0] for gray font, cache[1] for rgba component alpha
- * cache[2] for color glyph */
- cairo_gl_glyph_cache_t glyph_cache[3];
+ /* cache[0] for gray font, cache[1] for rgba component alpha
+ * cache[2] for color glyph */
+ cairo_gl_glyph_cache_t glyph_cache[3];
cairo_list_t fonts;
cairo_gl_surface_t *current_target;
@@ -578,6 +609,7 @@ struct _cairo_gl_context {
cairo_gl_operand_t operands[2];
cairo_bool_t spans;
+ unsigned int vbo_size;
unsigned int vb_offset;
unsigned int vertex_size;
cairo_region_t *clip_region;
@@ -593,6 +625,7 @@ struct _cairo_gl_context {
cairo_bool_t has_packed_depth_stencil;
cairo_bool_t has_npot_repeat;
cairo_bool_t can_read_bgra;
+ cairo_bool_t is_gl33;
cairo_bool_t thread_aware;
@@ -755,7 +788,7 @@ _cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx);
cairo_private cairo_gl_emit_glyph_t
_cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx,
- const cairo_bool_t is_color_glyph);
+ const cairo_bool_t is_color_glyph);
cairo_private void
_cairo_gl_context_activate (cairo_gl_context_t *ctx,
@@ -804,6 +837,45 @@ _enable_scissor_buffer (cairo_gl_context_t *ctx)
}
}
+static cairo_always_inline void
+_cairo_gl_ensure_drawbuffers (cairo_gl_context_t *ctx)
+{
+ GLint vbo, ibo, vao;
+
+ if ((ctx->vao != 0 &&
+ (ctx->vao != ctx->states_cache.bound_vao))) {
+ ctx->dispatch.GetIntegerv (GL_VERTEX_ARRAY_BINDING, &vao);
+ if (vao != ctx->states_cache.bound_vao) {
+ ctx->dispatch.BindVertexArray (ctx->vao);
+ ctx->states_cache.bound_vao = ctx->vao;
+
+ ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, ctx->vbo);
+ ctx->states_cache.bound_vbo = ctx->vbo;
+
+ ctx->dispatch.BindBuffer (GL_ELEMENT_ARRAY_BUFFER, ctx->ibo);
+ ctx->states_cache.bound_ibo = ctx->ibo;
+ }
+ }
+
+ if ((ctx->vbo != 0 &&
+ (ctx->vbo != ctx->states_cache.bound_vbo))) {
+ ctx->dispatch.GetIntegerv (GL_ARRAY_BUFFER_BINDING, &vbo);
+ if (vbo != (GLint) ctx->states_cache.bound_vbo) {
+ ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, ctx->vbo);
+ }
+ ctx->states_cache.bound_vbo = ctx->vbo;
+ }
+
+ if ((ctx->ibo != 0 &&
+ (ctx->ibo != ctx->states_cache.bound_ibo))) {
+ ctx->dispatch.GetIntegerv (GL_ELEMENT_ARRAY_BUFFER_BINDING, &ibo);
+ if (ibo != (GLint) ctx->states_cache.bound_ibo) {
+ ctx->dispatch.BindBuffer (GL_ELEMENT_ARRAY_BUFFER, ctx->ibo);
+ }
+ ctx->states_cache.bound_ibo = ctx->ibo;
+ }
+}
+
cairo_private cairo_status_t
_cairo_gl_composite_init (cairo_gl_composite_t *setup,
cairo_operator_t op,
@@ -886,6 +958,12 @@ _cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t *ctx,
const cairo_point_t triangle[3]);
cairo_private cairo_int_status_t
+_cairo_gl_composite_emit_triangle_fan (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ const cairo_point_t *fan,
+ int count);
+
+cairo_private cairo_int_status_t
_cairo_gl_composite_emit_point_as_tristrip_line (cairo_gl_context_t *ctx,
const cairo_point_t point[2],
cairo_bool_t start_point);
@@ -944,49 +1022,49 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
cairo_private cairo_gl_uniform_t
_cairo_gl_shader_uniform_for_texunit (cairo_gl_uniform_t uniform,
- cairo_gl_tex_t tex_unit);
+ cairo_gl_tex_t tex_unit);
cairo_private void
_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
float value);
cairo_private void
_cairo_gl_shader_bind_float_array (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
int num, float *values);
cairo_private void
_cairo_gl_shader_bind_int (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
int value);
cairo_private void
_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
float value0, float value1);
cairo_private void
_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
float value0,
float value1,
float value2);
cairo_private void
_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
float value0, float value1,
float value2, float value3);
cairo_private void
_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
const cairo_matrix_t* m);
cairo_private void
_cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
GLfloat* gl_m);
cairo_private void
@@ -999,9 +1077,15 @@ _cairo_gl_shader_fini (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader);
cairo_private int
_cairo_gl_get_version (cairo_gl_dispatch_t *dispatch);
+cairo_private int
+_cairo_glsl_get_version (cairo_gl_dispatch_t *dispatch);
+
cairo_private cairo_gl_flavor_t
_cairo_gl_get_flavor (cairo_gl_dispatch_t *dispatch);
+cairo_private unsigned long
+_cairo_gl_get_vbo_size (void);
+
cairo_private cairo_bool_t
_cairo_gl_has_extension (cairo_gl_dispatch_t *dispatch, const char *ext);
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 0f8073ba6..7d7b669a8 100755..100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -44,50 +44,40 @@
#include "cairo-error-private.h"
#include "cairo-output-stream-private.h"
-static GLint
-_cairo_gl_shader_get_uniform_location (cairo_gl_context_t *ctx,
- cairo_gl_shader_t *shader,
- cairo_gl_uniform_t uniform)
+enum {
+ CAIRO_GLSL_VERSION_UNKNOWN,
+ CAIRO_GLSL_VERSION_330,
+ CAIRO_GLSL_VERSION_NON_330
+};
+
+static int needs_glsl330 = CAIRO_GLSL_VERSION_UNKNOWN;
+/*static const char[] glsl330_frag_out = "fsColorOut";
+static const char[] non_glsl330_frag_out = "gl_FragColor";
+static const char[] glsl330_in_attrib = "in";
+static const char[] non_glsl330_in_attrib = "attribute";
+static const char[] glsl330_out_attrib = "varying";
+static const char[] non_glsl330_out_attrib = "out";
+static const char[] glsl330 = "#version 330";
+*/
+static cairo_bool_t _cairo_needs_glsl330 (cairo_gl_context_t *ctx)
{
- /* This should be kept in sync with the enum
- * definition in cairo-gl-private.h. */
- const char *names[CAIRO_GL_UNIFORM_MAX] = {
- "source_texdims",
- "source_texgen",
- "source_constant",
- "source_sampler",
- "source_a",
- "source_circle_d",
- "source_radius_0",
- "source_blur_radius",
- "source_blurs",
- "source_blur_step",
- "source_blur_x_axis",
- "source_blur_y_axis",
- "source_alpha",
- "mask_texdims",
- "mask_texgen",
- "mask_constant",
- "mask_sampler",
- "mask_a",
- "mask_circle_d",
- "mask_radius_0",
- "mask_blur_radius",
- "mask_blurs",
- "mask_blur_step",
- "mask_blur_x_axis",
- "mask_blur_y_axis",
- "mask_alpha",
- "ModelViewProjectionMatrix"
- };
-
- if (shader->uniforms[uniform] != -1)
- return shader->uniforms[uniform];
+ int version;
+ cairo_gl_flavor_t flavor;
+
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_UNKNOWN) {
+ version = _cairo_glsl_get_version (&ctx->dispatch);
+ flavor = _cairo_gl_get_flavor (&ctx->dispatch);
+
+ if ((flavor == CAIRO_GL_FLAVOR_DESKTOP &&
+ version >= CAIRO_GL_VERSION_ENCODE (3, 30)) ||
+ (flavor == CAIRO_GL_FLAVOR_ES3 &&
+ version >= CAIRO_GL_VERSION_ENCODE (3, 1)))
+ needs_glsl330 = CAIRO_GLSL_VERSION_330;
+ else
+ needs_glsl330 = CAIRO_GLSL_VERSION_NON_330;
+ }
- shader->uniforms[uniform] =
- ctx->dispatch.GetUniformLocation (shader->program,
- names[uniform]);
- return shader->uniforms[uniform];
+ return needs_glsl330 == CAIRO_GLSL_VERSION_330;
}
cairo_gl_uniform_t
@@ -212,12 +202,8 @@ _cairo_gl_shader_cache_destroy (void *data)
static void
_cairo_gl_shader_init (cairo_gl_shader_t *shader)
{
- int i;
shader->fragment_shader = 0;
shader->program = 0;
-
- for (i = 0; i < CAIRO_GL_UNIFORM_MAX; i++)
- shader->uniforms[i] = -1;
}
cairo_status_t
@@ -232,8 +218,23 @@ _cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
"{\n"
" gl_FragColor = color;\n"
"}\n";
+
+ static const char *glsl330_fill_fs_source =
+ "#version 330\n"
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "uniform vec4 color;\n"
+ "out vec4 fsColorOut;\n"
+ "void main()\n"
+ "{\n"
+ " fsColorOut = color;\n"
+ "}\n";
+
cairo_status_t status;
+ _cairo_needs_glsl330 (ctx);
+
if (_cairo_gl_get_version (&ctx->dispatch) >= CAIRO_GL_VERSION_ENCODE (2, 0) ||
(_cairo_gl_has_extension (&ctx->dispatch, "GL_ARB_shader_objects") &&
_cairo_gl_has_extension (&ctx->dispatch, "GL_ARB_fragment_shader") &&
@@ -258,7 +259,17 @@ _cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
return status;
_cairo_gl_shader_init (&ctx->fill_rectangles_shader);
- status = _cairo_gl_shader_compile_and_link (ctx,
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330)
+ status = _cairo_gl_shader_compile_and_link (ctx,
+ &ctx->fill_rectangles_shader,
+ CAIRO_GL_VAR_NONE,
+ CAIRO_GL_VAR_NONE,
+ FALSE,
+ glsl330_fill_fs_source,
+ CAIRO_EXTEND_NONE, CAIRO_EXTEND_NONE,
+ FALSE, FALSE);
+ else
+ status = _cairo_gl_shader_compile_and_link (ctx,
&ctx->fill_rectangles_shader,
CAIRO_GL_VAR_NONE,
CAIRO_GL_VAR_NONE,
@@ -334,32 +345,63 @@ cairo_gl_shader_emit_variable (cairo_output_stream_t *stream,
case CAIRO_GL_VAR_NONE:
break;
case CAIRO_GL_VAR_TEXCOORDS:
- _cairo_output_stream_printf (stream,
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330) {
+ _cairo_output_stream_printf (stream,
+ "in vec4 MultiTexCoord%d;\n"
+ "out vec2 %s_texcoords;\n",
+ name,
+ operand_names[name]);
+ if (use_atlas)
+ _cairo_output_stream_printf (stream,
+ "out vec2 %s_start_coords;\n"
+ "out vec2 %s_stop_coords;\n",
+ operand_names[name], operand_names[name]);
+ } else {
+ _cairo_output_stream_printf (stream,
"attribute vec4 MultiTexCoord%d;\n"
"varying vec2 %s_texcoords;\n",
name,
operand_names[name]);
- if (use_atlas)
- _cairo_output_stream_printf (stream,
+ if (use_atlas)
+ _cairo_output_stream_printf (stream,
"varying vec2 %s_start_coords;\n"
"varying vec2 %s_stop_coords;\n",
operand_names[name], operand_names[name]);
+ }
break;
case CAIRO_GL_VAR_TEXGEN:
- _cairo_output_stream_printf (stream,
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330) {
+ _cairo_output_stream_printf (stream,
+ "uniform mat3 %s_texgen;\n"
+ "out vec2 %s_texcoords;\n",
+ operand_names[name],
+ operand_names[name]);
+ /*if (use_atlas)
+ _cairo_output_stream_printf (stream,
+ "out vec2 %s_start_coords;\n"
+ "out vec2 %s_stop_coords;\n",
+ operand_names[name], operand_names[name]);
+ */
+ } else {
+ _cairo_output_stream_printf (stream,
"uniform mat3 %s_texgen;\n"
"varying vec2 %s_texcoords;\n",
operand_names[name],
operand_names[name]);
- /*if (use_atlas)
- _cairo_output_stream_printf (stream,
+ /*if (use_atlas)
+ _cairo_output_stream_printf (stream,
"varying vec2 %s_start_coords;\n"
"varying vec2 %s_stop_coords;\n",
operand_names[name], operand_names[name]);
-*/
+ */
+ }
break;
case CAIRO_GL_VAR_COLOR:
- _cairo_output_stream_printf (stream,
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330)
+ _cairo_output_stream_printf (stream,
+ "out vec4 fragment_color;\n");
+ else
+ _cairo_output_stream_printf (stream,
"varying vec4 fragment_color;\n");
break;
}
@@ -395,7 +437,10 @@ cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream,
static void
cairo_gl_shader_dcl_coverage (cairo_output_stream_t *stream)
{
- _cairo_output_stream_printf (stream, "varying float coverage;\n");
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330)
+ _cairo_output_stream_printf (stream, "out float coverage;\n");
+ else
+ _cairo_output_stream_printf (stream, "varying float coverage;\n");
}
static void
@@ -422,10 +467,16 @@ cairo_gl_shader_emit_varying (cairo_output_stream_t *stream,
{
const char *namestr = operand_names[name];
- _cairo_output_stream_printf (stream,
- "varying vec2 %s_start_coords;\n"
- "varying vec2 %s_stop_coords;\n",
- namestr, namestr);
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330)
+ _cairo_output_stream_printf (stream,
+ "out vec2 %s_start_coords;\n"
+ "out vec2 %s_stop_coords;\n",
+ namestr, namestr);
+ else
+ _cairo_output_stream_printf (stream,
+ "varying vec2 %s_start_coords;\n"
+ "varying vec2 %s_stop_coords;\n",
+ namestr, namestr);
}
static cairo_status_t
@@ -442,6 +493,11 @@ cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
unsigned long length;
cairo_status_t status;
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330)
+ _cairo_output_stream_printf (stream, "#version 330\n");
+
+ _cairo_output_stream_printf (stream, "#ifdef GL_ES\nprecision mediump float;\n#endif\n");
+
cairo_gl_shader_emit_variable (stream, src, CAIRO_GL_TEX_SOURCE, src_use_atlas);
cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_TEX_MASK, mask_use_atlas);
if (use_coverage)
@@ -453,7 +509,20 @@ cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
if (mask_use_atlas && mask == CAIRO_GL_VAR_TEXGEN)
cairo_gl_shader_emit_varying (stream, CAIRO_GL_TEX_MASK);
- _cairo_output_stream_printf (stream,
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330) {
+ _cairo_output_stream_printf (stream,
+ "in vec4 Vertex;\n"
+ "in vec4 Color;\n"
+ "in vec2 StartCoords0;\n"
+ "in vec2 StartCoords1;\n"
+ "in vec2 StopCoords0;\n"
+ "in vec2 StopCoords1;\n"
+ "uniform mat4 ModelViewProjectionMatrix;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = ModelViewProjectionMatrix * Vertex;\n");
+ } else {
+ _cairo_output_stream_printf (stream,
"attribute vec4 Vertex;\n"
"attribute vec4 Color;\n"
"attribute vec2 StartCoords0;\n"
@@ -464,6 +533,7 @@ cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
"void main()\n"
"{\n"
" gl_Position = ModelViewProjectionMatrix * Vertex;\n");
+ }
cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_TEX_SOURCE);
cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_TEX_MASK);
@@ -479,10 +549,8 @@ cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
"}\n\0", 3);
status = _cairo_memory_stream_destroy (stream, &source, &length);
- if (unlikely (status)) {
- free (source);
- return status;
- }
+ if (unlikely (status))
+ return status;
*out = (char *) source;
return CAIRO_STATUS_SUCCESS;
@@ -512,6 +580,7 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
cairo_gl_tex_t name)
{
const char *namestr = operand_names[name];
+ const char *textstr = (needs_glsl330 == CAIRO_GLSL_VERSION_330) ? "" : "2D";
const char *rectstr = (ctx->tex_target == GL_TEXTURE_RECTANGLE ? "Rect" : "");
cairo_bool_t use_atlas = _cairo_gl_operand_get_use_atlas (op);
@@ -521,7 +590,7 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
ASSERT_NOT_REACHED;
break;
case CAIRO_GL_OPERAND_NONE:
- _cairo_output_stream_printf (stream,
+ _cairo_output_stream_printf (stream,
"vec4 get_%s()\n"
"{\n"
" return vec4 (0, 0, 0, 1);\n"
@@ -530,13 +599,22 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
break;
case CAIRO_GL_OPERAND_CONSTANT:
if (op->constant.encode_as_attribute) {
- _cairo_output_stream_printf (stream,
- "varying vec4 fragment_color;\n"
- "vec4 get_%s()\n"
- "{\n"
- " return fragment_color;\n"
- "}\n",
- namestr);
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330)
+ _cairo_output_stream_printf (stream,
+ "in vec4 fragment_color;\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " return fragment_color;\n"
+ "}\n",
+ namestr);
+ else
+ _cairo_output_stream_printf (stream,
+ "varying vec4 fragment_color;\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " return fragment_color;\n"
+ "}\n",
+ namestr);
} else {
_cairo_output_stream_printf (stream,
"uniform vec4 %s_constant;\n"
@@ -546,23 +624,41 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
"}\n",
namestr, namestr, namestr);
}
- break;
+ break;
case CAIRO_GL_OPERAND_TEXTURE:
case CAIRO_GL_OPERAND_GAUSSIAN:
- if (! use_atlas) {
- _cairo_output_stream_printf (stream,
- "uniform sampler2D%s %s_sampler;\n"
- "uniform vec2 %s_texdims;\n"
- "varying vec2 %s_texcoords;\n",
- rectstr, namestr, namestr, namestr);
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330) {
+ if (! use_atlas) {
+ _cairo_output_stream_printf (stream,
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec2 %s_texdims;\n"
+ "in vec2 %s_texcoords;\n",
+ rectstr, namestr, namestr, namestr);
+ } else {
+ _cairo_output_stream_printf (stream,
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec2 %s_texdims;\n"
+ "in vec2 %s_texcoords;\n"
+ "in vec2 %s_start_coords;\n"
+ "in vec2 %s_stop_coords;\n",
+ rectstr, namestr, namestr, namestr, namestr, namestr);
+ }
} else {
- _cairo_output_stream_printf (stream,
- "uniform sampler2D%s %s_sampler;\n"
- "uniform vec2 %s_texdims;\n"
- "varying vec2 %s_texcoords;\n"
- "varying vec2 %s_start_coords;\n"
- "varying vec2 %s_stop_coords;\n",
- rectstr, namestr, namestr, namestr, namestr, namestr);
+ if (! use_atlas) {
+ _cairo_output_stream_printf (stream,
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec2 %s_texdims;\n"
+ "varying vec2 %s_texcoords;\n",
+ rectstr, namestr, namestr, namestr);
+ } else {
+ _cairo_output_stream_printf (stream,
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec2 %s_texdims;\n"
+ "varying vec2 %s_texcoords;\n"
+ "varying vec2 %s_start_coords;\n"
+ "varying vec2 %s_stop_coords;\n",
+ rectstr, namestr, namestr, namestr, namestr, namestr);
+ }
}
if (op->type != CAIRO_GL_OPERAND_TEXTURE) {
@@ -582,17 +678,17 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
namestr);
if (op->type == CAIRO_GL_OPERAND_TEXTURE) {
- if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 ||
+ if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) &&
_cairo_gl_shader_needs_border_fade (op))
{
if (! use_atlas) {
_cairo_output_stream_printf (stream,
" vec2 border_fade = %s_border_fade (%s_texcoords, %s_texdims);\n"
- " vec4 texel = texture2D%s (%s_sampler, %s_texcoords);\n"
+ " vec4 texel = texture%s%s (%s_sampler, %s_texcoords);\n"
" return texel * border_fade.x * border_fade.y;\n"
"}\n",
- namestr, namestr, namestr, rectstr, namestr, namestr);
+ namestr, namestr, namestr, textstr, rectstr, namestr, namestr);
}
else {
_cairo_output_stream_printf (stream,
@@ -600,25 +696,24 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
" vec2 co = %s_wrap (%s_texcoords, %s_start_coords, %s_stop_coords);\n"
" if (co.x == -1.0 && co.y == -1.0)\n"
" return vec4(0.0, 0.0, 0.0, 0.0);\n"
- " vec4 texel = texture2D%s (%s_sampler, co);\n"
+ " vec4 texel = texture%s%s (%s_sampler, %s_wrap (%s_texcoords, %s_start_coords, %s_stop_coords));\n"
" return texel * border_fade.x * border_fade.y;\n"
"}\n",
- namestr, namestr, namestr, namestr,
- namestr, namestr, namestr, rectstr, namestr);
+ namestr, namestr, namestr, namestr, namestr, namestr, namestr, textstr, rectstr, namestr, namestr, namestr, namestr, namestr);
}
}
else
{
if (! use_atlas) {
_cairo_output_stream_printf (stream,
- " return texture2D%s (%s_sampler, %s_wrap (%s_texcoords));\n"
+ " return texture%s%s (%s_sampler, %s_wrap (%s_texcoords));\n"
"}\n",
- rectstr, namestr, namestr, namestr);
+ textstr, rectstr, namestr, namestr, namestr);
} else {
_cairo_output_stream_printf (stream,
- " return texture2D%s (%s_sampler, %s_wrap (%s_texcoords, %s_start_coords, %s_stop_coords));\n"
+ " return texture%s%s (%s_sampler, %s_wrap (%s_texcoords, %s_start_coords, %s_stop_coords));\n"
"}\n",
- rectstr, namestr, namestr, namestr, namestr, namestr);
+ textstr, rectstr, namestr, namestr, namestr, namestr, namestr);
}
}
}
@@ -631,7 +726,7 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
" vec2 wrapped_coords = %s_wrap (%s_texcoords, %s_start_coords, %s_stop_coords);\n"
" if (wrapped_coords == vec2 (-1.0, -1.0))\n"
" return texel;\n"
- " texel += texture2D%s (%s_sampler, wrapped_coords);\n"
+ " texel += texture%s%s (%s_sampler, wrapped_coords);\n"
" texel = texel * %s_blurs[%s_blur_radius];\n"
" for (i = -%s_blur_radius; i <= %s_blur_radius; i++) {\n"
" if (i == 0)\n"
@@ -642,160 +737,255 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
" if (wrapped_coords == vec2 (-1.0, -1.0))\n"
" texel += vec4 (0.0, 0.0, 0.0, alpha) * %s_blurs[i+%s_blur_radius];\n"
" else\n"
- " texel += texture2D%s (%s_sampler, wrapped_coords) * %s_blurs[i+%s_blur_radius];\n"
+ " texel += texture%s%s (%s_sampler, wrapped_coords) * %s_blurs[i+%s_blur_radius];\n"
" }\n"
" return texel;\n"
"}\n",
namestr, namestr, namestr, namestr, namestr,
- rectstr, namestr, namestr, namestr,
+ textstr, rectstr, namestr, namestr, namestr,
namestr, namestr, namestr, namestr,
namestr, namestr, namestr, namestr,
namestr, namestr, namestr, namestr,
- rectstr, namestr, namestr, namestr);
+ textstr, rectstr, namestr, namestr, namestr);
}
break;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- _cairo_output_stream_printf (stream,
- "varying vec2 %s_texcoords;\n"
- "uniform vec2 %s_texdims;\n"
- "uniform sampler2D%s %s_sampler;\n"
- "\n"
- "vec4 get_%s()\n"
- "{\n",
- namestr, namestr, rectstr, namestr, namestr);
- if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 ||
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330) {
+ _cairo_output_stream_printf (stream,
+ "in vec2 %s_texcoords;\n"
+ "uniform vec2 %s_texdims;\n"
+ "uniform sampler2D%s %s_sampler;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n",
+ namestr, namestr, rectstr, namestr, namestr);
+ }
+ else {
+ _cairo_output_stream_printf (stream,
+ "varying vec2 %s_texcoords;\n"
+ "uniform vec2 %s_texdims;\n"
+ "uniform sampler2D%s %s_sampler;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n",
+ namestr, namestr, rectstr, namestr, namestr);
+ }
+
+ if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) &&
_cairo_gl_shader_needs_border_fade (op))
{
_cairo_output_stream_printf (stream,
" float border_fade = %s_border_fade (%s_texcoords.x, %s_texdims.x);\n"
- " vec4 texel = texture2D%s (%s_sampler, vec2 (%s_texcoords.x, 0.5));\n"
+ " vec4 texel = texture%s%s (%s_sampler, vec2 (%s_texcoords.x, 0.5));\n"
" return texel * border_fade;\n"
"}\n",
- namestr, namestr, namestr, rectstr, namestr, namestr);
+ namestr, namestr, namestr, textstr, rectstr, namestr, namestr);
}
else
{
_cairo_output_stream_printf (stream,
- " return texture2D%s (%s_sampler, %s_wrap (vec2 (%s_texcoords.x, 0.5)));\n"
+ " return texture%s%s (%s_sampler, %s_wrap (vec2 (%s_texcoords.x, 0.5)));\n"
"}\n",
- rectstr, namestr, namestr, namestr);
+ textstr, rectstr, namestr, namestr, namestr);
}
break;
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
- _cairo_output_stream_printf (stream,
- "varying vec2 %s_texcoords;\n"
- "uniform vec2 %s_texdims;\n"
- "uniform sampler2D%s %s_sampler;\n"
- "uniform vec3 %s_circle_d;\n"
- "uniform float %s_radius_0;\n"
- "\n"
- "vec4 get_%s()\n"
- "{\n"
- " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
- " \n"
- " float B = dot (pos, %s_circle_d);\n"
- " float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
- " \n"
- " float t = 0.5 * C / B;\n"
- " 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_ES2 ||
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330) {
+ _cairo_output_stream_printf (stream,
+ "in vec2 %s_texcoords;\n"
+ "uniform vec2 %s_texdims;\n"
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec3 %s_circle_d;\n"
+ "uniform float %s_radius_0;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
+ " \n"
+ " float B = dot (pos, %s_circle_d);\n"
+ " float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
+ " \n"
+ " float t = 0.5 * C / B;\n"
+ " 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);
+ } else {
+ _cairo_output_stream_printf (stream,
+ "varying vec2 %s_texcoords;\n"
+ "uniform vec2 %s_texdims;\n"
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec3 %s_circle_d;\n"
+ "uniform float %s_radius_0;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
+ " \n"
+ " float B = dot (pos, %s_circle_d);\n"
+ " float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
+ " \n"
+ " float t = 0.5 * C / B;\n"
+ " 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_ES2 ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) &&
_cairo_gl_shader_needs_border_fade (op))
{
_cairo_output_stream_printf (stream,
" float border_fade = %s_border_fade (t, %s_texdims.x);\n"
- " vec4 texel = texture2D%s (%s_sampler, vec2 (t, 0.5));\n"
+ " vec4 texel = texture%s%s (%s_sampler, vec2 (t, 0.5));\n"
" return mix (vec4 (0.0), texel * border_fade, is_valid);\n"
"}\n",
- namestr, namestr, rectstr, namestr);
+ namestr, namestr, textstr, rectstr, namestr);
}
else
{
_cairo_output_stream_printf (stream,
- " vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2 (t, 0.5)));\n"
+ " vec4 texel = texture%s%s (%s_sampler, %s_wrap (vec2 (t, 0.5)));\n"
" return mix (vec4 (0.0), texel, is_valid);\n"
"}\n",
- rectstr, namestr, namestr);
+ textstr, rectstr, namestr, namestr);
}
break;
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
- _cairo_output_stream_printf (stream,
- "varying vec2 %s_texcoords;\n"
- "uniform vec2 %s_texdims;\n"
- "uniform sampler2D%s %s_sampler;\n"
- "uniform vec3 %s_circle_d;\n"
- "uniform float %s_a;\n"
- "uniform float %s_radius_0;\n"
- "\n"
- "vec4 get_%s()\n"
- "{\n"
- " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
- " \n"
- " float B = dot (pos, %s_circle_d);\n"
- " float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
- " \n"
- " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n"
- " float sqrtdet = sqrt (abs (det));\n"
- " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n"
- " \n"
- " vec2 is_valid = step (vec2 (0.0), t) * step (t, vec2(1.0));\n"
- " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n"
- " \n"
- " 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_ES2 ||
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330) {
+ _cairo_output_stream_printf (stream,
+ "in vec2 %s_texcoords;\n"
+ "uniform vec2 %s_texdims;\n"
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec3 %s_circle_d;\n"
+ "uniform float %s_a;\n"
+ "uniform float %s_radius_0;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
+ " \n"
+ " float B = dot (pos, %s_circle_d);\n"
+ " float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
+ " \n"
+ " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n"
+ " float sqrtdet = sqrt (abs (det));\n"
+ " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n"
+ " \n"
+ " vec2 is_valid = step (vec2 (0.0), t) * step (t, vec2(1.0));\n"
+ " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n"
+ " \n"
+ " 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);
+ } else {
+ _cairo_output_stream_printf (stream,
+ "varying vec2 %s_texcoords;\n"
+ "uniform vec2 %s_texdims;\n"
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec3 %s_circle_d;\n"
+ "uniform float %s_a;\n"
+ "uniform float %s_radius_0;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
+ " \n"
+ " float B = dot (pos, %s_circle_d);\n"
+ " float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
+ " \n"
+ " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n"
+ " float sqrtdet = sqrt (abs (det));\n"
+ " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n"
+ " \n"
+ " vec2 is_valid = step (vec2 (0.0), t) * step (t, vec2(1.0));\n"
+ " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n"
+ " \n"
+ " 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_ES2 ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) &&
_cairo_gl_shader_needs_border_fade (op))
{
_cairo_output_stream_printf (stream,
" float border_fade = %s_border_fade (upper_t, %s_texdims.x);\n"
- " vec4 texel = texture2D%s (%s_sampler, vec2 (upper_t, 0.5));\n"
+ " vec4 texel = texture%s%s (%s_sampler, vec2 (upper_t, 0.5));\n"
" return mix (vec4 (0.0), texel * border_fade, has_color);\n"
"}\n",
- namestr, namestr, rectstr, namestr);
+ namestr, namestr, textstr, rectstr, namestr);
}
else
{
_cairo_output_stream_printf (stream,
- " vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n"
+ " vec4 texel = texture%s%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n"
" return mix (vec4 (0.0), texel, has_color);\n"
"}\n",
- rectstr, namestr, namestr);
+ textstr, rectstr, namestr, namestr);
}
break;
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
- _cairo_output_stream_printf (stream,
- "varying vec2 %s_texcoords;\n"
- "uniform sampler2D%s %s_sampler;\n"
- "uniform vec3 %s_circle_d;\n"
- "uniform float %s_a;\n"
- "uniform float %s_radius_0;\n"
- "\n"
- "vec4 get_%s()\n"
- "{\n"
- " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
- " \n"
- " float B = dot (pos, %s_circle_d);\n"
- " float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
- " \n"
- " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n"
- " float sqrtdet = sqrt (abs (det));\n"
- " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n"
- " \n"
- " vec2 is_valid = step (vec2 (-%s_radius_0), t * %s_circle_d.z);\n"
- " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n"
- " \n"
- " float upper_t = mix (t.y, t.x, is_valid.x);\n"
- " vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n"
- " return mix (vec4 (0.0), texel, has_color);\n"
- "}\n",
- namestr, rectstr, namestr, namestr, namestr, namestr,
- namestr, namestr, namestr, namestr, namestr,
- namestr, namestr, namestr, rectstr, namestr, namestr);
+ if (needs_glsl330 == CAIRO_GLSL_VERSION_330) {
+ _cairo_output_stream_printf (stream,
+ "in vec2 %s_texcoords;\n"
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec3 %s_circle_d;\n"
+ "uniform float %s_a;\n"
+ "uniform float %s_radius_0;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
+ " \n"
+ " float B = dot (pos, %s_circle_d);\n"
+ " float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
+ " \n"
+ " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n"
+ " float sqrtdet = sqrt (abs (det));\n"
+ " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n"
+ " \n"
+ " vec2 is_valid = step (vec2 (-%s_radius_0), t * %s_circle_d.z);\n"
+ " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n"
+ " \n"
+ " float upper_t = mix (t.y, t.x, is_valid.x);\n"
+ " vec4 texel = texture%s%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n"
+ " return mix (vec4 (0.0), texel, has_color);\n"
+ "}\n",
+ namestr, rectstr, namestr, namestr, namestr, namestr,
+ namestr, namestr, namestr, namestr, namestr,
+ namestr, namestr, namestr, textstr, rectstr, namestr, namestr);
+ } else {
+ _cairo_output_stream_printf (stream,
+ "varying vec2 %s_texcoords;\n"
+ "uniform sampler2D%s %s_sampler;\n"
+ "uniform vec3 %s_circle_d;\n"
+ "uniform float %s_a;\n"
+ "uniform float %s_radius_0;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
+ " \n"
+ " float B = dot (pos, %s_circle_d);\n"
+ " float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
+ " \n"
+ " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n"
+ " float sqrtdet = sqrt (abs (det));\n"
+ " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n"
+ " \n"
+ " vec2 is_valid = step (vec2 (-%s_radius_0), t * %s_circle_d.z);\n"
+ " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n"
+ " \n"
+ " float upper_t = mix (t.y, t.x, is_valid.x);\n"
+ " vec4 texel = texture%s%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n"
+ " return mix (vec4 (0.0), texel, has_color);\n"
+ "}\n",
+ namestr, rectstr, namestr, namestr, namestr, namestr,
+ namestr, namestr, namestr, namestr, namestr,
+ namestr, namestr, namestr, textstr, rectstr, namestr, namestr);
+ }
break;
}
}
@@ -962,21 +1152,13 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
cairo_status_t status;
const char *coverage_str;
- // dy5.kim: Use highp only for gradients to handle the following test case
- // http://w3c-test.org/html/tests/approved/canvas/2d.gradient.radial.touch1.html
- if (src->type == CAIRO_GL_OPERAND_LINEAR_GRADIENT ||
- src->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0 ||
- src->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE ||
- src->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT)
- _cairo_output_stream_printf (stream,
- "#ifdef GL_ES\n"
- "precision highp float;\n"
- "#endif\n");
- else
- _cairo_output_stream_printf (stream,
- "#ifdef GL_ES\n"
- "precision mediump float;\n"
- "#endif\n");
+ if (_cairo_needs_glsl330 (ctx))
+ _cairo_output_stream_printf (stream, "#version 330\n");
+
+ _cairo_output_stream_printf (stream,
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n");
_cairo_gl_shader_emit_wrap (ctx, stream, src, CAIRO_GL_TEX_SOURCE);
_cairo_gl_shader_emit_wrap (ctx, stream, mask, CAIRO_GL_TEX_MASK);
@@ -994,10 +1176,17 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
coverage_str = "";
if (use_coverage) {
- _cairo_output_stream_printf (stream, "varying float coverage;\n");
+ if (_cairo_needs_glsl330 (ctx)) {
+ _cairo_output_stream_printf (stream, "in float coverage;\n");
+ } else {
+ _cairo_output_stream_printf (stream, "varying float coverage;\n");
+ }
coverage_str = " * coverage";
}
+ if (_cairo_needs_glsl330 (ctx))
+ _cairo_output_stream_printf (stream, "out vec4 fsColorOut;\n");
+
_cairo_output_stream_printf (stream,
"void main()\n"
"{\n");
@@ -1006,19 +1195,34 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
default:
ASSERT_NOT_REACHED;
case CAIRO_GL_SHADER_IN_NORMAL:
- _cairo_output_stream_printf (stream,
- " gl_FragColor = get_source() * get_mask().a%s;\n",
- coverage_str);
+ if (_cairo_needs_glsl330 (ctx))
+ _cairo_output_stream_printf (stream,
+ " fsColorOut = get_source() * get_mask().a%s;\n",
+ coverage_str);
+ else
+ _cairo_output_stream_printf (stream,
+ " gl_FragColor = get_source() * get_mask().a%s;\n",
+ coverage_str);
break;
case CAIRO_GL_SHADER_IN_CA_SOURCE:
- _cairo_output_stream_printf (stream,
- " gl_FragColor = get_source() * get_mask()%s;\n",
- coverage_str);
+ if (_cairo_needs_glsl330 (ctx))
+ _cairo_output_stream_printf (stream,
+ " fsColorOut = get_source() * get_mask()%s;\n",
+ coverage_str);
+ else
+ _cairo_output_stream_printf (stream,
+ " gl_FragColor = get_source() * get_mask()%s;\n",
+ coverage_str);
break;
case CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA:
- _cairo_output_stream_printf (stream,
- " gl_FragColor = get_source().a * get_mask()%s;\n",
- coverage_str);
+ if (_cairo_needs_glsl330 (ctx))
+ _cairo_output_stream_printf (stream,
+ " fsColorOut = get_source().a * get_mask()%s;\n",
+ coverage_str);
+ else
+ _cairo_output_stream_printf (stream,
+ " gl_FragColor = get_source().a * get_mask()%s;\n",
+ coverage_str);
break;
}
@@ -1026,10 +1230,8 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
"}\n\0", 3);
status = _cairo_memory_stream_destroy (stream, &source, &length);
- if (unlikely (status)) {
- free (source);
+ if (unlikely (status))
return status;
- }
*out = (char *) source;
return CAIRO_STATUS_SUCCESS;
@@ -1133,6 +1335,22 @@ link_shader_program (cairo_gl_context_t *ctx,
ASSERT_NOT_REACHED;
}
+static GLint
+_cairo_gl_get_op_uniform_location(cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader,
+ cairo_gl_tex_t tex_unit,
+ const char *suffix)
+{
+ cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+ char uniform_name[100];
+ const char *unit_name[2] = { "source", "mask" };
+
+ snprintf (uniform_name, sizeof (uniform_name), "%s_%s",
+ unit_name[tex_unit], suffix);
+
+ return dispatch->GetUniformLocation (shader->program, uniform_name);
+}
+
static cairo_status_t
_cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx,
cairo_gl_shader_t *shader,
@@ -1145,8 +1363,12 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx,
cairo_bool_t src_use_atlas,
cairo_bool_t mask_use_atlas)
{
+ cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
unsigned int vertex_shader;
cairo_status_t status;
+ int i;
+
+ _cairo_needs_glsl330 (ctx);
assert (shader->program == 0);
@@ -1167,12 +1389,14 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx,
use_coverage,
CAIRO_GL_VAR_NONE,
&source);
- if (unlikely (status))
- goto FAILURE;
+ if (unlikely (status))
+ goto FAILURE;
+
+ printf ("\n\n======= vertex source ========\n%s\n\n", source);
compile_shader (ctx, &ctx->vertex_shaders[vertex_shader],
GL_VERTEX_SHADER, source);
- free (source);
+ free (source);
}
compile_shader (ctx, &shader->fragment_shader,
@@ -1182,6 +1406,37 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx,
ctx->vertex_shaders[vertex_shader],
shader->fragment_shader);
+ shader->mvp_location =
+ dispatch->GetUniformLocation (shader->program,
+ "ModelViewProjectionMatrix");
+
+ for (i = 0; i < 2; i++) {
+ shader->constant_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "constant");
+ shader->a_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "a");
+ shader->circle_d_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "circle_d");
+ shader->radius_0_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "radius_0");
+ shader->texdims_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "texdims");
+ shader->texgen_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "texgen");
+ shader->blur_radius_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "blur_radius");
+ shader->blurs_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "blurs");
+ shader->blur_step_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "blur_step");
+ shader->blur_x_axis_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "blur_x_axis");
+ shader->blur_y_axis_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "blur_y_axis");
+ shader->alpha_location[i] =
+ _cairo_gl_get_op_uniform_location (ctx, shader, i, "alpha");
+ }
+
return CAIRO_STATUS_SUCCESS;
FAILURE:
@@ -1211,14 +1466,12 @@ _cairo_gl_shader_set_samplers (cairo_gl_context_t *ctx,
dispatch->GetIntegerv (GL_CURRENT_PROGRAM, &saved_program);
dispatch->UseProgram (shader->program);
- location = _cairo_gl_shader_get_uniform_location (ctx, shader,
- CAIRO_GL_UNIFORM_SAMPLER);
+ location = dispatch->GetUniformLocation (shader->program, "source_sampler");
if (location != -1) {
dispatch->Uniform1i (location, CAIRO_GL_TEX_SOURCE);
}
- location = _cairo_gl_shader_get_uniform_location (ctx, shader,
- CAIRO_GL_UNIFORM_MASK_SAMPLER);
+ location = dispatch->GetUniformLocation (shader->program, "mask_sampler");
if (location != -1) {
dispatch->Uniform1i (location, CAIRO_GL_TEX_MASK);
}
@@ -1228,96 +1481,74 @@ _cairo_gl_shader_set_samplers (cairo_gl_context_t *ctx,
void
_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
float value)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- GLint location = _cairo_gl_shader_get_uniform_location (ctx,
- ctx->current_shader,
- uniform);
assert (location != -1);
dispatch->Uniform1f (location, value);
}
void
_cairo_gl_shader_bind_int (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
int value)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- GLint location = _cairo_gl_shader_get_uniform_location (ctx,
- ctx->current_shader,
- uniform);
assert (location != -1);
dispatch->Uniform1i (location, value);
}
void
_cairo_gl_shader_bind_float_array (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
int num, float *values)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- GLint location = _cairo_gl_shader_get_uniform_location (ctx,
- ctx->current_shader,
- uniform);
assert (location != -1);
dispatch->Uniform1fv (location, num, values);
}
void
_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
float value0,
float value1)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- GLint location = _cairo_gl_shader_get_uniform_location (ctx,
- ctx->current_shader,
- uniform);
assert (location != -1);
dispatch->Uniform2f (location, value0, value1);
}
void
_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
float value0,
float value1,
float value2)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- GLint location = _cairo_gl_shader_get_uniform_location (ctx,
- ctx->current_shader,
- uniform);
assert (location != -1);
dispatch->Uniform3f (location, value0, value1, value2);
}
void
_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
float value0, float value1,
float value2, float value3)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- GLint location = _cairo_gl_shader_get_uniform_location (ctx,
- ctx->current_shader,
- uniform);
assert (location != -1);
dispatch->Uniform4f (location, value0, value1, value2, value3);
}
void
_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
+ GLint location,
const cairo_matrix_t* m)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- GLint location = _cairo_gl_shader_get_uniform_location (ctx,
- ctx->current_shader,
- uniform);
-
float gl_m[9] = {
m->xx, m->yx, 0,
m->xy, m->yy, 0,
@@ -1329,13 +1560,9 @@ _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
void
_cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx,
- cairo_gl_uniform_t uniform,
- GLfloat* gl_m)
+ GLint location, GLfloat* gl_m)
{
cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- GLint location = _cairo_gl_shader_get_uniform_location (ctx,
- ctx->current_shader,
- uniform);
assert (location != -1);
dispatch->UniformMatrix4fv (location, 1, GL_FALSE, gl_m);
}
@@ -1411,6 +1638,8 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
if (unlikely (status))
return status;
+ printf ("\n\n======= fragment source ========\n%s\n\n", fs_source);
+
entry = malloc (sizeof (cairo_shader_cache_entry_t));
if (unlikely (entry == NULL)) {
free (fs_source);
diff --git a/src/cairo-gl-source.c b/src/cairo-gl-source.c
index 53c3ed35a..53c3ed35a 100755..100644
--- a/src/cairo-gl-source.c
+++ b/src/cairo-gl-source.c
diff --git a/src/cairo-gl-spans-compositor.c b/src/cairo-gl-spans-compositor.c
index 724ae6661..df337404e 100755..100644
--- a/src/cairo-gl-spans-compositor.c
+++ b/src/cairo-gl-spans-compositor.c
@@ -299,9 +299,6 @@ draw_image_boxes (void *_dst,
struct _cairo_boxes_chunk *chunk;
int i;
- if (_cairo_gl_surface_is_texture (dst))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
cairo_box_t *b = &chunk->base[i];
diff --git a/src/cairo-gl-surface-legacy.c b/src/cairo-gl-surface-legacy.c
index 92b27c905..92b27c905 100755..100644
--- a/src/cairo-gl-surface-legacy.c
+++ b/src/cairo-gl-surface-legacy.c
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index ac19a13ad..665ab244a 100755..100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -76,7 +76,7 @@ _cairo_gl_surface_shadow_surface (void *surface,
return NULL;
shadow_surface = ctx->shadow_scratch_surfaces[0];
-
+
if (shadow_surface) {
shadow_width = shadow_surface->width;
shadow_height = shadow_surface->height;
@@ -258,7 +258,7 @@ _cairo_gl_surface_glyph_shadow_surface (void *surface,
shadow_surface = ctx->shadow_scratch_surfaces[1];
else
shadow_surface = ctx->shadow_scratch_surfaces[2];
-
+
if (shadow_surface) {
shadow_width = shadow_surface->width;
shadow_height = shadow_surface->height;
@@ -273,7 +273,7 @@ _cairo_gl_surface_glyph_shadow_surface (void *surface,
if (! shadow_surface) {
shadow_surface = (cairo_gl_surface_t *)
_cairo_gl_surface_create_scratch (ctx,
- CAIRO_CONTENT_COLOR_ALPHA,
+ CAIRO_CONTENT_COLOR_ALPHA,
width, height);
if (unlikely (shadow_surface->base.status)) {
cairo_surface_destroy (&shadow_surface->base);
@@ -309,10 +309,10 @@ _cairo_gl_surface_glyph_shadow_mask_surface (void *surface,
return NULL;
mask_surface = ctx->shadow_masks[index + 2];
-
+
if (mask_surface) {
if (mask_surface->width != width ||
- mask_surface->height != height) {
+ mask_surface->height != height) {
cairo_surface_destroy (&mask_surface->base);
mask_surface = NULL;
ctx->shadow_masks[index + 2] = NULL;
@@ -542,6 +542,9 @@ _cairo_gl_get_image_format_and_type_gl (pixman_format_code_t pixman_format,
*type = GL_UNSIGNED_BYTE;
return TRUE;
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,27,2)
+ case PIXMAN_a8r8g8b8_sRGB:
+#endif
case PIXMAN_a2b10g10r10:
case PIXMAN_x2b10g10r10:
case PIXMAN_a4r4g4b4:
@@ -690,17 +693,32 @@ _cairo_gl_surface_init (cairo_device_t *device,
_cairo_gl_surface_embedded_operand_init (surface);
}
+static cairo_bool_t
+_cairo_gl_surface_size_valid_for_context (cairo_gl_context_t *ctx,
+ int width, int height)
+{
+ return width > 0 && height > 0 &&
+ width <= ctx->max_framebuffer_size &&
+ height <= ctx->max_framebuffer_size;
+}
+
+static cairo_bool_t
+_cairo_gl_surface_size_valid (cairo_gl_surface_t *surface,
+ int width, int height)
+{
+ cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
+ return _cairo_gl_surface_size_valid_for_context (ctx, width, height);
+}
+
static cairo_surface_t *
_cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx,
cairo_content_t content,
GLuint tex,
int width,
- int height,
- cairo_bool_t set_tex_param)
+ int height)
{
cairo_gl_surface_t *surface;
- assert (width <= ctx->max_framebuffer_size && height <= ctx->max_framebuffer_size);
surface = calloc (1, sizeof (cairo_gl_surface_t));
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
@@ -713,12 +731,10 @@ _cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx,
surface->supports_stencil = TRUE;
/* Create the texture used to store the surface's data. */
- if (!set_tex_param) {
_cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
ctx->dispatch.BindTexture (ctx->tex_target, surface->tex);
ctx->dispatch.TexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
ctx->dispatch.TexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- }
return &surface->base;
}
@@ -737,7 +753,7 @@ _create_scratch_internal (cairo_gl_context_t *ctx,
ctx->dispatch.GenTextures (1, &tex);
surface = (cairo_gl_surface_t *)
_cairo_gl_surface_create_scratch_for_texture (ctx, content,
- tex, width, height, FALSE);
+ tex, width, height);
if (unlikely (surface->base.status))
return &surface->base;
@@ -753,7 +769,7 @@ _create_scratch_internal (cairo_gl_context_t *ctx,
default:
ASSERT_NOT_REACHED;
case CAIRO_CONTENT_COLOR_ALPHA:
- if (ctx->can_read_bgra)
+ if(ctx->can_read_bgra)
format = GL_BGRA;
else
format = GL_RGBA;
@@ -762,7 +778,7 @@ _create_scratch_internal (cairo_gl_context_t *ctx,
/* When using GL_ALPHA, compositing doesn't work properly, but for
* caching surfaces, we are just uploading pixel data, so it isn't
* an issue. */
- if (for_caching)
+ if (for_caching && !ctx->is_gl33)
format = GL_ALPHA;
else
format = GL_RGBA;
@@ -776,7 +792,7 @@ _create_scratch_internal (cairo_gl_context_t *ctx,
* specified. So, we have to store RGBA, and fill the alpha
* channel with 1 when blending.
*/
- if (ctx->can_read_bgra)
+ if(ctx->can_read_bgra)
format = GL_BGRA;
else
format = GL_RGBA;
@@ -785,7 +801,7 @@ _create_scratch_internal (cairo_gl_context_t *ctx,
ctx->dispatch.TexImage2D (ctx->tex_target, 0, format,
width, height, 0,
- format, GL_UNSIGNED_BYTE, NULL);
+ format, GL_UNSIGNED_BYTE, NULL);
return &surface->base;
}
@@ -861,15 +877,14 @@ _cairo_gl_surface_clear (cairo_gl_surface_t *surface,
}
/* optimize for mobile gl driver with deferred rendering */
- if (surface->clip_on_stencil_buffer ||
- ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
ctx->dispatch.Clear (GL_COLOR_BUFFER_BIT);
else {
- if (surface->clip_on_stencil_buffer) {
- _cairo_clip_destroy(surface->clip_on_stencil_buffer);
- surface->clip_on_stencil_buffer = NULL;
- }
- ctx->dispatch.Clear (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ if (surface->clip_on_stencil_buffer) {
+ _cairo_clip_destroy (surface->clip_on_stencil_buffer);
+ surface->clip_on_stencil_buffer = NULL;
+ }
+ ctx->dispatch.Clear (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
if (a == 0)
@@ -931,6 +946,11 @@ cairo_gl_surface_create (cairo_device_t *abstract_device,
if (unlikely (status))
return _cairo_surface_create_in_error (status);
+ if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) {
+ status = _cairo_gl_context_release (ctx, status);
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
+ }
+
surface = (cairo_gl_surface_t *)
_cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height);
if (unlikely (surface->base.status)) {
@@ -1003,9 +1023,14 @@ cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device,
if (unlikely (status))
return _cairo_surface_create_in_error (status);
+ if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) {
+ status = _cairo_gl_context_release (ctx, status);
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
+ }
+
surface = (cairo_gl_surface_t *)
_cairo_gl_surface_create_scratch_for_texture (ctx, content,
- tex, width, height, TRUE);
+ tex, width, height);
status = _cairo_gl_context_release (ctx, status);
return &surface->base;
@@ -1090,7 +1115,6 @@ cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
status = _cairo_gl_context_acquire (surface->base.device, &ctx);
if (unlikely (status))
return;
-
/* And in any case we should flush any pending operations. */
_cairo_gl_composite_flush (ctx);
@@ -1099,7 +1123,7 @@ cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
ctx->swap_buffers (ctx, surface);
- /* according to khronos specs on egl 1.4, stencil buffer is
+ /* according to khronos specs on egl 1.4, stencil buffer is
* not preserved after eglSwapBuffers */
if (surface->clip_on_stencil_buffer) {
_cairo_clip_destroy (surface->clip_on_stencil_buffer);
@@ -1112,16 +1136,6 @@ cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
}
}
-static cairo_bool_t
-_cairo_gl_surface_size_valid (cairo_gl_surface_t *surface,
- int width, int height)
-{
- cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
- return width > 0 && height > 0 &&
- width <= ctx->max_framebuffer_size &&
- height <= ctx->max_framebuffer_size;
-}
-
static cairo_surface_t *
_cairo_gl_surface_create_similar (void *abstract_surface,
cairo_content_t content,
@@ -1214,8 +1228,10 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
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;
+ if (src->pixman_format != pixman_format) {
+ if (!ctx->can_read_bgra)
+ require_conversion = TRUE;
+ }
}
else if (dst->base.content != CAIRO_CONTENT_ALPHA)
require_conversion = TRUE;
@@ -1227,6 +1243,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
}
if (require_conversion) {
+ src->base.is_clear = FALSE;
rgba_clone = (cairo_image_surface_t *)
_cairo_image_surface_create_with_pixman_format (NULL,
pixman_format,
@@ -1246,7 +1263,32 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
src = rgba_clone;
}
- }
+ } else if (ctx->is_gl33 && src->base.content == CAIRO_CONTENT_ALPHA) {
+ /* use RGBA for ALPHA */
+ pixman_format_code_t pixman_format;
+ cairo_surface_pattern_t pattern;
+ src->base.is_clear = FALSE;
+ pixman_format = _cairo_is_little_endian () ? PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8;
+
+ 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,
@@ -1311,6 +1353,9 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
}
else
{
+ /* When cpp != 4, setting GL_UNPACK_ALIGNMENT to cpp
+ causes many failures in cairo tests with respect to
+ GLESV2 */
ctx->dispatch.PixelStorei (GL_UNPACK_ALIGNMENT, 4);
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
@@ -1320,18 +1365,18 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
/* 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;
- }
+ if (unlikely (status)) {
+ free (data_start_gles2);
+ goto FAIL;
+ }
_cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
ctx->dispatch.BindTexture (ctx->tex_target, dst->tex);
ctx->dispatch.TexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
ctx->dispatch.TexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
ctx->dispatch.TexSubImage2D (ctx->tex_target, 0,
- dst_x, dst_y, width, height,
- format, type, data_start);
+ dst_x, dst_y, width, height,
+ format, type, data_start);
free (data_start_gles2);
@@ -1498,8 +1543,8 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
return NULL;
}
- if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2 ||
- _cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES3) {
+ /*if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2 ||
+ _cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES3)*/ {
/* 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
@@ -1538,11 +1583,11 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
/* If the original surface has not been modified or
* is clear, we can avoid downloading data. */
- if (surface->base.is_clear || surface->base.serial == 0) {
+/* if (surface->base.is_clear || surface->base.serial == 0) {
status = _cairo_gl_context_release (ctx, status);
return image;
}
-
+*/
/* This is inefficient, as we'd rather just read the thing without making
* it the destination. But then, this is the fallback path, so let's not
* fall back instead.
@@ -1554,10 +1599,11 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
flipped = ! _cairo_gl_surface_is_texture (surface);
mesa_invert = flipped && ctx->has_mesa_pack_invert;
- ctx->dispatch.PixelStorei (GL_PACK_ALIGNMENT, 4);
+ ctx->dispatch.PixelStorei (GL_PACK_ALIGNMENT, cpp);
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
ctx->dispatch.PixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
+
if (mesa_invert)
ctx->dispatch.PixelStorei (GL_PACK_INVERT_MESA, 1);
@@ -1566,8 +1612,9 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
y = surface->height - extents->y - extents->height;
ctx->dispatch.ReadPixels (extents->x, y,
- extents->width, extents->height,
- format, type, image->data);
+ extents->width, extents->height,
+ format, type, image->data);
+
if (mesa_invert)
ctx->dispatch.PixelStorei (GL_PACK_INVERT_MESA, 0);
@@ -1707,9 +1754,10 @@ _cairo_gl_surface_flush (void *abstract_surface, unsigned flags)
_cairo_gl_composite_flush (ctx);
status = _cairo_gl_surface_resolve_multisampling (surface);
-
+#if 0
if (ctx->msaa_type != CAIRO_GL_NONE_MULTISAMPLE_TO_TEXTURE)
- ctx->dispatch.Flush ();
+ ctx->dispatch.Flush ();
+#endif
return _cairo_gl_context_release (ctx, status);
}
@@ -1772,7 +1820,7 @@ _cairo_gl_surface_paint (void *surface,
&source->shadow);
ctx->source_scratch_in_use = FALSE;
if (unlikely (status)) {
- cairo_device_release (dst->base.device);
+ cairo_device_release (dst->base.device);
return status;
}
@@ -1781,13 +1829,12 @@ _cairo_gl_surface_paint (void *surface,
dst->content_changed = TRUE;
dst->content_synced = FALSE;
}
-
+
ctx->source_scratch_in_use = FALSE;
cairo_device_release (dst->base.device);
return status;
}
-#if 0 // Currently glClear does not get flushed to GPU so do not use this fast path for the time being
/* simplify the common case of clearing the surface */
if (clip == NULL) {
if (op == CAIRO_OPERATOR_CLEAR) {
@@ -1800,11 +1847,10 @@ _cairo_gl_surface_paint (void *surface,
(op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) {
status = _cairo_gl_surface_clear (surface,
&((cairo_solid_pattern_t *) source)->color);
- cairo_device_release (dst->base.device);
+ cairo_device_release (dst->base.device);
return status;
}
}
-#endif
status = _cairo_compositor_paint (get_compositor (surface), surface,
op, source, clip);
@@ -1812,7 +1858,7 @@ _cairo_gl_surface_paint (void *surface,
dst->content_changed = TRUE;
dst->content_synced = FALSE;
}
-
+
ctx->source_scratch_in_use = FALSE;
cairo_device_release (dst->base.device);
return status;
@@ -1837,7 +1883,7 @@ _cairo_gl_surface_mask (void *surface,
&source->shadow);
ctx->source_scratch_in_use = FALSE;
if (unlikely (status)) {
- cairo_device_release (dst->base.device);
+ cairo_device_release (dst->base.device);
return status;
}
@@ -1845,8 +1891,8 @@ _cairo_gl_surface_mask (void *surface,
if (status == CAIRO_INT_STATUS_SUCCESS) {
dst->content_changed = TRUE;
dst->content_synced = FALSE;
- }
-
+ }
+
ctx->source_scratch_in_use = FALSE;
cairo_device_release (dst->base.device);
return status;
@@ -1857,7 +1903,7 @@ _cairo_gl_surface_mask (void *surface,
if (status == CAIRO_INT_STATUS_SUCCESS) {
dst->content_changed = TRUE;
dst->content_synced = FALSE;
-
+
ctx->source_scratch_in_use = FALSE;
cairo_device_release (dst->base.device);
return status;
@@ -2016,7 +2062,6 @@ _cairo_gl_surface_fill (void *surface,
ctx->source_scratch_in_use = FALSE;
cairo_device_release (dst->base.device);
-
return status;
}
diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c
index 022a37d77..4e95e9a57 100755..100644
--- a/src/cairo-gl-traps-compositor.c
+++ b/src/cairo-gl-traps-compositor.c
@@ -84,9 +84,6 @@ draw_image_boxes (void *_dst,
struct _cairo_boxes_chunk *chunk;
int i;
- if (_cairo_gl_surface_is_texture (dst))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
cairo_box_t *b = &chunk->base[i];
@@ -268,7 +265,6 @@ lerp (void *dst,
0, 0,
dst_x, dst_y,
width, height);
-
if (unlikely (status))
return status;
@@ -284,27 +280,26 @@ lerp (void *dst,
}
static cairo_int_status_t
-lerp_color_glyph (void *dst,
- cairo_surface_t *src,
- cairo_surface_t *mask,
- int src_x,
- int src_y,
- int mask_x,
- int mask_y,
- int dst_x,
- int dst_y,
- unsigned int width,
- unsigned int height)
+lerp_color_glyph (void *dst,
+ cairo_surface_t *src,
+ cairo_surface_t *mask,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height)
{
- cairo_int_status_t status;
+ cairo_int_status_t status;
- /*we could avoid some repetition... */
+ /* we could avoid some repetition... */
status = composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, src,
mask_x, mask_y,
0, 0,
dst_x, dst_y,
width, height);
-
if (unlikely (status))
return status;
@@ -351,44 +346,12 @@ traps_to_operand (void *_dst,
return status;
}
- /* GLES2 only supports RGB/RGBA when uploading */
-#if 0
- if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) {
- 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)) {
- cairo_surface_destroy (image);
- 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;
- }
- }
-#endif
-
- mask = _cairo_surface_create_similar_scratch (_dst,
- CAIRO_CONTENT_COLOR_ALPHA,
- extents->width,
- extents->height);
+ mask = _cairo_surface_create_scratch (_dst,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ extents->width,
+ extents->height,
+ NULL);
+
if (unlikely (mask->status)) {
cairo_surface_destroy (image);
return mask->status;
@@ -419,7 +382,7 @@ traps_to_operand (void *_dst,
if (unlikely (status))
goto error;
- operand->texture.owns_surface = mask;
+ operand->texture.owns_surface = (cairo_gl_surface_t *)mask;
return CAIRO_STATUS_SUCCESS;
error:
@@ -442,42 +405,42 @@ composite_traps (void *_dst,
cairo_gl_composite_t setup;
cairo_gl_context_t *ctx;
cairo_int_status_t status;
- cairo_surface_t *src = (cairo_surface_t *) abstract_src;
- cairo_surface_t *dst = (cairo_surface_t *) _dst;
- cairo_surface_t *new_surface = NULL;
- cairo_surface_t *new_src = (cairo_surface_t *) abstract_src;
- int new_src_x, new_src_y;
- cairo_surface_pattern_t new_surface_pattern;
-
- if (dst == src) {
- new_surface = _cairo_surface_create_similar_scratch (src,
- src->content,
- extents->width,
- extents->height);
- status = new_surface->status;
- if (unlikely (status)) {
- cairo_surface_destroy (new_surface);
- return status;
- }
+ cairo_surface_t *src = (cairo_surface_t *) abstract_src;
+ cairo_surface_t *dst = (cairo_surface_t *) _dst;
+ cairo_surface_t *new_surface = NULL;
+ cairo_surface_t *new_src = (cairo_surface_t *) abstract_src;
+ int new_src_x, new_src_y;
+ cairo_surface_pattern_t new_surface_pattern;
+
+ if (dst == src) {
+ new_surface = _cairo_surface_create_similar_scratch (src,
+ src->content,
+ extents->width,
+ extents->height);
+ status = new_surface->status;
+ if (unlikely (status)) {
+ cairo_surface_destroy (new_surface);
+ return status;
+ }
_cairo_pattern_init_for_surface (&new_surface_pattern, src);
new_surface_pattern.base.extend = CAIRO_EXTEND_NONE;
new_surface_pattern.base.filter = CAIRO_FILTER_NEAREST;
status = _cairo_surface_paint (new_surface, CAIRO_OPERATOR_SOURCE,
- &new_surface_pattern.base, NULL);
+ &new_surface_pattern.base, NULL);
if (unlikely (status)) {
- _cairo_pattern_fini (&new_surface_pattern.base);
- cairo_surface_destroy (new_surface);
- return status;
- }
+ _cairo_pattern_fini (&new_surface_pattern.base);
+ cairo_surface_destroy (new_surface);
+ return status;
+ }
new_src = _cairo_gl_pattern_to_source (dst,
- &new_surface_pattern.base,
- FALSE,
- extents, extents,
- &new_src_x, &new_src_y);
- }
+ &new_surface_pattern.base,
+ FALSE,
+ extents, extents,
+ &new_src_x, &new_src_y);
+ }
status = _cairo_gl_composite_init (&setup, op, _dst, FALSE);
if (unlikely (status))
@@ -485,9 +448,8 @@ composite_traps (void *_dst,
_cairo_gl_composite_set_source_operand (&setup,
source_to_operand (new_src));
-
- if (src == new_src)
- _cairo_gl_operand_translate (&setup.src, -src_x-dst_x, -src_y-dst_y);
+ if (src == new_src)
+ _cairo_gl_operand_translate (&setup.src, -src_x-dst_x, -src_y-dst_y);
status = traps_to_operand (_dst, extents, antialias, traps, &setup.mask, dst_x, dst_y);
if (unlikely (status))
goto FAIL;
@@ -506,12 +468,12 @@ composite_traps (void *_dst,
FAIL:
_cairo_gl_composite_fini (&setup);
- if (new_src != src) {
- cairo_surface_destroy (new_src);
- cairo_surface_destroy (new_surface);
- _cairo_pattern_fini (&new_surface_pattern.base);
- }
-
+ if (new_src != src) {
+ cairo_surface_destroy (new_src);
+ cairo_surface_destroy (new_surface);
+ _cairo_pattern_fini (&new_surface_pattern.base);
+ }
+
return status;
}
@@ -542,10 +504,11 @@ tristrip_to_surface (void *_dst,
return (cairo_gl_surface_t *)image;
}
- mask = _cairo_surface_create_similar_scratch (_dst,
- CAIRO_CONTENT_COLOR_ALPHA,
- extents->width,
- extents->height);
+ mask = _cairo_surface_create_scratch (_dst,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ extents->width,
+ extents->height,
+ NULL);
if (unlikely (mask->status)) {
cairo_surface_destroy (image);
return (cairo_gl_surface_t *)mask;
@@ -648,8 +611,8 @@ _cairo_gl_traps_compositor_get (void)
compositor.check_composite = check_composite;
compositor.composite = composite;
compositor.lerp = lerp;
- //FIXME:
- compositor.lerp_color_glyph = lerp_color_glyph;
+ // FIXME:
+ compositor.lerp_color_glyph = lerp_color_glyph;
//compositor.check_composite_boxes = check_composite_boxes;
compositor.composite_boxes = composite_boxes;
//compositor.check_composite_traps = check_composite_traps;
diff --git a/src/cairo-gl.h b/src/cairo-gl.h
index 69738a265..85a0ac69e 100755..100644
--- a/src/cairo-gl.h
+++ b/src/cairo-gl.h
@@ -130,6 +130,21 @@ cairo_gl_surface_create_for_dc (cairo_device_t *device,
int height);
#endif
+#if CAIRO_HAS_CGL_FUNCTIONS
+#include <OpenGL/OpenGL.h>
+
+cairo_public cairo_device_t *
+cairo_cgl_device_create (CGLContextObj ctx);
+
+cairo_public cairo_surface_t *
+cairo_gl_surface_create_for_cgl (cairo_device_t *device,
+ int width,
+ int height);
+
+cairo_public CGLContextObj
+cairo_cgl_device_get_context (cairo_device_t *device);
+#endif
+
#if CAIRO_HAS_EGL_FUNCTIONS
#include <EGL/egl.h>
diff --git a/src/cairo-glx-context.c b/src/cairo-glx-context.c
index b4d706007..59e939292 100755..100644
--- a/src/cairo-glx-context.c
+++ b/src/cairo-glx-context.c
@@ -55,6 +55,7 @@ typedef struct _cairo_glx_context {
GLXDrawable current_drawable;
GLXContext previous_context;
+ GLXDrawable previous_drawable;
cairo_bool_t has_multithread_makecurrent;
} cairo_glx_context_t;
@@ -68,7 +69,8 @@ typedef struct _cairo_glx_surface {
static cairo_bool_t
_context_acquisition_changed_glx_state (cairo_glx_context_t *ctx)
{
- return ctx->previous_context != ctx->context;
+ return ctx->previous_context != ctx->context ||
+ ctx->previous_drawable != ctx->current_drawable;
}
static GLXDrawable
@@ -86,6 +88,7 @@ static void *
_glx_query_current_state (cairo_glx_context_t * ctx)
{
ctx->previous_context = glXGetCurrentContext ();
+ ctx->previous_drawable = glXGetCurrentDrawable ();
}
static void
@@ -252,7 +255,7 @@ _cairo_glx_get_proc_address (void *data, const char *name)
return func_map[i].func;
}
- return glXGetProcAddress (name);
+ return glXGetProcAddress (name);
}
cairo_device_t *
diff --git a/src/cairo-gstate-private.h b/src/cairo-gstate-private.h
index 92d3bb3c3..92d3bb3c3 100755..100644
--- a/src/cairo-gstate-private.h
+++ b/src/cairo-gstate-private.h
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 84b47fe9a..c747b3fa8 100755..100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -975,7 +975,7 @@ _cairo_gstate_copy_transformed_pattern (cairo_gstate_t *gstate,
surface = surface_pattern->surface;
if (_cairo_surface_has_device_transform (surface))
- _cairo_pattern_transform (pattern, &surface->device_transform);
+ _cairo_pattern_pretransform (pattern, &surface->device_transform);
}
if (! _cairo_matrix_is_identity (ctm_inverse))
@@ -1087,7 +1087,7 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
op = _reduce_op (gstate);
/* do not use static pattern */
if (op == CAIRO_OPERATOR_CLEAR) {
- if (! _cairo_gstate_has_shadow (gstate))
+ if (! _cairo_gstate_has_shadow (gstate))
pattern = &_cairo_pattern_clear.base;
else {
pattern = cairo_pattern_create_rgba (0, 0, 0, 0);
@@ -1219,6 +1219,8 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
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))
@@ -1239,8 +1241,15 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
assert (gstate->opacity == 1.0);
+ 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, &gstate->ctm, gstate->tolerance)) {
+ 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,
@@ -1259,8 +1268,8 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
&source_pattern.base,
path,
&style,
- &gstate->ctm,
- &gstate->ctm_inverse,
+ &aggregate_transform,
+ &aggregate_transform_inverse,
gstate->tolerance,
gstate->antialias,
gstate->clip);
@@ -1364,7 +1373,7 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
op = _reduce_op (gstate);
/* FIXME: I don't like this */
if (op == CAIRO_OPERATOR_CLEAR) {
- if (_cairo_gstate_has_shadow (gstate))
+ if (_cairo_gstate_has_shadow (gstate))
pattern = &_cairo_pattern_clear.base;
else {
pattern = cairo_pattern_create_rgba (0, 0, 0, 0);
@@ -1553,19 +1562,19 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
}
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
- cairo_traps_t traps;
-
- _cairo_traps_init (&traps);
- status = _cairo_path_fixed_stroke_polygon_to_traps (path,
- &gstate->stroke_style,
- &gstate->ctm,
- &gstate->ctm_inverse,
- gstate->tolerance,
- &traps);
- empty = traps.num_traps == 0;
+ cairo_polygon_t polygon;
+
+ _cairo_polygon_init (&polygon, NULL, 0);
+ status = _cairo_path_fixed_stroke_to_polygon (path,
+ &gstate->stroke_style,
+ &gstate->ctm,
+ &gstate->ctm_inverse,
+ gstate->tolerance,
+ &polygon);
+ empty = polygon.num_edges == 0;
if (! empty)
- _cairo_traps_extents (&traps, &extents);
- _cairo_traps_fini (&traps);
+ extents = polygon.extents;
+ _cairo_polygon_fini (&polygon);
}
if (! empty) {
_cairo_gstate_extents_to_user_rectangle (gstate, &extents,
@@ -1924,6 +1933,7 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate)
cairo_status_t status;
cairo_font_options_t options;
cairo_scaled_font_t *scaled_font;
+ cairo_matrix_t font_ctm;
if (gstate->scaled_font != NULL)
return gstate->scaled_font->status;
@@ -1935,9 +1945,13 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate)
cairo_surface_get_font_options (gstate->target, &options);
cairo_font_options_merge (&options, &gstate->font_options);
+ cairo_matrix_multiply (&font_ctm,
+ &gstate->ctm,
+ &gstate->target->device_transform);
+
scaled_font = cairo_scaled_font_create (gstate->font_face,
&gstate->font_matrix,
- &gstate->ctm,
+ &font_ctm,
&options);
status = cairo_scaled_font_status (scaled_font);
@@ -2094,6 +2108,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
if (cairo_surface_has_show_text_glyphs (gstate->target) ||
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240)
{
+
if (info != NULL) {
status = _cairo_surface_show_text_glyphs (gstate->target, op, pattern,
info->utf8, info->utf8_len,
diff --git a/src/cairo-hash-private.h b/src/cairo-hash-private.h
index 30e51ffe6..30e51ffe6 100755..100644
--- a/src/cairo-hash-private.h
+++ b/src/cairo-hash-private.h
diff --git a/src/cairo-hash.c b/src/cairo-hash.c
index 928c74b8b..928c74b8b 100755..100644
--- a/src/cairo-hash.c
+++ b/src/cairo-hash.c
diff --git a/src/cairo-hull.c b/src/cairo-hull.c
index c65593327..c65593327 100755..100644
--- a/src/cairo-hull.c
+++ b/src/cairo-hull.c
diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c
index a732f2a3a..18a44fb8c 100755..100644
--- a/src/cairo-image-compositor.c
+++ b/src/cairo-image-compositor.c
@@ -52,9 +52,7 @@
#include "cairo-traps-private.h"
#include "cairo-tristrip-private.h"
-#if CAIRO_HAS_TG_SURFACE
-#include "cairo-thread-local-private.h"
-#endif
+#include "cairo-pixman-private.h"
static pixman_image_t *
to_pixman_image (cairo_surface_t *s)
@@ -260,9 +258,9 @@ _pixman_operator (cairo_operator_t op)
}
static cairo_bool_t
-fill_reduces_to_source (cairo_operator_t op,
- const cairo_color_t *color,
- cairo_image_surface_t *dst)
+__fill_reduces_to_source (cairo_operator_t op,
+ const cairo_color_t *color,
+ const cairo_image_surface_t *dst)
{
if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR)
return TRUE;
@@ -274,6 +272,19 @@ fill_reduces_to_source (cairo_operator_t op,
return FALSE;
}
+static cairo_bool_t
+fill_reduces_to_source (cairo_operator_t op,
+ const cairo_color_t *color,
+ const cairo_image_surface_t *dst,
+ uint32_t *pixel)
+{
+ if (__fill_reduces_to_source (op, color, dst)) {
+ return color_to_pixel (color, dst->pixman_format, pixel);
+ }
+
+ return FALSE;
+}
+
static cairo_int_status_t
fill_rectangles (void *_dst,
cairo_operator_t op,
@@ -287,9 +298,7 @@ fill_rectangles (void *_dst,
TRACE ((stderr, "%s\n", __FUNCTION__));
- if (fill_reduces_to_source (op, color, dst) &&
- color_to_pixel (color, dst->pixman_format, &pixel))
- {
+ if (fill_reduces_to_source (op, color, dst, &pixel)) {
for (i = 0; i < num_rects; i++) {
pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
PIXMAN_FORMAT_BPP (dst->pixman_format),
@@ -297,12 +306,10 @@ fill_rectangles (void *_dst,
rects[i].width, rects[i].height,
pixel);
}
- }
- else
- {
+ } else {
pixman_image_t *src = _pixman_image_for_color (color);
- if (src == NULL)
- return CAIRO_STATUS_NULL_POINTER;
+ if (unlikely (src == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
op = _pixman_operator (op);
for (i = 0; i < num_rects; i++) {
@@ -333,9 +340,7 @@ fill_boxes (void *_dst,
TRACE ((stderr, "%s x %d\n", __FUNCTION__, boxes->num_boxes));
- if (fill_reduces_to_source (op, color, dst) &&
- color_to_pixel (color, dst->pixman_format, &pixel))
- {
+ if (fill_reduces_to_source (op, color, dst, &pixel)) {
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
for (i = 0; i < chunk->count; i++) {
int x = _cairo_fixed_integer_part (chunk->base[i].p1.x);
@@ -352,8 +357,8 @@ fill_boxes (void *_dst,
else
{
pixman_image_t *src = _pixman_image_for_color (color);
- if (src == NULL)
- return CAIRO_STATUS_NULL_POINTER;
+ if (unlikely (src == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
op = _pixman_operator (op);
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
@@ -472,49 +477,49 @@ lerp (void *_dst,
}
static cairo_int_status_t
-lerp_color_glyph (void *_dst,
- cairo_surface_t *abstract_src,
- cairo_surface_t *abstract_mask,
- int src_x,
- int src_y,
- int mask_x,
- int mask_y,
- int dst_x,
- int dst_y,
- unsigned int width,
- unsigned int height)
-{
- cairo_image_surface_t *dst = _dst;
- cairo_image_source_t *src = (cairo_image_source_t *)abstract_src;
- cairo_image_source_t *mask = (cairo_image_source_t *)abstract_mask;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- /* Punch the clip out of the destination */
- TRACE ((stderr, "%s - OUT_REVERSE (mask=%d/%p, dst=%d/%p)\n",
- __FUNCTION__,
- mask->base.unique_id, mask->pixman_image,
- dst->base.unique_id, dst->pixman_image));
- pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
- mask->pixman_image, src->pixman_image, dst->pixman_image,
- mask_x, mask_y,
- 0, 0,
- dst_x, dst_y,
- width, height);
-
- /* Now add the two results together */
- TRACE ((stderr, "%s - ADD (src=%d/%p, mask=%d/%p, dst=%d/%p)\n",
- __FUNCTION__,
- src->base.unique_id, src->pixman_image,
- mask->base.unique_id, mask->pixman_image,
- dst->base.unique_id, dst->pixman_image));
- pixman_image_composite32 (PIXMAN_OP_ADD,
- src->pixman_image, mask->pixman_image, dst->pixman_image,
- src_x, src_y,
- mask_x, mask_y,
- dst_x, dst_y,
- width, height);
- return CAIRO_STATUS_SUCCESS;
+lerp_color_glyph (void *_dst,
+ cairo_surface_t *abstract_src,
+ cairo_surface_t *abstract_mask,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height)
+{
+ cairo_image_surface_t *dst = _dst;
+ cairo_image_source_t *src = (cairo_image_source_t *)abstract_src;
+ cairo_image_source_t *mask = (cairo_image_source_t *)abstract_mask;
+
+ TRACE ((stderr, "%s\n", __FUNCTION__));
+
+ /* Punch the clip out of the destination */
+ TRACE ((stderr, "%s - OUT_REVERSE (mask=%d/%p, dst=%d/%p)\n",
+ __FUNCTION__,
+ mask->base.unique_id, mask->pixman_image,
+ dst->base.unique_id, dst->pixman_image));
+ pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
+ mask->pixman_image, src->pixman_image, dst->pixman_image,
+ mask_x, mask_y,
+ 0, 0,
+ dst_x, dst_y,
+ width, height);
+
+ /* Now add the two results together */
+ TRACE ((stderr, "%s - ADD (src=%d/%p, mask=%d/%p, dst=%d/%p)\n",
+ __FUNCTION__,
+ src->base.unique_id, src->pixman_image,
+ mask->base.unique_id, mask->pixman_image,
+ dst->base.unique_id, dst->pixman_image));
+ pixman_image_composite32 (PIXMAN_OP_ADD,
+ src->pixman_image, mask->pixman_image, dst->pixman_image,
+ src_x, src_y,
+ mask_x, mask_y,
+ dst_x, dst_y,
+ width, height);
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -552,9 +557,8 @@ composite_boxes (void *_dst,
op = PIXMAN_OP_LERP_CLEAR;
#else
free_src = src = _pixman_image_for_color (CAIRO_COLOR_WHITE);
- if (src == NULL)
- return CAIRO_STATUS_NULL_POINTER;
-
+ if (unlikely (src == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
op = PIXMAN_OP_OUT_REVERSE;
#endif
} else if (op == CAIRO_OPERATOR_SOURCE) {
@@ -691,11 +695,18 @@ composite_traps (void *_dst,
{
cairo_image_surface_t *dst = (cairo_image_surface_t *) _dst;
cairo_image_source_t *src = (cairo_image_source_t *) abstract_src;
+ cairo_int_status_t status;
pixman_image_t *mask;
pixman_format_code_t format;
TRACE ((stderr, "%s\n", __FUNCTION__));
+ /* pixman doesn't eliminate self-intersecting trapezoids/edges */
+ status = _cairo_bentley_ottmann_tessellate_traps (traps,
+ CAIRO_FILL_RULE_WINDING);
+ if (status != CAIRO_INT_STATUS_SUCCESS)
+ return status;
+
/* Special case adding trapezoids onto a mask surface; we want to avoid
* creating an intermediate temporary mask unnecessarily.
*
@@ -731,6 +742,7 @@ composite_traps (void *_dst,
return CAIRO_STATUS_SUCCESS;
}
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
static void
set_point (pixman_point_fixed_t *p, cairo_point_t *c)
{
@@ -779,6 +791,31 @@ composite_tristrip (void *_dst,
if (strip->num_points < 3)
return CAIRO_STATUS_SUCCESS;
+ if (1) { /* pixman doesn't eliminate self-intersecting triangles/edges */
+ cairo_int_status_t status;
+ cairo_traps_t traps;
+ int n;
+
+ _cairo_traps_init (&traps);
+ for (n = 0; n < strip->num_points; n++) {
+ cairo_point_t p[4];
+
+ p[0] = strip->points[0];
+ p[1] = strip->points[1];
+ p[2] = strip->points[2];
+ p[3] = strip->points[0];
+
+ _cairo_traps_tessellate_convex_quad (&traps, p);
+ }
+ status = composite_traps (_dst, op, abstract_src,
+ src_x, src_y,
+ dst_x, dst_y,
+ extents, antialias, &traps);
+ _cairo_traps_fini (&traps);
+
+ return status;
+ }
+
format = antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8;
if (dst->pixman_format == format &&
(abstract_src == NULL ||
@@ -806,6 +843,7 @@ composite_tristrip (void *_dst,
return CAIRO_STATUS_SUCCESS;
}
+#endif
static cairo_int_status_t
check_composite_glyphs (const cairo_composite_rectangles_t *extents,
@@ -817,51 +855,30 @@ check_composite_glyphs (const cairo_composite_rectangles_t *extents,
}
#if 0 && HAS_PIXMAN_GLYPHS
-#if CAIRO_HAS_TG_SURFACE
-CAIRO_DEFINE_THREAD_LOCAL (pixman_glyph_cache_t *, per_thread_glyph_cache);
-#else
static pixman_glyph_cache_t *global_glyph_cache;
-#endif
static inline pixman_glyph_cache_t *
get_glyph_cache (void)
{
- pixman_glyph_cache_t **glyph_cache = NULL;
+ if (!global_glyph_cache)
+ global_glyph_cache = pixman_glyph_cache_create ();
-#if CAIRO_HAS_TG_SURFACE
- glyph_cache = CAIRO_GET_THREAD_LOCAL (per_thread_glyph_cache);
-#else
- glyph_cache = &global_glyph_cache;
-#endif
-
- if (! (*glyph_cache))
- *glyph_cache = pixman_glyph_cache_create ();
-
- return *glyph_cache;
+ return global_glyph_cache;
}
void
_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
- pixman_glyph_cache_t *glyph_cache = NULL;
-
-#if CAIRO_HAS_TG_SURFACE
- glyph_cache = *CAIRO_GET_THREAD_LOCAL (per_thread_glyph_cache);
-#else
- glyph_cache = global_glyph_cache;
CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
-#endif
- if (glyph_cache) {
+ if (global_glyph_cache) {
pixman_glyph_cache_remove (
- glyph_cache, scaled_font,
+ global_glyph_cache, scaled_font,
(void *)_cairo_scaled_glyph_index (scaled_glyph));
}
-#if ! CAIRO_HAS_TG_SURFACE
CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
-#endif
}
static cairo_int_status_t
@@ -883,9 +900,7 @@ composite_glyphs (void *_dst,
TRACE ((stderr, "%s\n", __FUNCTION__));
-#if ! CAIRO_HAS_TG_SURFACE
CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
-#endif
glyph_cache = get_glyph_cache();
if (unlikely (glyph_cache == NULL)) {
@@ -913,43 +928,23 @@ composite_glyphs (void *_dst,
cairo_scaled_glyph_t *scaled_glyph;
cairo_image_surface_t *glyph_surface;
-#if ! CAIRO_HAS_TG_SURFACE
/* This call can actually end up recursing, so we have to
* drop the mutex around it.
*/
CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
-#else
- _cairo_scaled_font_freeze_cache (info->font);
- CAIRO_MUTEX_LOCK (_cairo_tg_scaled_glyph_mutex);
-#endif
-
status = _cairo_scaled_glyph_lookup (info->font, index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
&scaled_glyph);
-
-#if ! CAIRO_HAS_TG_SURFACE
CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
-#endif
- if (unlikely (status)) {
-#if CAIRO_HAS_TG_SURFACE
- CAIRO_MUTEX_UNLOCK (_cairo_tg_scaled_glyph_mutex);
- _cairo_scaled_font_thaw_cache (info->font);
-#endif
+ if (unlikely (status))
goto out_thaw;
- }
glyph_surface = scaled_glyph->surface;
glyph = pixman_glyph_cache_insert (glyph_cache, info->font, (void *)index,
glyph_surface->base.device_transform.x0,
glyph_surface->base.device_transform.y0,
glyph_surface->pixman_image);
-
-#if CAIRO_HAS_TG_SURFACE
- CAIRO_MUTEX_UNLOCK (_cairo_tg_scaled_glyph_mutex);
- _cairo_scaled_font_thaw_cache (info->font);
-#endif
-
if (unlikely (!glyph)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto out_thaw;
@@ -992,10 +987,7 @@ out_thaw:
free(pglyphs);
out_unlock:
-#if ! CAIRO_HAS_TG_SURFACE
CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
-#endif
-
return status;
}
#else
@@ -1015,7 +1007,7 @@ composite_one_glyph (void *_dst,
int dst_y,
cairo_composite_glyphs_info_t *info)
{
- cairo_image_surface_t *dst_surface = (cairo_image_surface_t *)_dst;
+ cairo_image_surface_t *dst_surface = (cairo_image_surface_t *)_dst;
cairo_image_surface_t *glyph_surface;
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status;
@@ -1035,11 +1027,11 @@ composite_one_glyph (void *_dst,
if (glyph_surface->width == 0 || glyph_surface->height == 0)
return CAIRO_INT_STATUS_NOTHING_TO_DO;
- if (glyph_surface->format == CAIRO_FORMAT_ARGB32 &&
- dst_surface->format != CAIRO_FORMAT_ARGB32) {
+ if (glyph_surface->format == CAIRO_FORMAT_ARGB32 &&
+ dst_surface->format != CAIRO_FORMAT_ARGB32) {
/* FIXME: color glyph */
return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
- }
+ }
/* round glyph locations to the nearest pixel */
/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
@@ -1048,28 +1040,27 @@ composite_one_glyph (void *_dst,
y = _cairo_lround (info->glyphs[0].y -
glyph_surface->base.device_transform.y0);
-
- if (glyph_surface->format != CAIRO_FORMAT_ARGB32 ||
- pixman_image_get_component_alpha (glyph_surface->pixman_image))
- pixman_image_composite32 (_pixman_operator (op),
- ((cairo_image_source_t *)_src)->pixman_image,
- glyph_surface->pixman_image,
- to_pixman_image (_dst),
- x + src_x, y + src_y,
- 0, 0,
- x - dst_x, y - dst_y,
- glyph_surface->width,
- glyph_surface->height);
- else /* color glyph */
- pixman_image_composite32 (_pixman_operator (op),
- glyph_surface->pixman_image,
- NULL,
- to_pixman_image (_dst),
- 0, 0,
- x + src_x, y + src_y,
- x - dst_x, y - dst_y,
- glyph_surface->width,
- glyph_surface->height);
+ if (glyph_surface->format != CAIRO_FORMAT_ARGB32 ||
+ pixman_image_get_component_alpha (glyph_surface->pixman_image))
+ pixman_image_composite32 (_pixman_operator (op),
+ ((cairo_image_source_t *)_src)->pixman_image,
+ glyph_surface->pixman_image,
+ to_pixman_image (_dst),
+ x + src_x, y + src_y,
+ 0, 0,
+ x - dst_x, y - dst_y,
+ glyph_surface->width,
+ glyph_surface->height);
+ else /* color glyph */
+ pixman_image_composite32 (_pixman_operator (op),
+ glyph_surface->pixman_image,
+ NULL,
+ to_pixman_image (_dst),
+ 0, 0,
+ x + src_x, y + src_y,
+ x - dst_x, y - dst_y,
+ glyph_surface->width,
+ glyph_surface->height);
return CAIRO_INT_STATUS_SUCCESS;
}
@@ -1092,7 +1083,7 @@ composite_glyphs_via_mask (void *_dst,
pixman_format_code_t format;
cairo_status_t status;
int i;
- cairo_bool_t component_alpha = FALSE;
+ cairo_bool_t component_alpha = FALSE;
TRACE ((stderr, "%s\n", __FUNCTION__));
@@ -1167,7 +1158,7 @@ composite_glyphs_via_mask (void *_dst,
glyph_surface = scaled_glyph->surface;
if (! component_alpha)
- component_alpha = pixman_image_get_component_alpha (glyph_surface->pixman_image);
+ component_alpha = pixman_image_get_component_alpha (glyph_surface->pixman_image);
if (glyph_surface->width && glyph_surface->height) {
if (glyph_surface->base.content & CAIRO_CONTENT_COLOR &&
format == PIXMAN_a8) {
@@ -1225,22 +1216,22 @@ composite_glyphs_via_mask (void *_dst,
if (format == PIXMAN_a8r8g8b8 && component_alpha)
pixman_image_set_component_alpha (mask, TRUE);
- if (format != PIXMAN_a8r8g8b8 || component_alpha)
- pixman_image_composite32 (_pixman_operator (op),
- ((cairo_image_source_t *)_src)->pixman_image,
- mask,
- to_pixman_image (_dst),
- info->extents.x + src_x, info->extents.y + src_y,
- 0, 0,
- info->extents.x - dst_x, info->extents.y - dst_y,
- info->extents.width, info->extents.height);
- else /* color glyph */
- pixman_image_composite32 (_pixman_operator (op), mask, NULL,
- to_pixman_image (_dst),
- 0, 0,
- info->extents.x + src_x, info->extents.y + src_y,
- info->extents.x - dst_x, info->extents.y - dst_y,
- info->extents.width, info->extents.height);
+ if (format != PIXMAN_a8r8g8b8 || component_alpha)
+ pixman_image_composite32 (_pixman_operator (op),
+ ((cairo_image_source_t *)_src)->pixman_image,
+ mask,
+ to_pixman_image (_dst),
+ info->extents.x + src_x, info->extents.y + src_y,
+ 0, 0,
+ info->extents.x - dst_x, info->extents.y - dst_y,
+ info->extents.width, info->extents.height);
+ else /* color glyph */
+ pixman_image_composite32 (_pixman_operator (op), mask, NULL,
+ to_pixman_image (_dst),
+ 0, 0,
+ info->extents.x + src_x, info->extents.y + src_y,
+ info->extents.x - dst_x, info->extents.y - dst_y,
+ info->extents.width, info->extents.height);
pixman_image_unref (mask);
pixman_image_unref (white);
@@ -1261,24 +1252,17 @@ composite_glyphs (void *_dst,
pixman_image_t *dst, *src;
cairo_status_t status;
int i;
- cairo_image_surface_t *dst_surface = (cairo_image_surface_t *)_dst;
+ cairo_image_surface_t *dst_surface = (cairo_image_surface_t *)_dst;
TRACE ((stderr, "%s\n", __FUNCTION__));
-#if CAIRO_HAS_TG_SURFACE
- _cairo_scaled_font_freeze_cache (info->font);
- CAIRO_MUTEX_LOCK (_cairo_tg_scaled_glyph_mutex);
-#endif
+ /* XXX */
+ if (0 && info->num_glyphs == 1)
+ return composite_one_glyph(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
- if (0 && info->num_glyphs == 1) {
- status = composite_one_glyph(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
- goto out_thaw;
- }
-
- if (0 && info->use_mask) {
- status = composite_glyphs_via_mask(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
- goto out_thaw;
- }
+ /* XXX */
+ if (info->use_mask)
+ return composite_glyphs_via_mask(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
op = _pixman_operator (op);
dst = to_pixman_image (_dst);
@@ -1310,9 +1294,9 @@ composite_glyphs (void *_dst,
glyph_surface = scaled_glyph->surface;
if (glyph_surface->format == CAIRO_FORMAT_ARGB32 &&
- dst_surface->format != CAIRO_FORMAT_ARGB32) {
- /* FIXME: color glyph */
- return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+ dst_surface->format != CAIRO_FORMAT_ARGB32) {
+ /* FIXME: color glyph */
+ return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
}
if (glyph_surface->width && glyph_surface->height) {
@@ -1323,30 +1307,24 @@ composite_glyphs (void *_dst,
y = _cairo_lround (info->glyphs[i].y -
glyph_surface->base.device_transform.y0);
- if (glyph_surface->format != CAIRO_FORMAT_ARGB32 ||
+ if (glyph_surface->format != CAIRO_FORMAT_ARGB32 ||
pixman_image_get_component_alpha (glyph_surface->pixman_image))
- pixman_image_composite32 (op, src, glyph_surface->pixman_image, dst,
- x + src_x, y + src_y,
- 0, 0,
- x - dst_x, y - dst_y,
- glyph_surface->width,
- glyph_surface->height);
- else /* Color glyph. */
- pixman_image_composite32 (op, glyph_surface->pixman_image, NULL, dst,
- 0, 0,
- x + src_x, y + src_y,
- x - dst_x, y - dst_y,
- glyph_surface->width,
- glyph_surface->height);
- }
+ pixman_image_composite32 (op, src, glyph_surface->pixman_image, dst,
+ x + src_x, y + src_y,
+ 0, 0,
+ x - dst_x, y - dst_y,
+ glyph_surface->width,
+ glyph_surface->height);
+ else /* Color glyph. */
+ pixman_image_composite32 (op, glyph_surface->pixman_image, NULL, dst,
+ 0, 0,
+ x + src_x, y + src_y,
+ x - dst_x, y - dst_y,
+ glyph_surface->width,
+ glyph_surface->height);
+ }
}
-out_thaw:
-#if CAIRO_HAS_TG_SURFACE
- _cairo_scaled_font_thaw_cache (info->font);
- CAIRO_MUTEX_UNLOCK (_cairo_tg_scaled_glyph_mutex);
-#endif
-
return status;
}
#endif
@@ -1381,7 +1359,9 @@ _cairo_image_traps_compositor_get (void)
//compositor.check_composite_traps = check_composite_traps;
compositor.composite_traps = composite_traps;
//compositor.check_composite_tristrip = check_composite_traps;
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
compositor.composite_tristrip = composite_tristrip;
+#endif
compositor.check_composite_glyphs = check_composite_glyphs;
compositor.composite_glyphs = composite_glyphs;
}
@@ -1404,9 +1384,10 @@ _cairo_image_mask_compositor_get (void)
compositor.draw_image_boxes = draw_image_boxes;
compositor.fill_rectangles = fill_rectangles;
compositor.fill_boxes = fill_boxes;
- //compositor.check_composite = check_composite;
+ compositor.check_composite = check_composite;
compositor.composite = composite;
//compositor.lerp = lerp;
+ //compositor.lerp_color_glyph = lerp_color_glyph;
//compositor.check_composite_boxes = check_composite_boxes;
compositor.composite_boxes = composite_boxes;
compositor.check_composite_glyphs = check_composite_glyphs;
@@ -1714,7 +1695,7 @@ typedef struct _cairo_image_span_renderer {
} mask;
} u;
uint8_t _buf[0];
-#define SZ_BUF (sizeof (cairo_abstract_span_renderer_t) - sizeof (cairo_image_span_renderer_t))
+#define SZ_BUF (int)(sizeof (cairo_abstract_span_renderer_t) - sizeof (cairo_image_span_renderer_t))
} cairo_image_span_renderer_t;
COMPILE_TIME_ASSERT (sizeof (cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t));
@@ -2184,8 +2165,7 @@ mono_renderer_init (cairo_image_span_renderer_t *r,
if (composite->op == CAIRO_OPERATOR_CLEAR)
color = CAIRO_COLOR_TRANSPARENT;
- if (fill_reduces_to_source (composite->op, color, dst) &&
- color_to_pixel (color, dst->pixman_format, &r->u.fill.pixel)) {
+ if (fill_reduces_to_source (composite->op, color, dst, &r->u.fill.pixel)) {
/* Use plain C for the fill operations as the span length is
* typically small, too small to payback the startup overheads of
* using SSE2 etc.
@@ -2366,10 +2346,10 @@ _fill_xrgb32_lerp_opaque_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;
}
- } else while (len--) {
+ } else while (len-- > 0) {
*d = lerp8x4 (r->u.fill.pixel, a, *d);
d++;
}
@@ -2943,8 +2923,7 @@ inplace_renderer_init (cairo_image_span_renderer_t *r,
if (composite->op == CAIRO_OPERATOR_CLEAR)
color = CAIRO_COLOR_TRANSPARENT;
- if (fill_reduces_to_source (composite->op, color, dst) &&
- color_to_pixel (color, dst->pixman_format, &r->u.fill.pixel)) {
+ if (fill_reduces_to_source (composite->op, color, dst, &r->u.fill.pixel)) {
/* Use plain C for the fill operations as the span length is
* typically small, too small to payback the startup overheads of
* using SSE2 etc.
@@ -3181,7 +3160,7 @@ span_renderer_init (cairo_abstract_span_renderer_t *_r,
r->u.mask.extents = composite->unbounded;
r->u.mask.stride = (r->u.mask.extents.width + 3) & ~3;
- if (r->u.mask.extents.height * r->u.mask.stride > (int)sizeof (r->_buf)) {
+ if (r->u.mask.extents.height * r->u.mask.stride > SZ_BUF) {
r->mask = pixman_image_create_bits (PIXMAN_a8,
r->u.mask.extents.width,
r->u.mask.extents.height,
@@ -3217,12 +3196,11 @@ span_renderer_fini (cairo_abstract_span_renderer_t *_r,
TRACE ((stderr, "%s\n", __FUNCTION__));
if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
- if (r->base.finish)
+ if (r->base.finish)
r->base.finish (r);
}
-
if (likely (status == CAIRO_INT_STATUS_SUCCESS && r->bpp == 0)) {
- const cairo_composite_rectangles_t *composite = r->composite;
+ const cairo_composite_rectangles_t *composite = r->composite;
pixman_image_composite32 (r->op, r->src, r->mask,
to_pixman_image (composite->surface),
diff --git a/src/cairo-image-filters-private.h b/src/cairo-image-filters-private.h
index a9e47f0b3..2761c7b29 100755..100644
--- a/src/cairo-image-filters-private.h
+++ b/src/cairo-image-filters-private.h
@@ -49,8 +49,8 @@
#define MAX_BLUR_SIZE 256
-cairo_private cairo_surface_t *
-_cairo_image_gaussian_filter (cairo_surface_t *src,
+cairo_private cairo_surface_t *
+_cairo_image_gaussian_filter (cairo_surface_t *src,
const cairo_pattern_t *pattern);
#endif /* CAIRO_IMAGE_FILTERS_PRIVATE_H */
diff --git a/src/cairo-image-filters.c b/src/cairo-image-filters.c
index 1f0531ef2..1216b7931 100755..100644
--- a/src/cairo-image-filters.c
+++ b/src/cairo-image-filters.c
@@ -106,7 +106,7 @@ _pixman_image_create_convolution_params (double *params,
return pixman_params;
}
-cairo_surface_t *
+cairo_surface_t *
_cairo_image_gaussian_filter (cairo_surface_t *src, const cairo_pattern_t *pattern)
{
int row, col;
@@ -139,10 +139,10 @@ _cairo_image_gaussian_filter (cairo_surface_t *src, const cairo_pattern_t *patt
row = pattern->y_radius * 2 + 1;
col = pattern->x_radius * 2 + 1;
- width = src_width / pattern->shrink_factor_x;
- height = src_height / pattern->shrink_factor_y;
+ width = src_width / pattern->shrink_factor_x;
+ height = src_height / pattern->shrink_factor_y;
stride = width * (src_image->stride / src_width);
-
+
clone_image = (cairo_image_surface_t *)
cairo_image_surface_create (src_image->format,
src_width, src_height);
@@ -152,7 +152,7 @@ _cairo_image_gaussian_filter (cairo_surface_t *src, const cairo_pattern_t *patt
clone_image = (cairo_image_surface_t *)cairo_surface_reference (src);
goto DONE;
}
-
+
/* XXX: we must always create a clone because we need to modify
* it transformation, no copy data */
temp_image = pixman_image_create_bits (src_image->pixman_format,
@@ -165,7 +165,7 @@ _cairo_image_gaussian_filter (cairo_surface_t *src, const cairo_pattern_t *patt
clone_image = (cairo_image_surface_t *)cairo_surface_reference (src);
goto DONE;
}
-
+
/* create scratch images */
for (i = 0; i < 2; i++) {
scratch_images[i] = pixman_image_create_bits (src_image->pixman_format,
@@ -183,7 +183,7 @@ _cairo_image_gaussian_filter (cairo_surface_t *src, const cairo_pattern_t *patt
if (width != src_width || height != src_height) {
pixman_image_set_filter (temp_image, PIXMAN_FILTER_NEAREST, NULL, 0);
/* set up transform matrix */
- cairo_matrix_init_scale (&matrix,
+ cairo_matrix_init_scale (&matrix,
(double) src_width / (double) width,
(double) src_height / (double) height);
status = _cairo_matrix_to_pixman_matrix_offset (&matrix,
@@ -264,7 +264,7 @@ _cairo_image_gaussian_filter (cairo_surface_t *src, const cairo_pattern_t *patt
/* paint scratch_surfaces[0] to clone */
/* set up transform matrix */
- cairo_matrix_init_scale (&matrix,
+ cairo_matrix_init_scale (&matrix,
(double) width / (double) src_width,
(double) height / (double) src_height);
status = _cairo_matrix_to_pixman_matrix_offset (&matrix,
diff --git a/src/cairo-image-info-private.h b/src/cairo-image-info-private.h
index 0d9ef8498..e64928e40 100755..100644
--- a/src/cairo-image-info-private.h
+++ b/src/cairo-image-info-private.h
@@ -60,4 +60,9 @@ _cairo_image_info_get_png_info (cairo_image_info_t *info,
const unsigned char *data,
unsigned long length);
+cairo_private cairo_int_status_t
+_cairo_image_info_get_jbig2_info (cairo_image_info_t *info,
+ const unsigned char *data,
+ unsigned long length);
+
#endif /* CAIRO_IMAGE_INFO_PRIVATE_H */
diff --git a/src/cairo-image-info.c b/src/cairo-image-info.c
index 4489698e8..26e7ae5af 100755..100644
--- a/src/cairo-image-info.c
+++ b/src/cairo-image-info.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2008 Adrian Johnson
@@ -38,12 +39,6 @@
#include "cairo-error-private.h"
#include "cairo-image-info-private.h"
-static uint32_t
-_get_be32 (const unsigned char *p)
-{
- return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
-}
-
/* JPEG (image/jpeg)
*
* http://www.w3.org/Graphics/JPEG/itu-t81.pdf
@@ -169,7 +164,7 @@ static const unsigned char _jpx_signature[] = {
static const unsigned char *
_jpx_next_box (const unsigned char *p)
{
- return p + _get_be32 (p);
+ return p + get_unaligned_be32 (p);
}
static const unsigned char *
@@ -184,8 +179,8 @@ _jpx_match_box (const unsigned char *p, const unsigned char *end, uint32_t type)
uint32_t length;
if (p + 8 < end) {
- length = _get_be32 (p);
- if (_get_be32 (p + 4) == type && p + length < end)
+ length = get_unaligned_be32 (p);
+ if (get_unaligned_be32 (p + 4) == type && p + length < end)
return TRUE;
}
@@ -207,8 +202,8 @@ _jpx_find_box (const unsigned char *p, const unsigned char *end, uint32_t type)
static void
_jpx_extract_info (const unsigned char *p, cairo_image_info_t *info)
{
- info->height = _get_be32 (p);
- info->width = _get_be32 (p + 4);
+ info->height = get_unaligned_be32 (p);
+ info->width = get_unaligned_be32 (p + 4);
info->num_components = (p[8] << 8) + p[9];
info->bits_per_component = p[10];
}
@@ -280,13 +275,147 @@ _cairo_image_info_get_png_info (cairo_image_info_t *info,
return CAIRO_INT_STATUS_UNSUPPORTED;
p += 4;
- if (_get_be32 (p) != PNG_IHDR)
+ if (get_unaligned_be32 (p) != PNG_IHDR)
return CAIRO_INT_STATUS_UNSUPPORTED;
p += 4;
- info->width = _get_be32 (p);
+ info->width = get_unaligned_be32 (p);
p += 4;
- info->height = _get_be32 (p);
+ info->height = get_unaligned_be32 (p);
return CAIRO_STATUS_SUCCESS;
}
+
+static const unsigned char *
+_jbig2_find_data_end (const unsigned char *p,
+ const unsigned char *end,
+ int type)
+{
+ unsigned char end_seq[2];
+ int mmr;
+
+ /* Segments of type "Immediate generic region" may have an
+ * unspecified data length. The JBIG2 specification specifies the
+ * method to find the end of the data for these segments. */
+ if (type == 36 || type == 38 || type == 39) {
+ if (p + 18 < end) {
+ mmr = p[17] & 0x01;
+ if (mmr) {
+ /* MMR encoding ends with 0x00, 0x00 */
+ end_seq[0] = 0x00;
+ end_seq[1] = 0x00;
+ } else {
+ /* Template encoding ends with 0xff, 0xac */
+ end_seq[0] = 0xff;
+ end_seq[1] = 0xac;
+ }
+ p += 18;
+ while (p < end) {
+ if (p[0] == end_seq[0] && p[1] == end_seq[1]) {
+ /* Skip the 2 terminating bytes and the 4 byte row count that follows. */
+ p += 6;
+ if (p < end)
+ return p;
+ }
+ p++;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static const unsigned char *
+_jbig2_get_next_segment (const unsigned char *p,
+ const unsigned char *end,
+ int *type,
+ const unsigned char **data,
+ unsigned long *data_len)
+{
+ unsigned long seg_num;
+ cairo_bool_t big_page_size;
+ int num_segs;
+ int ref_seg_bytes;
+ int referred_size;
+
+ if (p + 6 >= end)
+ return NULL;
+
+ seg_num = get_unaligned_be32 (p);
+ *type = p[4] & 0x3f;
+ big_page_size = (p[4] & 0x40) != 0;
+ p += 5;
+
+ num_segs = p[0] >> 5;
+ if (num_segs == 7) {
+ num_segs = get_unaligned_be32 (p) & 0x1fffffff;
+ ref_seg_bytes = 4 + ((num_segs + 1)/8);
+ } else {
+ ref_seg_bytes = 1;
+ }
+ p += ref_seg_bytes;
+
+ if (seg_num <= 256)
+ referred_size = 1;
+ else if (seg_num <= 65536)
+ referred_size = 2;
+ else
+ referred_size = 4;
+
+ p += num_segs * referred_size;
+ p += big_page_size ? 4 : 1;
+ if (p + 4 >= end)
+ return NULL;
+
+ *data_len = get_unaligned_be32 (p);
+ p += 4;
+ *data = p;
+
+ if (*data_len == 0xffffffff) {
+ /* if data length is -1 we have to scan through the data to find the end */
+ p = _jbig2_find_data_end (*data, end, *type);
+ if (!p || p >= end)
+ return NULL;
+
+ *data_len = p - *data;
+ } else {
+ p += *data_len;
+ }
+
+ if (p < end)
+ return p;
+ else
+ return NULL;
+}
+
+static void
+_jbig2_extract_info (cairo_image_info_t *info, const unsigned char *p)
+{
+ info->width = get_unaligned_be32 (p);
+ info->height = get_unaligned_be32 (p + 4);
+ info->num_components = 1;
+ info->bits_per_component = 1;
+}
+
+cairo_int_status_t
+_cairo_image_info_get_jbig2_info (cairo_image_info_t *info,
+ const unsigned char *data,
+ unsigned long length)
+{
+ const unsigned char *p = data;
+ const unsigned char *end = data + length;
+ int seg_type;
+ const unsigned char *seg_data;
+ unsigned long seg_data_len;
+
+ while (p && p < end) {
+ p = _jbig2_get_next_segment (p, end, &seg_type, &seg_data, &seg_data_len);
+ if (p && seg_type == 48 && seg_data_len > 8) {
+ /* page information segment */
+ _jbig2_extract_info (info, seg_data);
+ return CAIRO_STATUS_SUCCESS;
+ }
+ }
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
diff --git a/src/cairo-image-mask-compositor.c b/src/cairo-image-mask-compositor.c
index 33fd6dd87..bb990dd65 100755..100644
--- a/src/cairo-image-mask-compositor.c
+++ b/src/cairo-image-mask-compositor.c
@@ -48,6 +48,8 @@
#include "cairo-compositor-private.h"
#include "cairo-region-private.h"
+#error This file isn't included in any Makefile
+
static cairo_int_status_t
acquire (void *abstract_dst)
{
@@ -398,6 +400,7 @@ _cairo_image_mask_compositor_get (void)
compositor.draw_image = draw_image;
compositor.fill_rectangles = fill_rectangles;
compositor.fill_boxes = fill_boxes;
+#error check_composite must never be NULL, because it gets called without a NULL pointer check
//compositor.check_composite = check_composite;
compositor.composite = composite;
//compositor.check_composite_boxes = check_composite_boxes;
diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c
index e02ebe5e0..25cdf9373 100755..100644
--- a/src/cairo-image-source.c
+++ b/src/cairo-image-source.c
@@ -56,10 +56,6 @@
#include "cairo-surface-subsurface-private.h"
#include "cairo-image-filters-private.h"
-#if CAIRO_HAS_TG_SURFACE
-#include "cairo-tg-private.h"
-#endif
-
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
#if CAIRO_NO_MUTEX
@@ -444,51 +440,6 @@ _defer_free_cleanup (pixman_image_t *pixman_image,
cairo_surface_destroy (closure);
}
-typedef struct _cairo_image_buffer
-{
- cairo_format_t format;
- unsigned char *data;
- int width;
- int height;
- int stride;
- pixman_image_t *pixman_image;
- pixman_format_code_t pixman_format;
-} cairo_image_buffer_t;
-
-static inline void
-_get_image_buffer (cairo_surface_t *surface, cairo_image_buffer_t *image_buffer)
-{
- if (surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE)
- {
- cairo_image_surface_t *image = (cairo_image_surface_t *)surface;
-
- image_buffer->format = image->format;
- image_buffer->data = image->data;
- image_buffer->width = image->width;
- image_buffer->height = image->height;
- image_buffer->stride = image->stride;
- image_buffer->pixman_image = image->pixman_image;
- image_buffer->pixman_format = image->pixman_format;
- }
-#if CAIRO_HAS_TG_SURFACE
- else if (surface->backend->type == CAIRO_SURFACE_TYPE_TG)
- {
- cairo_tg_surface_t *tg = (cairo_tg_surface_t *)surface;
-
- image_buffer->format = tg->format;
- image_buffer->data = tg->data;
- image_buffer->width = tg->width;
- image_buffer->height = tg->height;
- image_buffer->stride = tg->stride;
- image_buffer->pixman_image = ((cairo_image_surface_t *)(tg->image_surface))->pixman_image;
- image_buffer->pixman_format = ((cairo_image_surface_t *)(tg->image_surface))->pixman_format;
-
- /* flush the journal to make the memory image_buffer up-to-date. */
- cairo_surface_flush (surface);
- }
-#endif
-}
-
static uint16_t
expand_channel (uint16_t v, uint32_t bits)
{
@@ -502,25 +453,25 @@ expand_channel (uint16_t v, uint32_t bits)
}
static pixman_image_t *
-_pixel_to_solid (const cairo_image_buffer_t *image_buffer, int x, int y)
+_pixel_to_solid (cairo_image_surface_t *image, int x, int y)
{
uint32_t pixel;
pixman_color_t color;
TRACE ((stderr, "%s\n", __FUNCTION__));
- switch (image_buffer->format) {
+ switch (image->format) {
default:
case CAIRO_FORMAT_INVALID:
ASSERT_NOT_REACHED;
return NULL;
case CAIRO_FORMAT_A1:
- pixel = *(uint8_t *) (image_buffer->data + y * image_buffer->stride + x/8);
+ pixel = *(uint8_t *) (image->data + y * image->stride + x/8);
return pixel & (1 << (x&7)) ? _pixman_black_image () : _pixman_transparent_image ();
case CAIRO_FORMAT_A8:
- color.alpha = *(uint8_t *) (image_buffer->data + y * image_buffer->stride + x);
+ color.alpha = *(uint8_t *) (image->data + y * image->stride + x);
color.alpha |= color.alpha << 8;
if (color.alpha == 0)
return _pixman_transparent_image ();
@@ -531,7 +482,7 @@ _pixel_to_solid (const cairo_image_buffer_t *image_buffer, int x, int y)
return pixman_image_create_solid_fill (&color);
case CAIRO_FORMAT_RGB16_565:
- pixel = *(uint16_t *) (image_buffer->data + y * image_buffer->stride + 2 * x);
+ pixel = *(uint16_t *) (image->data + y * image->stride + 2 * x);
if (pixel == 0)
return _pixman_black_image ();
if (pixel == 0xffff)
@@ -544,7 +495,7 @@ _pixel_to_solid (const cairo_image_buffer_t *image_buffer, int x, int y)
return pixman_image_create_solid_fill (&color);
case CAIRO_FORMAT_RGB30:
- pixel = *(uint32_t *) (image_buffer->data + y * image_buffer->stride + 4 * x);
+ pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
pixel &= 0x3fffffff; /* ignore alpha bits */
if (pixel == 0)
return _pixman_black_image ();
@@ -560,8 +511,8 @@ _pixel_to_solid (const cairo_image_buffer_t *image_buffer, int x, int y)
case CAIRO_FORMAT_ARGB32:
case CAIRO_FORMAT_RGB24:
- pixel = *(uint32_t *) (image_buffer->data + y * image_buffer->stride + 4 * x);
- color.alpha = image_buffer->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
+ pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
+ color.alpha = image->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
if (color.alpha == 0)
return _pixman_transparent_image ();
if (pixel == 0xffffffff)
@@ -576,6 +527,368 @@ _pixel_to_solid (const cairo_image_buffer_t *image_buffer, int x, int y)
}
}
+/* ========================================================================== */
+
+/* Index into filter table */
+typedef enum
+{
+ KERNEL_IMPULSE,
+ KERNEL_BOX,
+ KERNEL_LINEAR,
+ KERNEL_MITCHELL,
+ KERNEL_NOTCH,
+ KERNEL_CATMULL_ROM,
+ KERNEL_LANCZOS3,
+ KERNEL_LANCZOS3_STRETCHED,
+ KERNEL_TENT
+} kernel_t;
+
+/* Produce contribution of a filter of size r for pixel centered on x.
+ For a typical low-pass function this evaluates the function at x/r.
+ If the frequency is higher than 1/2, such as when r is less than 1,
+ this may need to integrate several samples, see cubic for examples.
+*/
+typedef double (* kernel_func_t) (double x, double r);
+
+/* Return maximum number of pixels that will be non-zero. Except for
+ impluse this is the maximum of 2 and the width of the non-zero part
+ of the filter rounded up to the next integer.
+*/
+typedef int (* kernel_width_func_t) (double r);
+
+/* Table of filters */
+typedef struct
+{
+ kernel_t kernel;
+ kernel_func_t func;
+ kernel_width_func_t width;
+} filter_info_t;
+
+/* PIXMAN_KERNEL_IMPULSE: Returns pixel nearest the center. This
+ matches PIXMAN_FILTER_NEAREST. This is useful if you wish to
+ combine the result of nearest in one direction with another filter
+ in the other.
+*/
+
+static double
+impulse_kernel (double x, double r)
+{
+ return 1;
+}
+
+static int
+impulse_width (double r)
+{
+ return 1;
+}
+
+/* PIXMAN_KERNEL_BOX: Intersection of a box of width r with square
+ pixels. This is the smallest possible filter such that the output
+ image contains an equal contribution from all the input
+ pixels. Lots of software uses this. The function is a trapazoid of
+ width r+1, not a box.
+
+ When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
+ PIXMAN_KERNEL_TENT all produce the same filter, allowing
+ them to be exchanged at this point.
+*/
+
+static double
+box_kernel (double x, double r)
+{
+ return MAX (0.0, MIN (MIN (r, 1.0),
+ MIN ((r + 1) / 2 - x, (r + 1) / 2 + x)));
+}
+
+static int
+box_width (double r)
+{
+ return r < 1.0 ? 2 : ceil(r + 1);
+}
+
+/* PIXMAN_KERNEL_LINEAR: Weighted sum of the two pixels nearest the
+ center, or a triangle of width 2. This matches
+ PIXMAN_FILTER_BILINEAR. This is useful if you wish to combine the
+ result of bilinear in one direction with another filter in the
+ other. This is not a good filter if r > 1. You may actually want
+ PIXMAN_FILTER_TENT.
+
+ When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
+ PIXMAN_KERNEL_TENT all produce the same filter, allowing
+ them to be exchanged at this point.
+*/
+
+static double
+linear_kernel (double x, double r)
+{
+ return MAX (1.0 - fabs(x), 0.0);
+}
+
+static int
+linear_width (double r)
+{
+ return 2;
+}
+
+/* Cubic functions described in the Mitchell-Netravali paper.
+ http://mentallandscape.com/Papers_siggraph88.pdf. This describes
+ all possible cubic functions that can be used for sampling.
+*/
+
+static double
+general_cubic (double x, double r, double B, double C)
+{
+ double ax;
+ if (r < 1.0)
+ return
+ general_cubic(x * 2 - .5, r * 2, B, C) +
+ general_cubic(x * 2 + .5, r * 2, B, C);
+
+ ax = fabs (x / r);
+
+ if (ax < 1)
+ {
+ return (((12 - 9 * B - 6 * C) * ax +
+ (-18 + 12 * B + 6 * C)) * ax * ax +
+ (6 - 2 * B)) / 6;
+ }
+ else if (ax < 2)
+ {
+ return ((((-B - 6 * C) * ax +
+ (6 * B + 30 * C)) * ax +
+ (-12 * B - 48 * C)) * ax +
+ (8 * B + 24 * C)) / 6;
+ }
+ else
+ {
+ return 0.0;
+ }
+}
+
+static int
+cubic_width (double r)
+{
+ return MAX (2, ceil (r * 4));
+}
+
+/* PIXMAN_KERNEL_CATMULL_ROM: Catmull-Rom interpolation. Often called
+ "cubic interpolation", "b-spline", or just "cubic" by other
+ software. This filter has negative values so it can produce ringing
+ and output pixels outside the range of input pixels. This is very
+ close to lanczos2 so there is no reason to supply that as well.
+*/
+
+static double
+cubic_kernel (double x, double r)
+{
+ return general_cubic (x, r, 0.0, 0.5);
+}
+
+/* PIXMAN_KERNEL_MITCHELL: Cubic recommended by the Mitchell-Netravali
+ paper. This has negative values and because the values at +/-1 are
+ not zero it does not interpolate the pixels, meaning it will change
+ an image even if there is no translation.
+*/
+
+static double
+mitchell_kernel (double x, double r)
+{
+ return general_cubic (x, r, 1/3.0, 1/3.0);
+}
+
+/* PIXMAN_KERNEL_NOTCH: Cubic recommended by the Mitchell-Netravali
+ paper to remove postaliasing artifacts. This does not remove
+ aliasing already present in the source image, though it may appear
+ to due to it's excessive blurriness. In any case this is more
+ useful than gaussian for image reconstruction.
+*/
+
+static double
+notch_kernel (double x, double r)
+{
+ return general_cubic (x, r, 1.5, -0.25);
+}
+
+/* PIXMAN_KERNEL_LANCZOS3: lanczos windowed sinc function from -3 to
+ +3. Very popular with high-end software though I think any
+ advantage over cubics is hidden by quantization and programming
+ mistakes. You will see LANCZOS5 or even 7 sometimes.
+*/
+
+static double
+sinc (double x)
+{
+ return x ? sin (M_PI * x) / (M_PI * x) : 1.0;
+}
+
+static double
+lanczos (double x, double n)
+{
+ return fabs (x) < n ? sinc (x) * sinc (x * (1.0 / n)) : 0.0;
+}
+
+static double
+lanczos3_kernel (double x, double r)
+{
+ if (r < 1.0)
+ return
+ lanczos3_kernel (x * 2 - .5, r * 2) +
+ lanczos3_kernel (x * 2 + .5, r * 2);
+ else
+ return lanczos (x / r, 3.0);
+}
+
+static int
+lanczos3_width (double r)
+{
+ return MAX (2, ceil (r * 6));
+}
+
+/* PIXMAN_KERNEL_LANCZOS3_STRETCHED - The LANCZOS3 kernel widened by
+ 4/3. Recommended by Jim Blinn
+ http://graphics.cs.cmu.edu/nsp/course/15-462/Fall07/462/papers/jaggy.pdf
+*/
+
+static double
+nice_kernel (double x, double r)
+{
+ return lanczos3_kernel (x, r * (4.0/3));
+}
+
+static int
+nice_width (double r)
+{
+ return MAX (2.0, ceil (r * 8));
+}
+
+/* PIXMAN_KERNEL_TENT: Triangle of width 2r. Lots of software uses
+ this as a "better" filter, twice the size of a box but smaller than
+ a cubic.
+
+ When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
+ PIXMAN_KERNEL_TENT all produce the same filter, allowing
+ them to be exchanged at this point.
+*/
+
+static double
+tent_kernel (double x, double r)
+{
+ if (r < 1.0)
+ return box_kernel(x, r);
+ else
+ return MAX (1.0 - fabs(x / r), 0.0);
+}
+
+static int
+tent_width (double r)
+{
+ return r < 1.0 ? 2 : ceil(2 * r);
+}
+
+
+static const filter_info_t filters[] =
+{
+ { KERNEL_IMPULSE, impulse_kernel, impulse_width },
+ { KERNEL_BOX, box_kernel, box_width },
+ { KERNEL_LINEAR, linear_kernel, linear_width },
+ { KERNEL_MITCHELL, mitchell_kernel, cubic_width },
+ { KERNEL_NOTCH, notch_kernel, cubic_width },
+ { KERNEL_CATMULL_ROM, cubic_kernel, cubic_width },
+ { KERNEL_LANCZOS3, lanczos3_kernel, lanczos3_width },
+ { KERNEL_LANCZOS3_STRETCHED,nice_kernel, nice_width },
+ { KERNEL_TENT, tent_kernel, tent_width }
+};
+
+/* Fills in one dimension of the filter array */
+static void get_filter(kernel_t filter, double r,
+ int width, int subsample,
+ pixman_fixed_t* out)
+{
+ int i;
+ pixman_fixed_t *p = out;
+ int n_phases = 1 << subsample;
+ double step = 1.0 / n_phases;
+ kernel_func_t func = filters[filter].func;
+
+ /* special-case the impulse filter: */
+ if (width <= 1)
+ {
+ for (i = 0; i < n_phases; ++i)
+ *p++ = pixman_fixed_1;
+ return;
+ }
+
+ for (i = 0; i < n_phases; ++i)
+ {
+ double frac = (i + .5) * step;
+ /* Center of left-most pixel: */
+ double x1 = ceil (frac - width / 2.0 - 0.5) - frac + 0.5;
+ double total = 0;
+ pixman_fixed_t new_total = 0;
+ int j;
+
+ for (j = 0; j < width; ++j)
+ {
+ double v = func(x1 + j, r);
+ total += v;
+ p[j] = pixman_double_to_fixed (v);
+ }
+
+ /* Normalize */
+ total = 1 / total;
+ for (j = 0; j < width; ++j)
+ new_total += (p[j] *= total);
+
+ /* Put any error on center pixel */
+ p[width / 2] += (pixman_fixed_1 - new_total);
+
+ p += width;
+ }
+}
+
+
+/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
+ * with the given kernels and scale parameters.
+ */
+static pixman_fixed_t *
+create_separable_convolution (int *n_values,
+ kernel_t xfilter,
+ double sx,
+ kernel_t yfilter,
+ double sy)
+{
+ int xwidth, xsubsample, ywidth, ysubsample, size_x, size_y;
+ pixman_fixed_t *params;
+
+ xwidth = filters[xfilter].width(sx);
+ xsubsample = 0;
+ if (xwidth > 1)
+ while (sx * (1 << xsubsample) <= 128.0) xsubsample++;
+ size_x = (1 << xsubsample) * xwidth;
+
+ ywidth = filters[yfilter].width(sy);
+ ysubsample = 0;
+ if (ywidth > 1)
+ while (sy * (1 << ysubsample) <= 128.0) ysubsample++;
+ size_y = (1 << ysubsample) * ywidth;
+
+ *n_values = 4 + size_x + size_y;
+ params = malloc (*n_values * sizeof (pixman_fixed_t));
+ if (!params) return 0;
+
+ params[0] = pixman_int_to_fixed (xwidth);
+ params[1] = pixman_int_to_fixed (ywidth);
+ params[2] = pixman_int_to_fixed (xsubsample);
+ params[3] = pixman_int_to_fixed (ysubsample);
+
+ get_filter(xfilter, sx, xwidth, xsubsample, params + 4);
+ get_filter(yfilter, sy, ywidth, ysubsample, params + 4 + size_x);
+
+ return params;
+}
+
+/* ========================================================================== */
+
static cairo_bool_t
_pixman_image_set_properties (pixman_image_t *pixman_image,
const cairo_pattern_t *pattern,
@@ -605,16 +918,58 @@ _pixman_image_set_properties (pixman_image_t *pixman_image,
else
{
pixman_filter_t pixman_filter;
+ kernel_t kernel;
+ double dx, dy;
+
+ /* Compute scale factors from the pattern matrix. These scale
+ * factors are from user to pattern space, and as such they
+ * are greater than 1.0 for downscaling and less than 1.0 for
+ * upscaling. The factors are the size of an axis-aligned
+ * rectangle with the same area as the parallelgram a 1x1
+ * square transforms to.
+ */
+ dx = hypot (pattern->matrix.xx, pattern->matrix.xy);
+ dy = hypot (pattern->matrix.yx, pattern->matrix.yy);
+
+ /* Clip at maximum pixman_fixed number. Besides making it
+ * passable to pixman, this avoids errors from inf and nan.
+ */
+ if (! (dx < 0x7FFF)) dx = 0x7FFF;
+ if (! (dy < 0x7FFF)) dy = 0x7FFF;
switch (pattern->filter) {
case CAIRO_FILTER_FAST:
pixman_filter = PIXMAN_FILTER_FAST;
break;
case CAIRO_FILTER_GOOD:
- pixman_filter = PIXMAN_FILTER_GOOD;
+ pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
+ kernel = KERNEL_BOX;
+ /* Clip the filter size to prevent extreme slowness. This
+ value could be raised if 2-pass filtering is done */
+ if (dx > 16.0) dx = 16.0;
+ if (dy > 16.0) dy = 16.0;
+ /* Match the bilinear filter for scales > .75: */
+ if (dx < 1.0/0.75) dx = 1.0;
+ if (dy < 1.0/0.75) dy = 1.0;
break;
case CAIRO_FILTER_BEST:
- pixman_filter = PIXMAN_FILTER_BEST;
+ pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
+ kernel = KERNEL_CATMULL_ROM; /* LANCZOS3 is better but not much */
+ /* Clip the filter size to prevent extreme slowness. This
+ value could be raised if 2-pass filtering is done */
+ if (dx > 16.0) { dx = 16.0; kernel = KERNEL_BOX; }
+ /* blur up to 2x scale, then blend to square pixels for larger: */
+ else if (dx < 1.0) {
+ if (dx < 1.0/128) dx = 1.0/127;
+ else if (dx < 0.5) dx = 1.0 / (1.0 / dx - 1.0);
+ else dx = 1.0;
+ }
+ if (dy > 16.0) { dy = 16.0; kernel = KERNEL_BOX; }
+ else if (dy < 1.0) {
+ if (dy < 1.0/128) dy = 1.0/127;
+ else if (dy < 0.5) dy = 1.0 / (1.0 / dy - 1.0);
+ else dy = 1.0;
+ }
break;
case CAIRO_FILTER_NEAREST:
pixman_filter = PIXMAN_FILTER_NEAREST;
@@ -632,7 +987,17 @@ _pixman_image_set_properties (pixman_image_t *pixman_image,
pixman_filter = PIXMAN_FILTER_BEST;
}
- pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
+ if (pixman_filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION) {
+ int n_params;
+ pixman_fixed_t *params;
+ params = create_separable_convolution
+ (&n_params, kernel, dx, kernel, dy);
+ pixman_image_set_filter (pixman_image, pixman_filter,
+ params, n_params);
+ free (params);
+ } else {
+ pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
+ }
}
{
@@ -835,7 +1200,7 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
done:
/* filter with gaussian */
blurred_surface = _cairo_image_gaussian_filter (clone, &pattern->base);
-
+
pixman_image = pixman_image_ref (((cairo_image_surface_t *)blurred_surface)->pixman_image);
cairo_surface_destroy (blurred_surface);
cairo_surface_destroy (clone);
@@ -854,16 +1219,6 @@ done:
return pixman_image;
}
-static inline cairo_bool_t
-_surface_type_is_image_buffer (cairo_surface_type_t type)
-{
-#if CAIRO_HAS_TG_SURFACE
- return type == CAIRO_SURFACE_TYPE_IMAGE || type == CAIRO_SURFACE_TYPE_TG;
-#else
- return type == CAIRO_SURFACE_TYPE_IMAGE;
-#endif
-}
-
static pixman_image_t *
_pixman_image_for_surface (cairo_image_surface_t *dst,
const cairo_surface_pattern_t *pattern,
@@ -886,27 +1241,26 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
is_mask, extents, sample,
ix, iy);
- if (_surface_type_is_image_buffer (pattern->surface->type) &&
+ if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
(! is_mask || ! pattern->base.has_component_alpha ||
(pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
{
cairo_surface_t *defer_free = NULL;
cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
- cairo_image_buffer_t image_buffer;
+ cairo_surface_type_t type;
if (_cairo_surface_is_snapshot (&source->base)) {
defer_free = _cairo_surface_snapshot_get_target (&source->base);
source = (cairo_image_surface_t *) defer_free;
}
- if (_surface_type_is_image_buffer (source->base.backend->type)) {
- _get_image_buffer (source, &image_buffer);
-
+ type = source->base.backend->type;
+ if (type == CAIRO_SURFACE_TYPE_IMAGE) {
if (extend != CAIRO_EXTEND_NONE &&
sample->x >= 0 &&
sample->y >= 0 &&
- sample->x + sample->width <= image_buffer.width &&
- sample->y + sample->height <= image_buffer.height)
+ sample->x + sample->width <= source->width &&
+ sample->y + sample->height <= source->height)
{
extend = CAIRO_EXTEND_NONE;
}
@@ -914,8 +1268,8 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
if (sample->width == 1 && sample->height == 1) {
if (sample->x < 0 ||
sample->y < 0 ||
- sample->x >= image_buffer.width ||
- sample->y >= image_buffer.height)
+ sample->x >= source->width ||
+ sample->y >= source->height)
{
if (extend == CAIRO_EXTEND_NONE) {
cairo_surface_destroy (defer_free);
@@ -924,7 +1278,8 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
}
else
{
- pixman_image = _pixel_to_solid (&image_buffer, sample->x, sample->y);
+ pixman_image = _pixel_to_solid (source,
+ sample->x, sample->y);
if (pixman_image) {
cairo_surface_destroy (defer_free);
return pixman_image;
@@ -948,16 +1303,16 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
return blurred_pixman_image;
}
else
- return pixman_image_ref (image_buffer.pixman_image);
+ return pixman_image_ref (source->pixman_image);
}
#endif
if (pattern->base.filter != CAIRO_FILTER_GAUSSIAN) {
- pixman_image = pixman_image_create_bits (image_buffer.pixman_format,
- image_buffer.width,
- image_buffer.height,
- (uint32_t *) image_buffer.data,
- image_buffer.stride);
+ pixman_image = pixman_image_create_bits (source->pixman_format,
+ source->width,
+ source->height,
+ (uint32_t *) source->data,
+ source->stride);
if (unlikely (pixman_image == NULL)) {
cairo_surface_destroy (defer_free);
if (blurred_surface)
@@ -975,14 +1330,12 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
}
else
blurred_surface = _cairo_image_gaussian_filter (&source->base, &pattern->base);
- } else if (source->base.backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
+ } else if (type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
cairo_surface_subsurface_t *sub;
cairo_bool_t is_contained = FALSE;
sub = (cairo_surface_subsurface_t *) source;
- source = sub->target;
-
- _get_image_buffer (source, &image_buffer);
+ source = (cairo_image_surface_t *) sub->target;
if (sample->x >= 0 &&
sample->y >= 0 &&
@@ -994,7 +1347,7 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
if (sample->width == 1 && sample->height == 1) {
if (is_contained) {
- pixman_image = _pixel_to_solid (&image_buffer,
+ pixman_image = _pixel_to_solid (source,
sub->extents.x + sample->x,
sub->extents.y + sample->y);
if (pixman_image)
@@ -1025,16 +1378,16 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
/* Avoid sub-byte offsets, force a copy in that case. */
if (pattern->base.filter != CAIRO_FILTER_GAUSSIAN) {
- if (PIXMAN_FORMAT_BPP (image_buffer.pixman_format) >= 8) {
- if (is_contained) {
- void *data = image_buffer.data
- + sub->extents.x * PIXMAN_FORMAT_BPP(image_buffer.pixman_format)/8
- + sub->extents.y * image_buffer.stride;
- pixman_image = pixman_image_create_bits (image_buffer.pixman_format,
- sub->extents.width,
- sub->extents.height,
- data,
- image_buffer.stride);
+ if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
+ if (is_contained) {
+ void *data = source->data
+ + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8
+ + sub->extents.y * source->stride;
+ pixman_image = pixman_image_create_bits (source->pixman_format,
+ sub->extents.width,
+ sub->extents.height,
+ data,
+ source->stride);
if (unlikely (pixman_image == NULL)) {
if (blurred_surface)
cairo_surface_destroy (blurred_surface);
@@ -1087,7 +1440,7 @@ _pixman_image_for_surface (cairo_image_surface_t *dst,
}
else
/* filter with gaussian */
- blurred_surface = _cairo_image_gaussian_filter (&image->base, &pattern->base);
+ blurred_surface = _cairo_image_gaussian_filter (&image->base, &pattern->base);
cleanup = malloc (sizeof (*cleanup));
if (unlikely (cleanup == NULL)) {
diff --git a/src/cairo-image-surface-inline.h b/src/cairo-image-surface-inline.h
index 743d5fd3e..743d5fd3e 100755..100644
--- a/src/cairo-image-surface-inline.h
+++ b/src/cairo-image-surface-inline.h
diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h
index 8ca694c5e..8ca694c5e 100755..100644
--- a/src/cairo-image-surface-private.h
+++ b/src/cairo-image-surface-private.h
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index b68f4a9e7..1948a1add 100755..100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -48,6 +48,7 @@
#include "cairo-image-surface-inline.h"
#include "cairo-paginated-private.h"
#include "cairo-pattern-private.h"
+#include "cairo-pixman-private.h"
#include "cairo-recording-surface-private.h"
#include "cairo-region-private.h"
#include "cairo-scaled-font-private.h"
@@ -123,7 +124,7 @@ _cairo_image_shadow_caches_destroy (void)
cairo_surface_destroy (shadow->surface);
free (shadow);
}
- shadow_caches_size = 0;
+ shadow_caches_size = 0;
}
}
@@ -222,7 +223,12 @@ _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
return CAIRO_FORMAT_A1;
case PIXMAN_r5g6b5:
return CAIRO_FORMAT_RGB16_565;
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
case PIXMAN_r8g8b8a8: case PIXMAN_r8g8b8x8:
+#endif
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,27,2)
+ case PIXMAN_a8r8g8b8_sRGB:
+#endif
case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8:
case PIXMAN_b8g8r8: case PIXMAN_b5g6r5:
case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
@@ -239,7 +245,9 @@ _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
case PIXMAN_a2b10g10r10:
case PIXMAN_x2b10g10r10:
case PIXMAN_a2r10g10b10:
+#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
case PIXMAN_x14r6g6b6:
+#endif
default:
return CAIRO_FORMAT_INVALID;
}
@@ -535,7 +543,7 @@ _cairo_image_surface_create_with_content (cairo_content_t content,
* <informalexample><programlisting>
* int stride;
* unsigned char *data;
- * #cairo_surface_t *surface;
+ * cairo_surface_t *surface;
*
* stride = cairo_format_stride_for_width (format, width);
* data = malloc (stride * height);
@@ -883,12 +891,12 @@ _cairo_image_surface_snapshot (void *abstract_surface)
return &clone->base;
image->pixman_image = NULL;
+ image->owns_data = FALSE;
clone->transparency = image->transparency;
clone->color = image->color;
- clone->owns_data = image->owns_data;
- image->owns_data = FALSE;
+ clone->owns_data = TRUE;
return &clone->base;
}
@@ -964,8 +972,9 @@ _cairo_image_surface_finish (void *abstract_surface)
}
if (surface->parent) {
- cairo_surface_destroy (surface->parent);
+ cairo_surface_t *parent = surface->parent;
surface->parent = NULL;
+ cairo_surface_destroy (parent);
}
_cairo_image_shadow_caches_destroy ();
@@ -1034,7 +1043,7 @@ _cairo_image_surface_paint (void *abstract_surface,
const cairo_clip_t *clip)
{
cairo_image_surface_t *surface = abstract_surface;
- cairo_int_status_t status;
+ cairo_int_status_t status;
TRACE ((stderr, "%s (surface=%d)\n",
__FUNCTION__, surface->base.unique_id));
@@ -1322,7 +1331,7 @@ _cairo_image_surface_shadow_surface (void *surface,
else
shadow_width = width;
}
-
+
if (height < MIN_IMAGE_SHADOW_SIZE)
shadow_height = height;
else if (has_blur) {
diff --git a/src/cairo-line-inline.h b/src/cairo-line-inline.h
new file mode 100644
index 000000000..71cc5e7eb
--- /dev/null
+++ b/src/cairo-line-inline.h
@@ -0,0 +1,48 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2014 Intel Corporation
+ *
+ * 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.
+ *
+ */
+
+#ifndef CAIRO_LINE_INLINE_H
+#define CAIRO_LINE_INLINE_H
+
+#include "cairo-types-private.h"
+#include "cairo-compiler-private.h"
+#include "cairo-fixed-private.h"
+#include "cairo-line-private.h"
+
+static inline int
+cairo_lines_equal (const cairo_line_t *a, const cairo_line_t *b)
+{
+ return (a->p1.x == b->p1.x && a->p1.y == b->p1.y &&
+ a->p2.x == b->p2.x && a->p2.y == b->p2.y);
+}
+
+#endif /* CAIRO_LINE_INLINE_H */
diff --git a/src/cairo-tg.h b/src/cairo-line-private.h
index 97be60153..08bf4b358 100755..100644
--- a/src/cairo-tg.h
+++ b/src/cairo-line-private.h
@@ -1,5 +1,6 @@
-/*
- * Copyright © 2012 SCore Corporation
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2014 Intel Corporation, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -24,47 +25,27 @@
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
- * Author: Taekyun Kim (podain77@gmail.com)
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
*/
-#ifndef CAIRO_TG_H
-#define CAIRO_TG_H
+#ifndef CAIRO_LINE_PRIVATE_H
+#define CAIRO_LINE_PRIVATE_H
-#include "cairo.h"
-
-#if CAIRO_HAS_TG_SURFACE
+#include "cairo-types-private.h"
+#include "cairo-error-private.h"
+#include "cairo-compiler-private.h"
CAIRO_BEGIN_DECLS
-cairo_public cairo_surface_t *
-cairo_tg_surface_create (cairo_format_t format,
- int width,
- int height);
-
-cairo_public cairo_surface_t *
-cairo_tg_surface_create_for_data (unsigned char *data,
- cairo_format_t format,
- int width,
- int height,
- int stride);
-
-cairo_public unsigned char *
-cairo_tg_surface_get_data (cairo_surface_t *surface);
-
-cairo_public cairo_format_t
-cairo_tg_surface_get_format (cairo_surface_t *surface);
-
-cairo_public int
-cairo_tg_surface_get_width (cairo_surface_t *surface);
-
-cairo_public int
-cairo_tg_surface_get_height (cairo_surface_t *surface);
-
-cairo_public int
-cairo_tg_surface_get_stride (cairo_surface_t *surface);
+cairo_private int
+cairo_lines_compare_at_y(const cairo_line_t *a,
+ const cairo_line_t *b,
+ int y);
CAIRO_END_DECLS
-#endif /* CAIRO_HAS_TG_SURFACE */
-
-#endif /* CAIRO_TG_H */
+#endif /* CAIRO_LINE_PRIVATE_H */
diff --git a/src/cairo-line.c b/src/cairo-line.c
new file mode 100644
index 000000000..cb13927bd
--- /dev/null
+++ b/src/cairo-line.c
@@ -0,0 +1,306 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/*
+ * Copyright © 2004 Carl Worth
+ * Copyright © 2006 Red Hat, Inc.
+ * Copyright © 2008 Chris Wilson
+ * Copyright © 2014 Intel Corporation
+ *
+ * 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 Keith Packard
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@cworth.org>
+ * Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ */
+
+#include "cairoint.h"
+
+#include "cairo-line-inline.h"
+#include "cairo-slope-private.h"
+
+static int
+line_compare_for_y_against_x (const cairo_line_t *a,
+ int32_t y,
+ int32_t x)
+{
+ int32_t adx, ady;
+ int32_t dx, dy;
+ cairo_int64_t L, R;
+
+ if (x < a->p1.x && x < a->p2.x)
+ return 1;
+ if (x > a->p1.x && x > a->p2.x)
+ return -1;
+
+ adx = a->p2.x - a->p1.x;
+ dx = x - a->p1.x;
+
+ if (adx == 0)
+ return -dx;
+ if (dx == 0 || (adx ^ dx) < 0)
+ return adx;
+
+ dy = y - a->p1.y;
+ ady = a->p2.y - a->p1.y;
+
+ L = _cairo_int32x32_64_mul (dy, adx);
+ R = _cairo_int32x32_64_mul (dx, ady);
+
+ return _cairo_int64_cmp (L, R);
+}
+
+/*
+ * We need to compare the x-coordinates of a pair of lines for a particular y,
+ * without loss of precision.
+ *
+ * The x-coordinate along an edge for a given y is:
+ * X = A_x + (Y - A_y) * A_dx / A_dy
+ *
+ * So the inequality we wish to test is:
+ * A_x + (Y - A_y) * A_dx / A_dy ∘ B_x + (Y - B_y) * B_dx / B_dy,
+ * where ∘ is our inequality operator.
+ *
+ * By construction, we know that A_dy and B_dy (and (Y - A_y), (Y - B_y)) are
+ * all positive, so we can rearrange it thus without causing a sign change:
+ * A_dy * B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx * A_dy
+ * - (Y - A_y) * A_dx * B_dy
+ *
+ * Given the assumption that all the deltas fit within 32 bits, we can compute
+ * this comparison directly using 128 bit arithmetic. For certain, but common,
+ * input we can reduce this down to a single 32 bit compare by inspecting the
+ * deltas.
+ *
+ * (And put the burden of the work on developing fast 128 bit ops, which are
+ * required throughout the tessellator.)
+ *
+ * See the similar discussion for _slope_compare().
+ */
+static int
+lines_compare_x_for_y_general (const cairo_line_t *a,
+ const cairo_line_t *b,
+ int32_t y)
+{
+ /* XXX: We're assuming here that dx and dy will still fit in 32
+ * bits. That's not true in general as there could be overflow. We
+ * should prevent that before the tessellation algorithm
+ * begins.
+ */
+ int32_t dx;
+ int32_t adx, ady;
+ int32_t bdx, bdy;
+ enum {
+ HAVE_NONE = 0x0,
+ HAVE_DX = 0x1,
+ HAVE_ADX = 0x2,
+ HAVE_DX_ADX = HAVE_DX | HAVE_ADX,
+ HAVE_BDX = 0x4,
+ HAVE_DX_BDX = HAVE_DX | HAVE_BDX,
+ HAVE_ADX_BDX = HAVE_ADX | HAVE_BDX,
+ HAVE_ALL = HAVE_DX | HAVE_ADX | HAVE_BDX
+ } have_dx_adx_bdx = HAVE_ALL;
+
+ ady = a->p2.y - a->p1.y;
+ adx = a->p2.x - a->p1.x;
+ if (adx == 0)
+ have_dx_adx_bdx &= ~HAVE_ADX;
+
+ bdy = b->p2.y - b->p1.y;
+ bdx = b->p2.x - b->p1.x;
+ if (bdx == 0)
+ have_dx_adx_bdx &= ~HAVE_BDX;
+
+ dx = a->p1.x - b->p1.x;
+ if (dx == 0)
+ have_dx_adx_bdx &= ~HAVE_DX;
+
+#define L _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (ady, bdy), dx)
+#define A _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (adx, bdy), y - a->p1.y)
+#define B _cairo_int64x32_128_mul (_cairo_int32x32_64_mul (bdx, ady), y - b->p1.y)
+ switch (have_dx_adx_bdx) {
+ default:
+ case HAVE_NONE:
+ return 0;
+ case HAVE_DX:
+ /* A_dy * B_dy * (A_x - B_x) ∘ 0 */
+ return dx; /* ady * bdy is positive definite */
+ case HAVE_ADX:
+ /* 0 ∘ - (Y - A_y) * A_dx * B_dy */
+ return adx; /* bdy * (y - a->top.y) is positive definite */
+ case HAVE_BDX:
+ /* 0 ∘ (Y - B_y) * B_dx * A_dy */
+ return -bdx; /* ady * (y - b->top.y) is positive definite */
+ case HAVE_ADX_BDX:
+ /* 0 ∘ (Y - B_y) * B_dx * A_dy - (Y - A_y) * A_dx * B_dy */
+ if ((adx ^ bdx) < 0) {
+ return adx;
+ } else if (a->p1.y == b->p1.y) { /* common origin */
+ cairo_int64_t adx_bdy, bdx_ady;
+
+ /* ∴ A_dx * B_dy ∘ B_dx * A_dy */
+
+ adx_bdy = _cairo_int32x32_64_mul (adx, bdy);
+ bdx_ady = _cairo_int32x32_64_mul (bdx, ady);
+
+ return _cairo_int64_cmp (adx_bdy, bdx_ady);
+ } else
+ return _cairo_int128_cmp (A, B);
+ case HAVE_DX_ADX:
+ /* A_dy * (A_x - B_x) ∘ - (Y - A_y) * A_dx */
+ if ((-adx ^ dx) < 0) {
+ return dx;
+ } else {
+ cairo_int64_t ady_dx, dy_adx;
+
+ ady_dx = _cairo_int32x32_64_mul (ady, dx);
+ dy_adx = _cairo_int32x32_64_mul (a->p1.y - y, adx);
+
+ return _cairo_int64_cmp (ady_dx, dy_adx);
+ }
+ case HAVE_DX_BDX:
+ /* B_dy * (A_x - B_x) ∘ (Y - B_y) * B_dx */
+ if ((bdx ^ dx) < 0) {
+ return dx;
+ } else {
+ cairo_int64_t bdy_dx, dy_bdx;
+
+ bdy_dx = _cairo_int32x32_64_mul (bdy, dx);
+ dy_bdx = _cairo_int32x32_64_mul (y - b->p1.y, bdx);
+
+ return _cairo_int64_cmp (bdy_dx, dy_bdx);
+ }
+ case HAVE_ALL:
+ /* XXX try comparing (a->p2.x - b->p2.x) et al */
+ return _cairo_int128_cmp (L, _cairo_int128_sub (B, A));
+ }
+#undef B
+#undef A
+#undef L
+}
+
+static int
+lines_compare_x_for_y (const cairo_line_t *a,
+ const cairo_line_t *b,
+ int32_t y)
+{
+ /* If the sweep-line is currently on an end-point of a line,
+ * then we know its precise x value (and considering that we often need to
+ * compare events at end-points, this happens frequently enough to warrant
+ * special casing).
+ */
+ enum {
+ HAVE_NEITHER = 0x0,
+ HAVE_AX = 0x1,
+ HAVE_BX = 0x2,
+ HAVE_BOTH = HAVE_AX | HAVE_BX
+ } have_ax_bx = HAVE_BOTH;
+ int32_t ax, bx;
+
+ if (y == a->p1.y)
+ ax = a->p1.x;
+ else if (y == a->p2.y)
+ ax = a->p2.x;
+ else
+ have_ax_bx &= ~HAVE_AX;
+
+ if (y == b->p1.y)
+ bx = b->p1.x;
+ else if (y == b->p2.y)
+ bx = b->p2.x;
+ else
+ have_ax_bx &= ~HAVE_BX;
+
+ switch (have_ax_bx) {
+ default:
+ case HAVE_NEITHER:
+ return lines_compare_x_for_y_general (a, b, y);
+ case HAVE_AX:
+ return -line_compare_for_y_against_x (b, y, ax);
+ case HAVE_BX:
+ return line_compare_for_y_against_x (a, y, bx);
+ case HAVE_BOTH:
+ return ax - bx;
+ }
+}
+
+static int bbox_compare (const cairo_line_t *a,
+ const cairo_line_t *b)
+{
+ int32_t amin, amax;
+ int32_t bmin, bmax;
+
+ if (a->p1.x < a->p2.x) {
+ amin = a->p1.x;
+ amax = a->p2.x;
+ } else {
+ amin = a->p2.x;
+ amax = a->p1.x;
+ }
+
+ if (b->p1.x < b->p2.x) {
+ bmin = b->p1.x;
+ bmax = b->p2.x;
+ } else {
+ bmin = b->p2.x;
+ bmax = b->p1.x;
+ }
+
+ if (amax < bmin)
+ return -1;
+
+ if (amin > bmax)
+ return +1;
+
+ return 0;
+}
+
+int cairo_lines_compare_at_y (const cairo_line_t *a,
+ const cairo_line_t *b,
+ int y)
+{
+ cairo_slope_t sa, sb;
+ int ret;
+
+ if (cairo_lines_equal (a, b))
+ return 0;
+
+ /* Don't bother solving for abscissa if the edges' bounding boxes
+ * can be used to order them.
+ */
+ ret = bbox_compare (a, b);
+ if (ret)
+ return ret;
+
+ ret = lines_compare_x_for_y (a, b, y);
+ if (ret)
+ return ret;
+
+ _cairo_slope_init (&sa, &a->p1, &a->p2);
+ _cairo_slope_init (&sb, &b->p1, &b->p2);
+
+ return _cairo_slope_compare (&sb, &sa);
+}
diff --git a/src/cairo-list-inline.h b/src/cairo-list-inline.h
index d00f40e98..0955178d2 100755..100644
--- a/src/cairo-list-inline.h
+++ b/src/cairo-list-inline.h
@@ -145,9 +145,15 @@ __cairo_list_del (cairo_list_t *prev, cairo_list_t *next)
}
static inline void
-cairo_list_del (cairo_list_t *entry)
+_cairo_list_del (cairo_list_t *entry)
{
__cairo_list_del (entry->prev, entry->next);
+}
+
+static inline void
+cairo_list_del (cairo_list_t *entry)
+{
+ _cairo_list_del (entry);
cairo_list_init (entry);
}
diff --git a/src/cairo-list-private.h b/src/cairo-list-private.h
index 9f39b668f..9f39b668f 100755..100644
--- a/src/cairo-list-private.h
+++ b/src/cairo-list-private.h
diff --git a/src/cairo-lzw.c b/src/cairo-lzw.c
index de7f99983..de7f99983 100755..100644
--- a/src/cairo-lzw.c
+++ b/src/cairo-lzw.c
diff --git a/src/cairo-malloc-private.h b/src/cairo-malloc-private.h
index 1e2c67f8d..1e2c67f8d 100755..100644
--- a/src/cairo-malloc-private.h
+++ b/src/cairo-malloc-private.h
diff --git a/src/cairo-mask-compositor.c b/src/cairo-mask-compositor.c
index 31d116119..80bf0f5e6 100755..100644
--- a/src/cairo-mask-compositor.c
+++ b/src/cairo-mask-compositor.c
@@ -163,9 +163,10 @@ create_composite_mask (const cairo_mask_compositor_t *compositor,
struct blt_in info;
int i;
- surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_ALPHA,
- extents->bounded.width,
- extents->bounded.height);
+ surface = _cairo_surface_create_scratch (dst, CAIRO_CONTENT_ALPHA,
+ extents->bounded.width,
+ extents->bounded.height,
+ NULL);
if (unlikely (surface->status))
return surface;
@@ -346,9 +347,10 @@ clip_and_composite_combine (const cairo_mask_compositor_t *compositor,
cairo_status_t status;
int clip_x, clip_y;
- tmp = _cairo_surface_create_similar_scratch (dst, dst->content,
- extents->bounded.width,
- extents->bounded.height);
+ tmp = _cairo_surface_create_scratch (dst, dst->content,
+ extents->bounded.width,
+ extents->bounded.height,
+ NULL);
if (unlikely (tmp->status)) {
status = tmp->status;
goto cleanup;
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index ba975beae..ae498f515 100755..100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -748,23 +748,32 @@ _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
return FALSE;
}
+#define SCALING_EPSILON _cairo_fixed_to_double(1)
+
+/* This only returns true if the matrix is 90 degree rotations or
+ * flips. It appears calling code is relying on this. It will return
+ * false for other rotations even if the scale is one. Approximations
+ * are allowed to handle matricies filled in using trig functions
+ * such as sin(M_PI_2).
+ */
cairo_bool_t
_cairo_matrix_has_unity_scale (const cairo_matrix_t *matrix)
{
- if (matrix->xy == 0.0 && matrix->yx == 0.0) {
- if (! (matrix->xx == 1.0 || matrix->xx == -1.0))
- return FALSE;
- if (! (matrix->yy == 1.0 || matrix->yy == -1.0))
- return FALSE;
- } else if (matrix->xx == 0.0 && matrix->yy == 0.0) {
- if (! (matrix->xy == 1.0 || matrix->xy == -1.0))
- return FALSE;
- if (! (matrix->yx == 1.0 || matrix->yx == -1.0))
- return FALSE;
- } else
- return FALSE;
-
- return TRUE;
+ /* check that the determinant is near +/-1 */
+ double det = _cairo_matrix_compute_determinant (matrix);
+ if (fabs (det * det - 1.0) < SCALING_EPSILON) {
+ /* check that one axis is close to zero */
+ if (fabs (matrix->xy) < SCALING_EPSILON &&
+ fabs (matrix->yx) < SCALING_EPSILON)
+ return TRUE;
+ if (fabs (matrix->xx) < SCALING_EPSILON &&
+ fabs (matrix->yy) < SCALING_EPSILON)
+ return TRUE;
+ /* If rotations are allowed then it must instead test for
+ * orthogonality. This is xx*xy+yx*yy ~= 0.
+ */
+ }
+ return FALSE;
}
/* By pixel exact here, we mean a matrix that is composed only of
diff --git a/src/cairo-mempool-private.h b/src/cairo-mempool-private.h
index a09f6ce51..a09f6ce51 100755..100644
--- a/src/cairo-mempool-private.h
+++ b/src/cairo-mempool-private.h
diff --git a/src/cairo-mempool.c b/src/cairo-mempool.c
index 96e4a62b2..751ede320 100755..100644
--- a/src/cairo-mempool.c
+++ b/src/cairo-mempool.c
@@ -157,7 +157,8 @@ get_buddy (cairo_mempool_t *pool, size_t offset, int bits)
{
struct _cairo_memblock *block;
- assert (offset + (1 << bits) <= pool->num_blocks);
+ if (offset + (1 << bits) >= pool->num_blocks)
+ return NULL; /* invalid */
if (BITTEST (pool, offset + (1 << bits) - 1))
return NULL; /* buddy is allocated */
diff --git a/src/cairo-mesh-pattern-rasterizer.c b/src/cairo-mesh-pattern-rasterizer.c
index 5342b3d22..86cd16833 100755..100644
--- a/src/cairo-mesh-pattern-rasterizer.c
+++ b/src/cairo-mesh-pattern-rasterizer.c
@@ -697,9 +697,9 @@ rasterize_bezier_patch (unsigned char *data, int width, int height, int stride,
cairo_point_double_t p[4][4], double col[4][4])
{
double pv[4][2][4], cstart[4], cend[4], dcstart[4], dcend[4];
- int vsteps, v, i, k;
+ int v, i, k;
- vsteps = 1 << vshift;
+ v = 1 << vshift;
/*
* pv[i][0] is the function (represented using forward
@@ -724,11 +724,12 @@ rasterize_bezier_patch (unsigned char *data, int width, int height, int stride,
for (i = 0; i < 4; ++i) {
cstart[i] = col[0][i];
cend[i] = col[1][i];
- dcstart[i] = (col[2][i] - col[0][i]) / vsteps;
- dcend[i] = (col[3][i] - col[1][i]) / vsteps;
+ dcstart[i] = (col[2][i] - col[0][i]) / v;
+ dcend[i] = (col[3][i] - col[1][i]) / v;
}
- for (v = 0; v <= vsteps; ++v) {
+ v++;
+ while (v--) {
cairo_point_double_t nodes[4];
for (i = 0; i < 4; ++i) {
nodes[i].x = pv[i][0][0];
diff --git a/src/cairo-misc.c b/src/cairo-misc.c
index bb37e1a0a..df8a4efc9 100755..100644
--- a/src/cairo-misc.c
+++ b/src/cairo-misc.c
@@ -156,6 +156,8 @@ cairo_status_to_string (cairo_status_t status)
return "invalid operation during mesh pattern construction";
case CAIRO_STATUS_DEVICE_FINISHED:
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";
default:
case CAIRO_STATUS_LAST_STATUS:
return "<unknown error status>";
@@ -757,6 +759,24 @@ _cairo_half_from_float (float f)
}
}
+#ifndef __BIONIC__
+# include <locale.h>
+
+const char *
+cairo_get_locale_decimal_point (void)
+{
+ struct lconv *locale_data = localeconv ();
+ return locale_data->decimal_point;
+}
+
+#else
+/* Android's Bionic libc doesn't provide decimal_point */
+const char *
+cairo_get_locale_decimal_point (void)
+{
+ return '.';
+}
+#endif
#ifdef _WIN32
diff --git a/src/cairo-mono-scan-converter.c b/src/cairo-mono-scan-converter.c
index 2a9546cf8..2a9546cf8 100755..100644
--- a/src/cairo-mono-scan-converter.c
+++ b/src/cairo-mono-scan-converter.c
diff --git a/src/cairo-mutex-impl-private.h b/src/cairo-mutex-impl-private.h
index 25223f3ea..25223f3ea 100755..100644
--- a/src/cairo-mutex-impl-private.h
+++ b/src/cairo-mutex-impl-private.h
diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h
index d79a059ea..f46afadb0 100755..100644
--- a/src/cairo-mutex-list-private.h
+++ b/src/cairo-mutex-list-private.h
@@ -34,7 +34,6 @@
#ifndef CAIRO_FEATURES_H
/* This block is to just make this header file standalone */
#define CAIRO_MUTEX_DECLARE(mutex)
-#define CAIRO_RECURSIVE_MUTEX_DECLARE(mutex)
#endif
CAIRO_MUTEX_DECLARE (_cairo_pattern_solid_surface_cache_lock)
@@ -48,10 +47,6 @@ CAIRO_MUTEX_DECLARE (_cairo_scaled_glyph_page_cache_mutex)
CAIRO_MUTEX_DECLARE (_cairo_scaled_font_error_mutex)
CAIRO_MUTEX_DECLARE (_cairo_glyph_cache_mutex)
-#if CAIRO_HAS_TG_SURFACE
-CAIRO_RECURSIVE_MUTEX_DECLARE(_cairo_tg_scaled_glyph_mutex)
-#endif
-
#if CAIRO_HAS_FT_FONT
CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex)
#endif
diff --git a/src/cairo-mutex-private.h b/src/cairo-mutex-private.h
index 0b806c186..61a7160a0 100755..100644
--- a/src/cairo-mutex-private.h
+++ b/src/cairo-mutex-private.h
@@ -59,10 +59,8 @@ cairo_private void _cairo_mutex_finalize (void);
/* Finally, extern the static mutexes and undef */
#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex;
-#define CAIRO_RECURSIVE_MUTEX_DECLARE(mutex) cairo_private extern cairo_recursive_mutex_t mutex;
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE
-#undef CAIRO_RECURSIVE_MUTEX_DECLARE
CAIRO_END_DECLS
diff --git a/src/cairo-mutex-type-private.h b/src/cairo-mutex-type-private.h
index e8c493985..e8c493985 100755..100644
--- a/src/cairo-mutex-type-private.h
+++ b/src/cairo-mutex-type-private.h
diff --git a/src/cairo-mutex.c b/src/cairo-mutex.c
index 41d5c73f4..0a31dced3 100755..100644
--- a/src/cairo-mutex.c
+++ b/src/cairo-mutex.c
@@ -36,11 +36,8 @@
#include "cairo-mutex-private.h"
#define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER;
-#define CAIRO_RECURSIVE_MUTEX_DECLARE(mutex) \
- cairo_recursive_mutex_t mutex = CAIRO_RECURSIVE_MUTEX_NIL_INITIALIZER;
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE
-#undef CAIRO_RECURSIVE_MUTEX_DECLARE
#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
@@ -65,10 +62,8 @@ void _cairo_mutex_initialize (void)
_cairo_mutex_initialized = TRUE;
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_INIT (mutex);
-#define CAIRO_RECURSIVE_MUTEX_DECLARE(mutex) CAIRO_RECURSIVE_MUTEX_INIT (mutex);
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE
-#undef CAIRO_RECURSIVE_MUTEX_DECLARE
}
#endif
@@ -81,9 +76,7 @@ void _cairo_mutex_finalize (void)
_cairo_mutex_initialized = FALSE;
#define CAIRO_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex);
-#define CAIRO_RECURSIVE_MUTEX_DECLARE(mutex) CAIRO_MUTEX_FINI (mutex);
#include "cairo-mutex-list-private.h"
#undef CAIRO_MUTEX_DECLARE
-#undef CAIRO_RECURSIVE_MUTEX_DECLARE
}
#endif
diff --git a/src/cairo-no-compositor.c b/src/cairo-no-compositor.c
index 1602a12f6..1602a12f6 100755..100644
--- a/src/cairo-no-compositor.c
+++ b/src/cairo-no-compositor.c
diff --git a/src/cairo-observer.c b/src/cairo-observer.c
index 36d6b93bd..36d6b93bd 100755..100644
--- a/src/cairo-observer.c
+++ b/src/cairo-observer.c
diff --git a/src/cairo-os2-private.h b/src/cairo-os2-private.h
index 829dd3c8d..829dd3c8d 100755..100644
--- a/src/cairo-os2-private.h
+++ b/src/cairo-os2-private.h
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index 1ab50f977..1ab50f977 100755..100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
diff --git a/src/cairo-os2.h b/src/cairo-os2.h
index d23f2dec4..d23f2dec4 100755..100644
--- a/src/cairo-os2.h
+++ b/src/cairo-os2.h
diff --git a/src/cairo-output-stream-private.h b/src/cairo-output-stream-private.h
index edaabbe78..2542646b8 100755..100644
--- a/src/cairo-output-stream-private.h
+++ b/src/cairo-output-stream-private.h
@@ -135,6 +135,11 @@ _cairo_output_stream_printf (cairo_output_stream_t *stream,
const char *fmt,
...) CAIRO_PRINTF_FORMAT (2, 3);
+/* Print matrix element values with rounding of insignificant digits. */
+cairo_private void
+_cairo_output_stream_print_matrix (cairo_output_stream_t *stream,
+ const cairo_matrix_t *matrix);
+
cairo_private long
_cairo_output_stream_get_position (cairo_output_stream_t *stream);
diff --git a/src/cairo-output-stream.c b/src/cairo-output-stream.c
index facc182f6..c29ea0e39 100755..100644
--- a/src/cairo-output-stream.c
+++ b/src/cairo-output-stream.c
@@ -43,7 +43,6 @@
#include "cairo-compiler-private.h"
#include <stdio.h>
-#include <locale.h>
#include <errno.h>
/* Numbers printed with %f are printed with this number of significant
@@ -303,7 +302,6 @@ _cairo_output_stream_write_hex_string (cairo_output_stream_t *stream,
static void
_cairo_dtostr (char *buffer, size_t size, double d, cairo_bool_t limited_precision)
{
- struct lconv *locale_data;
const char *decimal_point;
int decimal_point_len;
char *p;
@@ -314,8 +312,7 @@ _cairo_dtostr (char *buffer, size_t size, double d, cairo_bool_t limited_precisi
if (d == 0.0)
d = 0.0;
- locale_data = localeconv ();
- decimal_point = locale_data->decimal_point;
+ decimal_point = cairo_get_locale_decimal_point ();
decimal_point_len = strlen (decimal_point);
assert (decimal_point_len != 0);
@@ -530,6 +527,45 @@ _cairo_output_stream_printf (cairo_output_stream_t *stream,
va_end (ap);
}
+/* Matrix elements that are smaller than the value of the largest element * MATRIX_ROUNDING_TOLERANCE
+ * are rounded down to zero. */
+#define MATRIX_ROUNDING_TOLERANCE 1e-12
+
+void
+_cairo_output_stream_print_matrix (cairo_output_stream_t *stream,
+ const cairo_matrix_t *matrix)
+{
+ cairo_matrix_t m;
+ double s, e;
+
+ m = *matrix;
+ s = fabs (m.xx);
+ if (fabs (m.xy) > s)
+ s = fabs (m.xy);
+ if (fabs (m.yx) > s)
+ s = fabs (m.yx);
+ if (fabs (m.yy) > s)
+ s = fabs (m.yy);
+
+ e = s * MATRIX_ROUNDING_TOLERANCE;
+ if (fabs(m.xx) < e)
+ m.xx = 0;
+ if (fabs(m.xy) < e)
+ m.xy = 0;
+ if (fabs(m.yx) < e)
+ m.yx = 0;
+ if (fabs(m.yy) < e)
+ m.yy = 0;
+ if (fabs(m.x0) < e)
+ m.x0 = 0;
+ if (fabs(m.y0) < e)
+ m.y0 = 0;
+
+ _cairo_output_stream_printf (stream,
+ "%f %f %f %f %f %f",
+ m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);
+}
+
long
_cairo_output_stream_get_position (cairo_output_stream_t *stream)
{
diff --git a/src/cairo-paginated-private.h b/src/cairo-paginated-private.h
index b827faba0..b827faba0 100755..100644
--- a/src/cairo-paginated-private.h
+++ b/src/cairo-paginated-private.h
diff --git a/src/cairo-paginated-surface-private.h b/src/cairo-paginated-surface-private.h
index ebf4b3424..ebf4b3424 100755..100644
--- a/src/cairo-paginated-surface-private.h
+++ b/src/cairo-paginated-surface-private.h
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index b4580d77b..6d6d6dd1c 100755..100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -309,7 +309,7 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
image = _cairo_paginated_surface_create_image_surface (surface,
ceil (width * x_scale),
ceil (height * y_scale));
- _cairo_surface_set_device_scale (image, x_scale, y_scale);
+ cairo_surface_set_device_scale (image, x_scale, y_scale);
/* set_device_offset just sets the x0/y0 components of the matrix;
* so we have to do the scaling manually. */
cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index 77f23c887..e8cf0e320 100755..100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -221,7 +221,7 @@ _cairo_path_fixed_approximate_stroke_exact_extents (const cairo_path_fixed_t *pa
box_extents.p1.y -= _cairo_fixed_from_double (dy);
box_extents.p2.x += _cairo_fixed_from_double (dx);
box_extents.p2.y += _cairo_fixed_from_double (dy);
-
+
_cairo_box_to_doubles (&box_extents, &x1, &y1, &x2, &y2);
extents->x = x1;
diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c
index b38c2a8d3..4000c9c58 100755..100644
--- a/src/cairo-path-fill.c
+++ b/src/cairo-path-fill.c
@@ -339,4 +339,3 @@ _cairo_path_fixed_fill_rectilinear_to_boxes (const cairo_path_fixed_t *path,
antialias,
boxes);
}
-
diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
index cf7cd0836..adc3b532b 100755..100644
--- a/src/cairo-path-fixed-private.h
+++ b/src/cairo-path-fixed-private.h
@@ -101,6 +101,7 @@ typedef struct _cairo_path_buf_fixed {
struct _cairo_path_fixed {
cairo_point_t last_move_point;
cairo_point_t current_point;
+ cairo_point_t start_point;
unsigned int has_current_point : 1;
unsigned int needs_move_to : 1;
unsigned int has_extents : 1;
@@ -113,6 +114,7 @@ struct _cairo_path_fixed {
cairo_box_t extents;
cairo_path_buf_fixed_t buf;
+ unsigned int is_convex : 1;
};
cairo_private void
diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 2c198815d..5d57a61ec 100755..100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -86,6 +86,7 @@ _cairo_path_fixed_init (cairo_path_fixed_t *path)
path->current_point.x = 0;
path->current_point.y = 0;
path->last_move_point = path->current_point;
+ path->start_point = path->current_point;
path->has_current_point = FALSE;
path->needs_move_to = TRUE;
@@ -95,6 +96,7 @@ _cairo_path_fixed_init (cairo_path_fixed_t *path)
path->fill_is_rectilinear = TRUE;
path->fill_maybe_region = TRUE;
path->fill_is_empty = TRUE;
+ path->is_convex = TRUE;
path->extents.p1.x = path->extents.p1.y = 0;
path->extents.p2.x = path->extents.p2.y = 0;
@@ -132,6 +134,9 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
path->buf.base.num_ops = other->buf.base.num_ops;
path->buf.base.num_points = other->buf.base.num_points;
+
+ path->is_convex = other->is_convex;
+
memcpy (path->buf.op, other->buf.base.op,
other->buf.base.num_ops * sizeof (other->buf.op[0]));
memcpy (path->buf.points, other->buf.points,
@@ -408,6 +413,11 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
path->current_point.y = y;
path->last_move_point = path->current_point;
+ if (_cairo_path_fixed_is_empty (path))
+ path->is_convex = TRUE;
+ else
+ path->is_convex = FALSE;
+
return CAIRO_STATUS_SUCCESS;
}
@@ -450,6 +460,11 @@ _cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path)
path->needs_move_to = TRUE;
}
+ if (_cairo_path_fixed_is_empty (path))
+ path->is_convex = TRUE;
+ else
+ path->is_convex = FALSE;
+
path->has_current_point = FALSE;
}
@@ -548,6 +563,13 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
_cairo_box_add_point (&path->extents, &point);
+ /* if line to point does not match start point, is_convex false */
+ if (path->is_convex) {
+ if (path->start_point.x != x &&
+ path->start_point.y != y)
+ path->is_convex = FALSE;
+ }
+
return _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
}
@@ -620,6 +642,8 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
path->fill_maybe_region = FALSE;
path->fill_is_empty = FALSE;
+ path->is_convex = FALSE;
+
return _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
}
@@ -847,6 +871,9 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
}
} cairo_path_foreach_buf_end (buf, path);
+ if (path->needs_move_to && path->has_current_point)
+ return (*move_to) (closure, &path->current_point);
+
return CAIRO_STATUS_SUCCESS;
}
@@ -965,8 +992,19 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
path->extents.p1.x = _cairo_fixed_mul (scalex, path->extents.p1.x) + offx;
path->extents.p2.x = _cairo_fixed_mul (scalex, path->extents.p2.x) + offx;
+ if (scalex < 0) {
+ cairo_fixed_t t = path->extents.p1.x;
+ path->extents.p1.x = path->extents.p2.x;
+ path->extents.p2.x = t;
+ }
+
path->extents.p1.y = _cairo_fixed_mul (scaley, path->extents.p1.y) + offy;
path->extents.p2.y = _cairo_fixed_mul (scaley, path->extents.p2.y) + offy;
+ if (scaley < 0) {
+ cairo_fixed_t t = path->extents.p1.y;
+ path->extents.p1.y = path->extents.p2.y;
+ path->extents.p2.y = t;
+ }
}
void
@@ -1289,7 +1327,7 @@ _cairo_path_fixed_is_box (const cairo_path_fixed_t *path,
}
/* Determine whether two lines A->B and C->D intersect based on the
- * algorithm described here: http://paulbourke.net/geometry/lineline2d/ */
+ * algorithm described here: http://paulbourke.net/geometry/pointlineplane/ */
static inline cairo_bool_t
_lines_intersect_or_are_coincident (cairo_point_t a,
cairo_point_t b,
@@ -1297,6 +1335,7 @@ _lines_intersect_or_are_coincident (cairo_point_t a,
cairo_point_t d)
{
cairo_int64_t numerator_a, numerator_b, denominator;
+ cairo_bool_t denominator_negative;
denominator = _cairo_int64_sub (_cairo_int32x32_64_mul (d.y - c.y, b.x - a.x),
_cairo_int32x32_64_mul (d.x - c.x, b.y - a.y));
@@ -1316,20 +1355,34 @@ _lines_intersect_or_are_coincident (cairo_point_t a,
return FALSE;
}
- /* If either division would produce a number between 0 and 1, i.e.
- * the numerator is smaller than the denominator and their signs are
- * the same, then the lines intersect. */
- if (_cairo_int64_lt (numerator_a, denominator) &&
- ! (_cairo_int64_negative (numerator_a) ^ _cairo_int64_negative(denominator))) {
- return TRUE;
- }
+ /* The lines intersect if both quotients are between 0 and 1 (exclusive). */
- if (_cairo_int64_lt (numerator_b, denominator) &&
- ! (_cairo_int64_negative (numerator_b) ^ _cairo_int64_negative(denominator))) {
- return TRUE;
+ /* We first test whether either quotient is a negative number. */
+ denominator_negative = _cairo_int64_negative (denominator);
+ if (_cairo_int64_negative (numerator_a) ^ denominator_negative)
+ return FALSE;
+ if (_cairo_int64_negative (numerator_b) ^ denominator_negative)
+ return FALSE;
+
+ /* A zero quotient indicates an "intersection" at an endpoint, which
+ * we aren't considering a true intersection. */
+ if (_cairo_int64_is_zero (numerator_a) || _cairo_int64_is_zero (numerator_b))
+ return FALSE;
+
+ /* If the absolute value of the numerator is larger than or equal to the
+ * denominator the result of the division would be greater than or equal
+ * to one. */
+ if (! denominator_negative) {
+ if (! _cairo_int64_lt (numerator_a, denominator) ||
+ ! _cairo_int64_lt (numerator_b, denominator))
+ return FALSE;
+ } else {
+ if (! _cairo_int64_lt (denominator, numerator_a) ||
+ ! _cairo_int64_lt (denominator, numerator_b))
+ return FALSE;
}
- return FALSE;
+ return TRUE;
}
cairo_bool_t
@@ -1454,6 +1507,19 @@ _cairo_path_fixed_is_single_line (const cairo_path_fixed_t *path)
}
cairo_bool_t
+_cairo_path_fixed_is_empty (const cairo_path_fixed_t *path)
+{
+ unsigned int i;
+ const cairo_path_buf_t *buf = cairo_path_head (path);
+ for (i = 0; i < buf->num_ops; i++) {
+ if (buf->op[i] != CAIRO_PATH_OP_MOVE_TO)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+cairo_bool_t
_cairo_path_fixed_is_single_arc (const cairo_path_fixed_t *path)
{
const cairo_path_buf_t *buf = cairo_path_head (path);
diff --git a/src/cairo-path-in-fill.c b/src/cairo-path-in-fill.c
index 1787fb1a3..1787fb1a3 100755..100644
--- a/src/cairo-path-in-fill.c
+++ b/src/cairo-path-in-fill.c
diff --git a/src/cairo-path-private.h b/src/cairo-path-private.h
index 7b54317e2..7b54317e2 100755..100644
--- a/src/cairo-path-private.h
+++ b/src/cairo-path-private.h
diff --git a/src/cairo-path-stroke-boxes.c b/src/cairo-path-stroke-boxes.c
index 7f25bf76c..7f25bf76c 100755..100644
--- a/src/cairo-path-stroke-boxes.c
+++ b/src/cairo-path-stroke-boxes.c
diff --git a/src/cairo-path-stroke-polygon.c b/src/cairo-path-stroke-polygon.c
index b62ddfb8f..83e40854e 100755..100644
--- a/src/cairo-path-stroke-polygon.c
+++ b/src/cairo-path-stroke-polygon.c
@@ -1083,7 +1083,6 @@ spline_to (void *closure,
_cairo_contour_add_point (&stroker->path, point);
#endif
if ((tangent->dx | tangent->dy) == 0) {
- const cairo_point_t *inpt, *outpt;
struct stroke_contour *outer;
cairo_point_t t;
int clockwise;
@@ -1101,12 +1100,8 @@ spline_to (void *closure,
clockwise = join_is_clockwise (&stroker->current_face, &face);
if (clockwise) {
- inpt = &stroker->current_face.cw;
- outpt = &face.cw;
outer = &stroker->cw;
} else {
- inpt = &stroker->current_face.ccw;
- outpt = &face.ccw;
outer = &stroker->ccw;
}
@@ -1121,7 +1116,6 @@ spline_to (void *closure,
if ((face.dev_slope.x * stroker->current_face.dev_slope.x +
face.dev_slope.y * stroker->current_face.dev_slope.y) < stroker->spline_cusp_tolerance)
{
- const cairo_point_t *inpt, *outpt;
struct stroke_contour *outer;
int clockwise = join_is_clockwise (&stroker->current_face, &face);
@@ -1134,12 +1128,8 @@ spline_to (void *closure,
contour_add_point (stroker, &stroker->ccw, &stroker->current_face.ccw);
if (clockwise) {
- inpt = &stroker->current_face.cw;
- outpt = &face.cw;
outer = &stroker->cw;
} else {
- inpt = &stroker->current_face.ccw;
- outpt = &face.ccw;
outer = &stroker->ccw;
}
add_fan (stroker,
diff --git a/src/cairo-path-stroke-traps.c b/src/cairo-path-stroke-traps.c
index f95321491..03638961c 100755..100644
--- a/src/cairo-path-stroke-traps.c
+++ b/src/cairo-path-stroke-traps.c
@@ -249,9 +249,11 @@ join (struct stroker *stroker,
in->dev_slope.y * out->dev_slope.y) < stroker->spline_cusp_tolerance)
{
int start, stop;
- cairo_point_t tri[3];
+ cairo_point_t tri[3], edges[4];
cairo_pen_t *pen = &stroker->pen;
+ edges[0] = in->cw;
+ edges[1] = in->ccw;
tri[0] = in->point;
tri[1] = *inpt;
if (clockwise) {
@@ -261,8 +263,13 @@ join (struct stroker *stroker,
while (start != stop) {
tri[2] = in->point;
translate_point (&tri[2], &pen->vertices[start].point);
- _cairo_traps_tessellate_triangle (stroker->traps, tri);
+ edges[2] = in->point;
+ edges[3] = tri[2];
+ _cairo_traps_tessellate_triangle_with_edges (stroker->traps,
+ tri, edges);
tri[1] = tri[2];
+ edges[0] = edges[2];
+ edges[1] = edges[3];
if (start-- == 0)
start += pen->num_vertices;
@@ -274,17 +281,30 @@ join (struct stroker *stroker,
while (start != stop) {
tri[2] = in->point;
translate_point (&tri[2], &pen->vertices[start].point);
- _cairo_traps_tessellate_triangle (stroker->traps, tri);
+ edges[2] = in->point;
+ edges[3] = tri[2];
+ _cairo_traps_tessellate_triangle_with_edges (stroker->traps,
+ tri, edges);
tri[1] = tri[2];
+ edges[0] = edges[2];
+ edges[1] = edges[3];
if (++start == pen->num_vertices)
start = 0;
}
}
tri[2] = *outpt;
- _cairo_traps_tessellate_triangle (stroker->traps, tri);
- break;
+ edges[2] = out->cw;
+ edges[3] = out->ccw;
+ _cairo_traps_tessellate_triangle_with_edges (stroker->traps,
+ tri, edges);
+ } else {
+ cairo_point_t t[] = { { in->point.x, in->point.y}, { inpt->x, inpt->y }, { outpt->x, outpt->y } };
+ cairo_point_t e[] = { { in->cw.x, in->cw.y}, { in->ccw.x, in->ccw.y },
+ { out->cw.x, out->cw.y}, { out->ccw.x, out->ccw.y } };
+ _cairo_traps_tessellate_triangle_with_edges (stroker->traps, t, e);
}
+ break;
case CAIRO_LINE_JOIN_MITER:
default: {
@@ -442,12 +462,10 @@ join (struct stroker *stroker,
}
case CAIRO_LINE_JOIN_BEVEL: {
- cairo_point_t tri[3];
- tri[0] = in->point;
- tri[1] = *inpt;
- tri[2] = *outpt;
-
- _cairo_traps_tessellate_triangle (stroker->traps, tri);
+ cairo_point_t t[] = { { in->point.x, in->point.y }, { inpt->x, inpt->y }, { outpt->x, outpt->y } };
+ cairo_point_t e[] = { { in->cw.x, in->cw.y }, { in->ccw.x, in->ccw.y },
+ { out->cw.x, out->cw.y }, { out->ccw.x, out->ccw.y } };
+ _cairo_traps_tessellate_triangle_with_edges (stroker->traps, t, e);
break;
}
}
@@ -460,7 +478,7 @@ add_cap (struct stroker *stroker, cairo_stroke_face_t *f)
case CAIRO_LINE_CAP_ROUND: {
int start, stop;
cairo_slope_t in_slope, out_slope;
- cairo_point_t tri[3];
+ cairo_point_t tri[3], edges[4];
cairo_pen_t *pen = &stroker->pen;
in_slope = f->dev_vector;
@@ -468,19 +486,29 @@ add_cap (struct stroker *stroker, cairo_stroke_face_t *f)
out_slope.dy = -in_slope.dy;
_cairo_pen_find_active_cw_vertices (pen, &in_slope, &out_slope,
&start, &stop);
+ edges[0] = f->cw;
+ edges[1] = f->ccw;
tri[0] = f->point;
tri[1] = f->cw;
while (start != stop) {
tri[2] = f->point;
translate_point (&tri[2], &pen->vertices[start].point);
- _cairo_traps_tessellate_triangle (stroker->traps, tri);
+ edges[2] = f->point;
+ edges[3] = tri[2];
+ _cairo_traps_tessellate_triangle_with_edges (stroker->traps,
+ tri, edges);
tri[1] = tri[2];
+ edges[0] = edges[2];
+ edges[1] = edges[3];
if (++start == pen->num_vertices)
start = 0;
}
tri[2] = f->ccw;
- _cairo_traps_tessellate_triangle (stroker->traps, tri);
+ edges[2] = f->cw;
+ edges[3] = f->ccw;
+ _cairo_traps_tessellate_triangle_with_edges (stroker->traps,
+ tri, edges);
break;
}
@@ -937,7 +965,6 @@ spline_to (void *closure,
cairo_point_t rectangle[4];
compute_face (&stroker->current_face.point, tangent, stroker, &face);
-
join (stroker, &stroker->current_face, &face);
rectangle[0] = face.cw;
@@ -1024,7 +1051,7 @@ curve_to_dashed (void *closure,
func = (cairo_spline_add_point_func_t)line_to_dashed;
if (stroker->has_bounds &&
- ! _cairo_spline_intersects (&stroker->current_face.point, b, c, b,
+ ! _cairo_spline_intersects (&stroker->current_face.point, b, c, d,
&stroker->line_bounds))
return func (closure, d, NULL);
diff --git a/src/cairo-path-stroke-tristrip.c b/src/cairo-path-stroke-tristrip.c
index 3c232986b..3c232986b 100755..100644
--- a/src/cairo-path-stroke-tristrip.c
+++ b/src/cairo-path-stroke-tristrip.c
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 73c554bd8..5c260c915 100755..100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -54,6 +54,7 @@ typedef struct cairo_stroker {
const cairo_matrix_t *ctm_inverse;
double half_line_width;
double tolerance;
+ double spline_cusp_tolerance;
double ctm_determinant;
cairo_bool_t ctm_det_positive;
@@ -177,6 +178,18 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
stroker->tolerance = tolerance;
stroker->half_line_width = stroke_style->line_width / 2.0;
+ /* To test whether we need to join two segments of a spline using
+ * a round-join or a bevel-join, we can inspect the angle between the
+ * two segments. If the difference between the chord distance
+ * (half-line-width times the cosine of the bisection angle) and the
+ * half-line-width itself is greater than tolerance then we need to
+ * inject a point.
+ */
+ stroker->spline_cusp_tolerance = 1 - tolerance / stroker->half_line_width;
+ stroker->spline_cusp_tolerance *= stroker->spline_cusp_tolerance;
+ stroker->spline_cusp_tolerance *= 2;
+ stroker->spline_cusp_tolerance -= 1;
+
stroker->ctm_determinant = _cairo_matrix_compute_determinant (stroker->ctm);
stroker->ctm_det_positive = stroker->ctm_determinant >= 0.0;
@@ -1052,39 +1065,61 @@ _cairo_stroker_spline_to (void *closure,
slope_dy = _cairo_fixed_to_double (tangent->dy);
if (! _compute_normalized_device_slope (&slope_dx, &slope_dy,
- stroker->ctm_inverse, NULL))
+ stroker->ctm_inverse, NULL))
return CAIRO_STATUS_SUCCESS;
_compute_face (point, tangent,
slope_dx, slope_dy,
stroker, &new_face);
- assert(stroker->has_current_face);
-
- if (_cairo_stroke_segment_intersect (&stroker->current_face.cw,
- &stroker->current_face.ccw,
- &new_face.cw,
- &new_face.ccw,
- &intersect_point)) {
- points[0] = stroker->current_face.ccw;
- points[1] = new_face.ccw;
- points[2] = intersect_point;
- stroker->add_triangle (stroker->closure, points);
-
- points[0] = stroker->current_face.cw;
- points[1] = new_face.cw;
- stroker->add_triangle (stroker->closure, points);
+ assert (stroker->has_current_face);
+
+ if ((new_face.dev_slope.x * stroker->current_face.dev_slope.x +
+ new_face.dev_slope.y * stroker->current_face.dev_slope.y) < stroker->spline_cusp_tolerance) {
+
+ const cairo_point_t *inpt, *outpt;
+ int clockwise = _cairo_stroker_join_is_clockwise (&new_face,
+ &stroker->current_face);
+
+ if (clockwise) {
+ inpt = &stroker->current_face.cw;
+ outpt = &new_face.cw;
+ } else {
+ inpt = &stroker->current_face.ccw;
+ outpt = &new_face.ccw;
+ }
+
+ _tessellate_fan (stroker,
+ &stroker->current_face.dev_vector,
+ &new_face.dev_vector,
+ &stroker->current_face.point,
+ inpt, outpt,
+ clockwise);
}
- else {
- points[0] = stroker->current_face.ccw;
- points[1] = stroker->current_face.cw;
- points[2] = new_face.cw;
- stroker->add_triangle (stroker->closure, points);
-
- points[0] = stroker->current_face.ccw;
- points[1] = new_face.cw;
- points[2] = new_face.ccw;
- stroker->add_triangle (stroker->closure, points);
+
+ if (_slow_segment_intersection (&stroker->current_face.cw,
+ &stroker->current_face.ccw,
+ &new_face.cw,
+ &new_face.ccw,
+ &intersect_point)) {
+ points[0] = stroker->current_face.ccw;
+ points[1] = new_face.ccw;
+ points[2] = intersect_point;
+ stroker->add_triangle (stroker->closure, points);
+
+ points[0] = stroker->current_face.cw;
+ points[1] = new_face.cw;
+ stroker->add_triangle (stroker->closure, points);
+ } else {
+ points[0] = stroker->current_face.ccw;
+ points[1] = stroker->current_face.cw;
+ points[2] = new_face.cw;
+ stroker->add_triangle (stroker->closure, points);
+
+ points[0] = stroker->current_face.ccw;
+ points[1] = new_face.cw;
+ points[2] = new_face.ccw;
+ stroker->add_triangle (stroker->closure, points);
}
/* compute join */
diff --git a/src/cairo-path.c b/src/cairo-path.c
index 43cd175a3..6ca06a74e 100755..100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -342,7 +342,7 @@ _cairo_path_create_internal (cairo_path_fixed_t *path_fixed,
path->data = NULL;
path->status = CAIRO_STATUS_SUCCESS;
}
-
+ path->is_convex = path_fixed->is_convex;
return path;
}
diff --git a/src/cairo-pattern-inline.h b/src/cairo-pattern-inline.h
index 97e8ea034..97e8ea034 100755..100644
--- a/src/cairo-pattern-inline.h
+++ b/src/cairo-pattern-inline.h
diff --git a/src/cairo-pattern-private.h b/src/cairo-pattern-private.h
index a0092b135..5914b45f6 100755..100644
--- a/src/cairo-pattern-private.h
+++ b/src/cairo-pattern-private.h
@@ -259,6 +259,10 @@ cairo_private void
_cairo_pattern_transform (cairo_pattern_t *pattern,
const cairo_matrix_t *ctm_inverse);
+cairo_private void
+_cairo_pattern_pretransform (cairo_pattern_t *pattern,
+ const cairo_matrix_t *ctm);
+
cairo_private cairo_bool_t
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern);
@@ -307,7 +311,7 @@ _cairo_mesh_pattern_coord_box (const cairo_mesh_pattern_t *mesh,
double *out_xmax,
double *out_ymax);
-cairo_private_no_warn cairo_filter_t
+cairo_private void
_cairo_pattern_sampled_area (const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *extents,
cairo_rectangle_int_t *sample);
@@ -350,6 +354,9 @@ cairo_private cairo_bool_t
_cairo_pattern_equal (const cairo_pattern_t *a,
const cairo_pattern_t *b);
+cairo_private cairo_filter_t
+_cairo_pattern_analyze_filter (const cairo_pattern_t *pattern);
+
/* cairo-mesh-pattern-rasterizer.c */
cairo_private void
@@ -380,7 +387,7 @@ _cairo_raster_source_pattern_init_copy (cairo_pattern_t *pattern,
cairo_private void
_cairo_raster_source_pattern_finish (cairo_pattern_t *abstract_pattern);
-cairo_private cairo_status_t
+cairo_private cairo_status_t
_cairo_pattern_create_gaussian_matrix (cairo_pattern_t *pattern,
double line_width);
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 4d6094ba2..c7d269caa 100755..100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -51,8 +51,8 @@
* @See_Also: #cairo_t, #cairo_surface_t
*
* #cairo_pattern_t is the paint with which cairo draws.
- * The primary use of patterns is as the source for all cairo drawing
- * operations, although they can also be used as masks, that is, as the
+ * The primary use of patterns is as the source for all cairo drawing
+ * operations, although they can also be used as masks, that is, as the
* brush too.
*
* A cairo pattern is created by using one of the many constructors,
@@ -2158,6 +2158,16 @@ cairo_pattern_get_extend (cairo_pattern_t *pattern)
slim_hidden_def (cairo_pattern_get_extend);
void
+_cairo_pattern_pretransform (cairo_pattern_t *pattern,
+ const cairo_matrix_t *ctm)
+{
+ if (pattern->status)
+ return;
+
+ cairo_matrix_multiply (&pattern->matrix, &pattern->matrix, ctm);
+}
+
+void
_cairo_pattern_transform (cairo_pattern_t *pattern,
const cairo_matrix_t *ctm_inverse)
{
@@ -3358,111 +3368,180 @@ _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
return FALSE;
}
+/*
+ * Will given row of back-translation matrix work with bilinear scale?
+ * This is true for scales larger than 1. Also it was judged acceptable
+ * for scales larger than .75. And if there is integer translation
+ * then a scale of exactly .5 works.
+ */
+static int
+use_bilinear(double x, double y, double t)
+{
+ /* This is the inverse matrix! */
+ double h = x*x + y*y;
+ if (h < 1.0 / (0.75 * 0.75))
+ return TRUE; /* scale > .75 */
+ if ((h > 3.99 && h < 4.01) /* scale is 1/2 */
+ && !_cairo_fixed_from_double(x*y) /* parallel to an axis */
+ && _cairo_fixed_is_integer (_cairo_fixed_from_double (t)))
+ return TRUE;
+ return FALSE;
+}
+
/**
* _cairo_pattern_analyze_filter:
* @pattern: surface pattern
- * @pad_out: location to store necessary padding in the source image, or %NULL
* Returns: the optimized #cairo_filter_t to use with @pattern.
*
- * Analyze the filter to determine how much extra needs to be sampled
- * from the source image to account for the filter radius and whether
- * we can optimize the filter to a simpler value.
- *
- * XXX: We don't actually have any way of querying the backend for
- * the filter radius, so we just guess base on what we know that
- * backends do currently (see bug #10508)
+ * Possibly optimize the filter to a simpler value depending on transformation
**/
cairo_filter_t
-_cairo_pattern_analyze_filter (const cairo_pattern_t *pattern,
- double *pad_out)
+_cairo_pattern_analyze_filter (const cairo_pattern_t *pattern)
{
- double pad;
- cairo_filter_t optimized_filter;
-
switch (pattern->filter) {
case CAIRO_FILTER_GOOD:
case CAIRO_FILTER_BEST:
case CAIRO_FILTER_BILINEAR:
+ case CAIRO_FILTER_FAST:
/* If source pixels map 1:1 onto destination pixels, we do
* not need to filter (and do not want to filter, since it
* will cause blurriness)
*/
if (_cairo_matrix_is_pixel_exact (&pattern->matrix)) {
- pad = 0.;
- optimized_filter = CAIRO_FILTER_NEAREST;
+ return CAIRO_FILTER_NEAREST;
} else {
- /* 0.5 is enough for a bilinear filter. It's possible we
- * should defensively use more for CAIRO_FILTER_BEST, but
- * without a single example, it's hard to know how much
- * more would be defensive...
+ /* Use BILINEAR for any scale greater than .75 instead
+ * of GOOD. For scales of 1 and larger this is identical,
+ * for the smaller sizes it was judged that the artifacts
+ * were not worse than the artifacts from a box filer.
+ * BILINEAR can also be used if the scale is exactly .5
+ * and the translation in that direction is an integer.
*/
- pad = 0.5;
- optimized_filter = pattern->filter;
+ if (pattern->filter == CAIRO_FILTER_GOOD &&
+ use_bilinear (pattern->matrix.xx, pattern->matrix.xy,
+ pattern->matrix.x0) &&
+ use_bilinear (pattern->matrix.yx, pattern->matrix.yy,
+ pattern->matrix.y0))
+ return CAIRO_FILTER_BILINEAR;
}
break;
- case CAIRO_FILTER_FAST:
case CAIRO_FILTER_NEAREST:
case CAIRO_FILTER_GAUSSIAN:
default:
- pad = 0.;
- optimized_filter = pattern->filter;
break;
}
- if (pad_out)
- *pad_out = pad;
+ return pattern->filter;
+}
- return optimized_filter;
+/**
+ * _cairo_hypot:
+ * Returns: value similar to hypot(@x,@y)
+ *
+ * May want to replace this with Manhattan distance (abs(x)+abs(y)) if
+ * hypot is too slow, as there is no need for accuracy here.
+ **/
+static inline double
+_cairo_hypot(double x, double y)
+{
+ return hypot(x, y);
}
-cairo_filter_t
+/**
+ * _cairo_pattern_sampled_area:
+ *
+ * Return region of @pattern that will be sampled to fill @extents,
+ * based on the transformation and filter.
+ *
+ * This does not include pixels that are mulitiplied by values very
+ * close to zero by the ends of filters. This is so that transforms
+ * that should be the identity or 90 degree rotations do not expand
+ * the source unexpectedly.
+ *
+ * XXX: We don't actually have any way of querying the backend for
+ * the filter radius, so we just guess base on what we know that
+ * backends do currently (see bug #10508)
+ **/
+void
_cairo_pattern_sampled_area (const cairo_pattern_t *pattern,
const cairo_rectangle_int_t *extents,
cairo_rectangle_int_t *sample)
{
- cairo_filter_t filter;
double x1, x2, y1, y2;
- double pad;
+ double padx, pady;
- filter = _cairo_pattern_analyze_filter (pattern, &pad);
- if (pad == 0.0 && _cairo_matrix_is_identity (&pattern->matrix)) {
+ /* Assume filters are interpolating, which means identity
+ cannot change the image */
+ if (_cairo_matrix_is_identity (&pattern->matrix)) {
*sample = *extents;
- return filter;
+ return;
}
- x1 = extents->x;
- y1 = extents->y;
- x2 = extents->x + (int) extents->width;
- y2 = extents->y + (int) extents->height;
-
+ /* Transform the centers of the corner pixels */
+ x1 = extents->x + 0.5;
+ y1 = extents->y + 0.5;
+ x2 = x1 + (extents->width - 1);
+ y2 = y1 + (extents->height - 1);
_cairo_matrix_transform_bounding_box (&pattern->matrix,
&x1, &y1, &x2, &y2,
NULL);
- if (x1 > CAIRO_RECT_INT_MIN)
- sample->x = floor (x1 - pad);
- else
- sample->x = CAIRO_RECT_INT_MIN;
- if (y1 > CAIRO_RECT_INT_MIN)
- sample->y = floor (y1 - pad);
- else
- sample->y = CAIRO_RECT_INT_MIN;
+ /* How far away from center will it actually sample?
+ * This is the distance from a transformed pixel center to the
+ * furthest sample of reasonable size.
+ */
+ switch (pattern->filter) {
+ case CAIRO_FILTER_NEAREST:
+ case CAIRO_FILTER_FAST:
+ /* Correct value is zero, but when the sample is on an integer
+ * it is unknown if the backend will sample the pixel to the
+ * left or right. This value makes it include both possible pixels.
+ */
+ padx = pady = 0.004;
+ break;
+ case CAIRO_FILTER_BILINEAR:
+ case CAIRO_FILTER_GAUSSIAN:
+ default:
+ /* Correct value is .5 */
+ padx = pady = 0.495;
+ break;
+ case CAIRO_FILTER_GOOD:
+ /* Correct value is max(width,1)*.5 */
+ padx = _cairo_hypot (pattern->matrix.xx, pattern->matrix.xy);
+ if (padx <= 1.0) padx = 0.495;
+ else if (padx >= 16.0) padx = 7.92;
+ else padx *= 0.495;
+ pady = _cairo_hypot (pattern->matrix.yx, pattern->matrix.yy);
+ if (pady <= 1.0) pady = 0.495;
+ else if (pady >= 16.0) pady = 7.92;
+ else pady *= 0.495;
+ break;
+ case CAIRO_FILTER_BEST:
+ /* Correct value is width*2 */
+ padx = _cairo_hypot (pattern->matrix.xx, pattern->matrix.xy) * 1.98;
+ if (padx > 7.92) padx = 7.92;
+ pady = _cairo_hypot (pattern->matrix.yx, pattern->matrix.yy) * 1.98;
+ if (pady > 7.92) pady = 7.92;
+ break;
+ }
- if (x2 < CAIRO_RECT_INT_MAX)
- sample->width = ceil (x2 + pad);
- else
- sample->width = CAIRO_RECT_INT_MAX;
+ /* round furthest samples to edge of pixels */
+ x1 = floor (x1 - padx);
+ if (x1 < CAIRO_RECT_INT_MIN) x1 = CAIRO_RECT_INT_MIN;
+ sample->x = x1;
- if (y2 < CAIRO_RECT_INT_MAX)
- sample->height = ceil (y2 + pad);
- else
- sample->height = CAIRO_RECT_INT_MAX;
+ y1 = floor (y1 - pady);
+ if (y1 < CAIRO_RECT_INT_MIN) y1 = CAIRO_RECT_INT_MIN;
+ sample->y = y1;
- sample->width -= sample->x;
- sample->height -= sample->y;
+ x2 = floor (x2 + padx) + 1.0;
+ if (x2 > CAIRO_RECT_INT_MAX) x2 = CAIRO_RECT_INT_MAX;
+ sample->width = x2 - x1;
- return filter;
+ y2 = floor (y2 + pady) + 1.0;
+ if (y2 > CAIRO_RECT_INT_MAX) y2 = CAIRO_RECT_INT_MAX;
+ sample->height = y2 - y1;
}
/**
@@ -3482,7 +3561,9 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
cairo_rectangle_int_t *extents)
{
double x1, y1, x2, y2;
- cairo_status_t status;
+ int ix1, ix2, iy1, iy2;
+ cairo_bool_t round_x = FALSE;
+ cairo_bool_t round_y = FALSE;
switch (pattern->type) {
case CAIRO_PATTERN_TYPE_SOLID:
@@ -3494,7 +3575,6 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
const cairo_surface_pattern_t *surface_pattern =
(const cairo_surface_pattern_t *) pattern;
cairo_surface_t *surface = surface_pattern->surface;
- double pad;
if (! _cairo_surface_get_extents (surface, &surface_extents))
goto UNBOUNDED;
@@ -3505,14 +3585,12 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
if (pattern->extend != CAIRO_EXTEND_NONE)
goto UNBOUNDED;
- /* The filter can effectively enlarge the extents of the
- * pattern, so extend as necessary.
- */
- _cairo_pattern_analyze_filter (&surface_pattern->base, &pad);
- x1 = surface_extents.x - pad;
- y1 = surface_extents.y - pad;
- x2 = surface_extents.x + (int) surface_extents.width + pad;
- y2 = surface_extents.y + (int) surface_extents.height + pad;
+ x1 = surface_extents.x;
+ y1 = surface_extents.y;
+ x2 = surface_extents.x + (int) surface_extents.width;
+ y2 = surface_extents.y + (int) surface_extents.height;
+
+ goto HANDLE_FILTER;
}
break;
@@ -3520,7 +3598,6 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
{
const cairo_raster_source_pattern_t *raster =
(const cairo_raster_source_pattern_t *) pattern;
- double pad;
if (raster->extents.width == 0 || raster->extents.height == 0)
goto EMPTY;
@@ -3528,14 +3605,41 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
if (pattern->extend != CAIRO_EXTEND_NONE)
goto UNBOUNDED;
- /* The filter can effectively enlarge the extents of the
- * pattern, so extend as necessary.
- */
- _cairo_pattern_analyze_filter (pattern, &pad);
- x1 = raster->extents.x - pad;
- y1 = raster->extents.y - pad;
- x2 = raster->extents.x + (int) raster->extents.width + pad;
- y2 = raster->extents.y + (int) raster->extents.height + pad;
+ x1 = raster->extents.x;
+ y1 = raster->extents.y;
+ x2 = raster->extents.x + (int) raster->extents.width;
+ y2 = raster->extents.y + (int) raster->extents.height;
+ }
+ HANDLE_FILTER:
+ switch (pattern->filter) {
+ case CAIRO_FILTER_NEAREST:
+ case CAIRO_FILTER_FAST:
+ round_x = round_y = TRUE;
+ /* We don't know which way .5 will go, so fudge it slightly. */
+ x1 -= 0.004;
+ y1 -= 0.004;
+ x2 += 0.004;
+ y2 += 0.004;
+ break;
+ case CAIRO_FILTER_BEST:
+ /* Assume best filter will produce nice antialiased edges */
+ break;
+ case CAIRO_FILTER_BILINEAR:
+ case CAIRO_FILTER_GAUSSIAN:
+ case CAIRO_FILTER_GOOD:
+ default:
+ /* These filters can blur the edge out 1/2 pixel when scaling up */
+ if (_cairo_hypot (pattern->matrix.xx, pattern->matrix.yx) < 1.0) {
+ x1 -= 0.5;
+ x2 += 0.5;
+ round_x = TRUE;
+ }
+ if (_cairo_hypot (pattern->matrix.xy, pattern->matrix.yy) < 1.0) {
+ y1 -= 0.5;
+ y2 += 0.5;
+ round_y = TRUE;
+ }
+ break;
}
break;
@@ -3607,6 +3711,10 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
} else {
goto UNBOUNDED;
}
+
+ /* The current linear renderer just point-samples in the middle
+ of the pixels, similar to the NEAREST filter: */
+ round_x = round_y = TRUE;
}
break;
@@ -3614,22 +3722,8 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
{
const cairo_mesh_pattern_t *mesh =
(const cairo_mesh_pattern_t *) pattern;
- double padx, pady;
- cairo_bool_t is_valid;
-
- is_valid = _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2);
- if (!is_valid)
+ if (! _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2))
goto EMPTY;
-
- padx = pady = 1.;
- cairo_matrix_transform_distance (&pattern->matrix, &padx, &pady);
- padx = fabs (padx);
- pady = fabs (pady);
-
- x1 -= padx;
- y1 -= pady;
- x2 += padx;
- y2 += pady;
}
break;
@@ -3642,6 +3736,7 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
} else {
cairo_matrix_t imatrix;
+ cairo_status_t status;
imatrix = pattern->matrix;
status = cairo_matrix_invert (&imatrix);
@@ -3653,22 +3748,34 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
NULL);
}
- x1 = floor (x1);
+ if (!round_x) {
+ x1 -= 0.5;
+ x2 += 0.5;
+ }
if (x1 < CAIRO_RECT_INT_MIN)
- x1 = CAIRO_RECT_INT_MIN;
- y1 = floor (y1);
- if (y1 < CAIRO_RECT_INT_MIN)
- y1 = CAIRO_RECT_INT_MIN;
-
- x2 = ceil (x2);
+ ix1 = CAIRO_RECT_INT_MIN;
+ else
+ ix1 = _cairo_lround (x1);
if (x2 > CAIRO_RECT_INT_MAX)
- x2 = CAIRO_RECT_INT_MAX;
- y2 = ceil (y2);
+ ix2 = CAIRO_RECT_INT_MAX;
+ else
+ ix2 = _cairo_lround (x2);
+ extents->x = ix1; extents->width = ix2 - ix1;
+
+ if (!round_y) {
+ y1 -= 0.5;
+ y2 += 0.5;
+ }
+ if (y1 < CAIRO_RECT_INT_MIN)
+ iy1 = CAIRO_RECT_INT_MIN;
+ else
+ iy1 = _cairo_lround (y1);
if (y2 > CAIRO_RECT_INT_MAX)
- y2 = CAIRO_RECT_INT_MAX;
+ iy2 = CAIRO_RECT_INT_MAX;
+ else
+ iy2 = _cairo_lround (y2);
+ extents->y = iy1; extents->height = iy2 - iy1;
- extents->x = x1; extents->width = x2 - x1;
- extents->y = y1; extents->height = y2 - y1;
return;
UNBOUNDED:
@@ -4251,7 +4358,7 @@ cairo_pattern_get_rgba (cairo_pattern_t *pattern,
* cairo_pattern_get_surface:
* @pattern: a #cairo_pattern_t
* @surface: return value for surface of pattern, or %NULL
- *
+ *
* Gets the surface of a surface pattern. The reference returned in
* @surface is owned by the pattern; the caller should call
* cairo_surface_reference() if the surface is to be retained.
@@ -4291,8 +4398,9 @@ cairo_pattern_get_surface (cairo_pattern_t *pattern,
* @alpha: return value for alpha component of color, or %NULL
*
* Gets the color and offset information at the given @index for a
- * gradient pattern. Values of @index are 0 to 1 less than the number
- * returned by cairo_pattern_get_color_stop_count().
+ * gradient pattern. Values of @index range from 0 to n-1
+ * where n is the number returned
+ * by cairo_pattern_get_color_stop_count().
*
* Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
* if @index is not valid for the given pattern. If the pattern is
@@ -4502,7 +4610,7 @@ slim_hidden_def (cairo_mesh_pattern_get_patch_count);
* Gets path defining the patch @patch_num for a mesh
* pattern.
*
- * @patch_num can range 0 to 1 less than the number returned by
+ * @patch_num can range from 0 to n-1 where n is the number returned by
* cairo_mesh_pattern_get_patch_count().
*
* Return value: the path defining the patch, or a path with status
@@ -4598,7 +4706,7 @@ slim_hidden_def (cairo_mesh_pattern_get_path);
* Gets the color information in corner @corner_num of patch
* @patch_num for a mesh pattern.
*
- * @patch_num can range 0 to 1 less than the number returned by
+ * @patch_num can range from 0 to n-1 where n is the number returned by
* cairo_mesh_pattern_get_patch_count().
*
* Valid values for @corner_num are from 0 to 3 and identify the
@@ -4666,7 +4774,7 @@ slim_hidden_def (cairo_mesh_pattern_get_corner_color_rgba);
* Gets the control point @point_num of patch @patch_num for a mesh
* pattern.
*
- * @patch_num can range 0 to 1 less than the number returned by
+ * @patch_num can range from 0 to n-1 where n is the number returned by
* cairo_mesh_pattern_get_patch_count().
*
* Valid values for @point_num are from 0 to 3 and identify the
@@ -4840,7 +4948,7 @@ _cairo_pattern_create_gaussian_matrix (cairo_pattern_t *pattern,
break;
x_sigma /= 2.0;
- x_factor *= 2;
+ x_factor *= 2;
width *= 0.5;
test_line_width *= 0.5;
}
diff --git a/src/cairo-pdf-operators-private.h b/src/cairo-pdf-operators-private.h
index 6e1ae1833..4314a042e 100755..100644
--- a/src/cairo-pdf-operators-private.h
+++ b/src/cairo-pdf-operators-private.h
@@ -53,9 +53,10 @@
*/
#define PDF_GLYPH_BUFFER_SIZE 200
-typedef cairo_status_t (*cairo_pdf_operators_use_font_subset_t) (unsigned int font_id,
- unsigned int subset_id,
- void *closure);
+typedef cairo_int_status_t
+(*cairo_pdf_operators_use_font_subset_t) (unsigned int font_id,
+ unsigned int subset_id,
+ void *closure);
typedef struct _cairo_pdf_glyph {
unsigned int glyph_index;
@@ -69,6 +70,7 @@ typedef struct _cairo_pdf_operators {
cairo_scaled_font_subsets_t *font_subsets;
cairo_pdf_operators_use_font_subset_t use_font_subset;
void *use_font_subset_closure;
+ cairo_bool_t ps_output; /* output is for PostScript */
cairo_bool_t use_actual_text;
cairo_bool_t in_text_object; /* inside BT/ET pair */
@@ -100,7 +102,8 @@ cairo_private void
_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream,
cairo_matrix_t *cairo_to_pdf,
- cairo_scaled_font_subsets_t *font_subsets);
+ cairo_scaled_font_subsets_t *font_subsets,
+ cairo_bool_t ps);
cairo_private cairo_status_t
_cairo_pdf_operators_fini (cairo_pdf_operators_t *pdf_operators);
diff --git a/src/cairo-pdf-operators.c b/src/cairo-pdf-operators.c
index fceaf1cc4..dcee25f0c 100755..100644
--- a/src/cairo-pdf-operators.c
+++ b/src/cairo-pdf-operators.c
@@ -57,11 +57,13 @@ void
_cairo_pdf_operators_init (cairo_pdf_operators_t *pdf_operators,
cairo_output_stream_t *stream,
cairo_matrix_t *cairo_to_pdf,
- cairo_scaled_font_subsets_t *font_subsets)
+ cairo_scaled_font_subsets_t *font_subsets,
+ cairo_bool_t ps)
{
pdf_operators->stream = stream;
pdf_operators->cairo_to_pdf = *cairo_to_pdf;
pdf_operators->font_subsets = font_subsets;
+ pdf_operators->ps_output = ps;
pdf_operators->use_font_subset = NULL;
pdf_operators->use_font_subset_closure = NULL;
pdf_operators->in_text_object = FALSE;
@@ -176,6 +178,7 @@ typedef struct _word_wrap_stream {
cairo_output_stream_t base;
cairo_output_stream_t *output;
int max_column;
+ cairo_bool_t ps_output;
int column;
cairo_word_wrap_state_t state;
cairo_bool_t in_escape;
@@ -269,7 +272,7 @@ _word_wrap_stream_count_string_up_to (word_wrap_stream_t *stream,
if (*s == '\\') {
stream->in_escape = TRUE;
stream->escape_digits = 0;
- } else if (stream->column > stream->max_column) {
+ } else if (stream->ps_output && stream->column > stream->max_column) {
newline = TRUE;
break;
}
@@ -348,7 +351,7 @@ _word_wrap_stream_close (cairo_output_stream_t *base)
}
static cairo_output_stream_t *
-_word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
+_word_wrap_stream_create (cairo_output_stream_t *output, cairo_bool_t ps, int max_column)
{
word_wrap_stream_t *stream;
@@ -367,6 +370,7 @@ _word_wrap_stream_create (cairo_output_stream_t *output, int max_column)
_word_wrap_stream_close);
stream->output = output;
stream->max_column = max_column;
+ stream->ps_output = ps;
stream->column = 0;
stream->state = WRAP_STATE_DELIMITER;
stream->in_escape = FALSE;
@@ -502,7 +506,7 @@ _cairo_pdf_operators_emit_path (cairo_pdf_operators_t *pdf_operators,
pdf_path_info_t info;
cairo_box_t box;
- word_wrap = _word_wrap_stream_create (pdf_operators->stream, 72);
+ word_wrap = _word_wrap_stream_create (pdf_operators->stream, pdf_operators->ps_output, 72);
status = _cairo_output_stream_get_status (word_wrap);
if (unlikely (status))
return _cairo_output_stream_destroy (word_wrap);
@@ -510,7 +514,9 @@ _cairo_pdf_operators_emit_path (cairo_pdf_operators_t *pdf_operators,
info.output = word_wrap;
info.path_transform = path_transform;
info.line_cap = line_cap;
- if (_cairo_path_fixed_is_rectangle (path, &box)) {
+ if (_cairo_path_fixed_is_rectangle (path, &box) &&
+ ((path_transform->xx == 0 && path_transform->yy == 0) ||
+ (path_transform->xy == 0 && path_transform->yx == 0))) {
status = _cairo_pdf_path_rectangle (&info, &box);
} else {
status = _cairo_path_fixed_interpret (path,
@@ -828,10 +834,9 @@ _cairo_pdf_operators_emit_stroke (cairo_pdf_operators_t *pdf_operators,
return status;
if (has_ctm) {
- _cairo_output_stream_printf (pdf_operators->stream,
- "q %f %f %f %f %f %f cm\n",
- m.xx, m.yx, m.xy, m.yy,
- m.x0, m.y0);
+ _cairo_output_stream_printf (pdf_operators->stream, "q ");
+ _cairo_output_stream_print_matrix (pdf_operators->stream, &m);
+ _cairo_output_stream_printf (pdf_operators->stream, " cm\n");
} else {
path_transform = pdf_operators->cairo_to_pdf;
}
@@ -1050,7 +1055,7 @@ _cairo_pdf_operators_flush_glyphs (cairo_pdf_operators_t *pdf_operators)
if (pdf_operators->num_glyphs == 0)
return CAIRO_STATUS_SUCCESS;
- word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, 72);
+ word_wrap_stream = _word_wrap_stream_create (pdf_operators->stream, pdf_operators->ps_output, 72);
status = _cairo_output_stream_get_status (word_wrap_stream);
if (unlikely (status))
return _cairo_output_stream_destroy (word_wrap_stream);
@@ -1120,14 +1125,8 @@ _cairo_pdf_operators_set_text_matrix (cairo_pdf_operators_t *pdf_operators,
pdf_operators->cur_x = 0;
pdf_operators->cur_y = 0;
pdf_operators->glyph_buf_x_pos = 0;
- _cairo_output_stream_printf (pdf_operators->stream,
- "%f %f %f %f %f %f Tm\n",
- pdf_operators->text_matrix.xx,
- pdf_operators->text_matrix.yx,
- pdf_operators->text_matrix.xy,
- pdf_operators->text_matrix.yy,
- pdf_operators->text_matrix.x0,
- pdf_operators->text_matrix.y0);
+ _cairo_output_stream_print_matrix (pdf_operators->stream, &pdf_operators->text_matrix);
+ _cairo_output_stream_printf (pdf_operators->stream, " Tm\n");
pdf_operators->cairo_to_pdftext = *matrix;
status = cairo_matrix_invert (&pdf_operators->cairo_to_pdftext);
@@ -1416,7 +1415,11 @@ _cairo_pdf_operators_emit_cluster (cairo_pdf_operators_t *pdf_operators,
return status;
}
- cur_glyph = glyphs;
+ if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+ cur_glyph = glyphs + num_glyphs - 1;
+ else
+ cur_glyph = glyphs;
+
/* XXX
* If no glyphs, we should put *something* here for the text to be selectable. */
for (i = 0; i < num_glyphs; i++) {
diff --git a/src/cairo-pdf-shading-private.h b/src/cairo-pdf-shading-private.h
index 0ca8cb7d5..0ca8cb7d5 100755..100644
--- a/src/cairo-pdf-shading-private.h
+++ b/src/cairo-pdf-shading-private.h
diff --git a/src/cairo-pdf-shading.c b/src/cairo-pdf-shading.c
index 6a2fe3615..6a2fe3615 100755..100644
--- a/src/cairo-pdf-shading.c
+++ b/src/cairo-pdf-shading.c
diff --git a/src/cairo-pdf-surface-private.h b/src/cairo-pdf-surface-private.h
index d9f65d800..618ca4ede 100755..100644
--- a/src/cairo-pdf-surface-private.h
+++ b/src/cairo-pdf-surface-private.h
@@ -70,9 +70,12 @@ typedef struct _cairo_pdf_source_surface_entry {
unsigned int id;
unsigned char *unique_id;
unsigned long unique_id_length;
+ cairo_operator_t operator;
cairo_bool_t interpolate;
cairo_bool_t stencil_mask;
+ cairo_bool_t smask;
cairo_pdf_resource_t surface_res;
+ cairo_pdf_resource_t smask_res;
int width;
int height;
cairo_rectangle_int_t extents;
@@ -92,6 +95,7 @@ typedef struct _cairo_pdf_pattern {
cairo_pattern_t *pattern;
cairo_pdf_resource_t pattern_res;
cairo_pdf_resource_t gstate_res;
+ cairo_operator_t operator;
cairo_bool_t is_shading;
} cairo_pdf_pattern_t;
@@ -127,6 +131,13 @@ typedef struct _cairo_pdf_smask_group {
cairo_scaled_font_t *scaled_font;
} cairo_pdf_smask_group_t;
+typedef struct _cairo_pdf_jbig2_global {
+ unsigned char *id;
+ unsigned long id_length;
+ cairo_pdf_resource_t res;
+ cairo_bool_t emitted;
+} cairo_pdf_jbig2_global_t;
+
typedef struct _cairo_pdf_surface cairo_pdf_surface_t;
struct _cairo_pdf_surface {
@@ -149,6 +160,7 @@ struct _cairo_pdf_surface {
cairo_hash_table_t *all_surfaces;
cairo_array_t smask_groups;
cairo_array_t knockout_group;
+ cairo_array_t jbig2_global;
cairo_scaled_font_subsets_t *font_subsets;
cairo_array_t fonts;
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index a0bf1c1d5..552e4bf4f 100755..100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -130,6 +130,23 @@
*
* The PDF surface is used to render cairo graphics to Adobe
* PDF files and is a multi-page vector surface backend.
+ *
+ * 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.
+ *
+ * JBIG2 data in PDF must be in the embedded format as descibed 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
+ * 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
+ * %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
**/
static cairo_bool_t
@@ -164,6 +181,9 @@ static const char *_cairo_pdf_supported_mime_types[] =
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,
NULL
};
@@ -198,7 +218,7 @@ _cairo_pdf_surface_clear (cairo_pdf_surface_t *surface);
static void
_cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group);
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_font (unsigned int font_id,
unsigned int subset_id,
void *closure);
@@ -206,16 +226,16 @@ _cairo_pdf_surface_add_font (unsigned int font_id,
static void
_cairo_pdf_group_resources_init (cairo_pdf_group_resources_t *res);
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t *resource,
cairo_bool_t compressed,
const char *fmt,
...) CAIRO_PRINTF_FORMAT(4, 5);
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface);
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
static void
@@ -230,10 +250,10 @@ _cairo_pdf_surface_write_catalog (cairo_pdf_surface_t *surface);
static long
_cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface);
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface);
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface);
static cairo_bool_t
@@ -246,7 +266,7 @@ static cairo_pdf_resource_t
_cairo_pdf_surface_new_object (cairo_pdf_surface_t *surface)
{
cairo_pdf_resource_t resource;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_pdf_object_t object;
object.offset = _cairo_output_stream_get_position (surface->output);
@@ -365,6 +385,7 @@ _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->jbig2_global, sizeof (cairo_pdf_jbig2_global_t));
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);
@@ -410,7 +431,8 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
_cairo_pdf_operators_init (&surface->pdf_operators,
surface->output,
&surface->cairo_to_pdf,
- surface->font_subsets);
+ surface->font_subsets,
+ FALSE);
_cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
_cairo_pdf_surface_add_font,
surface);
@@ -769,14 +791,14 @@ _cairo_pdf_surface_add_operator (cairo_pdf_surface_t *surface,
res->operators[op] = TRUE;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
double alpha,
int *index)
{
int num_alphas, i;
double other;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_pdf_group_resources_t *res = &surface->resources;
num_alphas = _cairo_array_num_elements (&res->alphas);
@@ -797,21 +819,21 @@ _cairo_pdf_surface_add_alpha (cairo_pdf_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_smask (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t smask)
{
return _cairo_array_append (&(surface->resources.smasks), &smask);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_pattern (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t pattern)
{
return _cairo_array_append (&(surface->resources.patterns), &pattern);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_shading (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t shading)
{
@@ -819,14 +841,14 @@ _cairo_pdf_surface_add_shading (cairo_pdf_surface_t *surface,
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_xobject (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t xobject)
{
return _cairo_array_append (&(surface->resources.xobjects), &xobject);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_font (unsigned int font_id,
unsigned int subset_id,
void *closure)
@@ -834,7 +856,7 @@ _cairo_pdf_surface_add_font (unsigned int font_id,
cairo_pdf_surface_t *surface = closure;
cairo_pdf_font_t font;
int num_fonts, i;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_pdf_group_resources_t *res = &surface->resources;
num_fonts = _cairo_array_num_elements (&res->fonts);
@@ -1093,7 +1115,7 @@ _cairo_pdf_smask_group_destroy (cairo_pdf_smask_group_t *group)
free (group);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_smask_group (cairo_pdf_surface_t *surface,
cairo_pdf_smask_group_t *group)
{
@@ -1187,6 +1209,20 @@ _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,
@@ -1263,6 +1299,15 @@ _get_source_surface_size (cairo_surface_t *source,
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;
@@ -1295,9 +1340,12 @@ _get_source_surface_size (cairo_surface_t *source,
* @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
@@ -1315,13 +1363,16 @@ _get_source_surface_size (cairo_surface_t *source,
* Only one of @source_pattern or @source_surface is to be
* specified. Set the other to NULL.
**/
-static cairo_status_t
+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,
@@ -1332,9 +1383,9 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
cairo_pdf_source_surface_t src_surface;
cairo_pdf_source_surface_entry_t surface_key;
cairo_pdf_source_surface_entry_t *surface_entry;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_bool_t interpolate;
- unsigned char *unique_id;
+ unsigned char *unique_id = NULL;
unsigned long unique_id_length = 0;
cairo_image_surface_t *image;
void *image_extra;
@@ -1419,13 +1470,19 @@ release_source:
}
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->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;
_cairo_pdf_source_surface_init_key (surface_entry);
src_surface.hash_entry = surface_entry;
@@ -1476,24 +1533,26 @@ fail1:
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface,
const cairo_pattern_t *pattern,
+ cairo_operator_t op,
const cairo_rectangle_int_t *extents,
cairo_bool_t is_shading,
cairo_pdf_resource_t *pattern_res,
cairo_pdf_resource_t *gstate_res)
{
cairo_pdf_pattern_t pdf_pattern;
- cairo_status_t status;
+ cairo_int_status_t status;
pdf_pattern.is_shading = is_shading;
+ pdf_pattern.operator = op;
/* Solid colors are emitted into the content stream */
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
pattern_res->id = 0;
gstate_res->id = 0;
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
status = _cairo_pattern_create_copy (&pdf_pattern.pattern, pattern);
@@ -1545,7 +1604,7 @@ _cairo_pdf_surface_add_pdf_pattern_or_shading (cairo_pdf_surface_t *surface,
return status;
}
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
/* Get BBox in PDF coordinates from extents in cairo coordinates */
@@ -1560,37 +1619,41 @@ _get_bbox_from_extents (double surface_height,
bbox->p2.y = surface_height - extents->y;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_pdf_shading (cairo_pdf_surface_t *surface,
const cairo_pattern_t *pattern,
+ cairo_operator_t op,
const cairo_rectangle_int_t *extents,
cairo_pdf_resource_t *shading_res,
cairo_pdf_resource_t *gstate_res)
{
return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
pattern,
+ op,
extents,
TRUE,
shading_res,
gstate_res);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
const cairo_pattern_t *pattern,
+ cairo_operator_t op,
const cairo_rectangle_int_t *extents,
cairo_pdf_resource_t *pattern_res,
cairo_pdf_resource_t *gstate_res)
{
return _cairo_pdf_surface_add_pdf_pattern_or_shading (surface,
pattern,
+ op,
extents,
FALSE,
pattern_res,
gstate_res);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t *resource,
cairo_bool_t compressed,
@@ -1659,22 +1722,22 @@ _cairo_pdf_surface_open_stream (cairo_pdf_surface_t *surface,
return _cairo_output_stream_get_status (surface->output);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
{
- cairo_status_t status;
+ cairo_int_status_t status;
long length;
if (! surface->pdf_stream.active)
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (surface->pdf_stream.compressed) {
- cairo_status_t status2;
+ cairo_int_status_t status2;
status2 = _cairo_output_stream_destroy (surface->output);
- if (likely (status == CAIRO_STATUS_SUCCESS))
+ if (likely (status == CAIRO_INT_STATUS_SUCCESS))
status = status2;
surface->output = surface->pdf_stream.old_output;
@@ -1700,7 +1763,7 @@ _cairo_pdf_surface_close_stream (cairo_pdf_surface_t *surface)
surface->pdf_stream.active = FALSE;
- if (likely (status == CAIRO_STATUS_SUCCESS))
+ if (likely (status == CAIRO_INT_STATUS_SUCCESS))
status = _cairo_output_stream_get_status (surface->output);
return status;
@@ -1755,12 +1818,12 @@ _cairo_pdf_surface_write_memory_stream (cairo_pdf_surface_t *surface,
"endobj\n");
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
const cairo_box_double_t *bbox,
cairo_pdf_resource_t *resource)
{
- cairo_status_t status;
+ cairo_int_status_t status;
assert (surface->pdf_stream.active == FALSE);
assert (surface->group_stream.active == FALSE);
@@ -1798,11 +1861,11 @@ _cairo_pdf_surface_open_group (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
const cairo_box_double_t *bbox)
{
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_pdf_surface_open_group (surface, bbox, NULL);
if (unlikely (status))
@@ -1810,14 +1873,14 @@ _cairo_pdf_surface_open_knockout_group (cairo_pdf_surface_t *surface,
surface->group_stream.is_knockout = TRUE;
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t *group)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS, status2;
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS, status2;
assert (surface->pdf_stream.active == FALSE);
assert (surface->group_stream.active == TRUE);
@@ -1846,7 +1909,7 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
*group = surface->group_stream.resource;
status2 = _cairo_output_stream_destroy (surface->group_stream.mem_stream);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
surface->group_stream.mem_stream = NULL;
@@ -1855,13 +1918,14 @@ _cairo_pdf_surface_close_group (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
const cairo_box_double_t *bbox,
cairo_pdf_resource_t *resource,
- cairo_bool_t is_form)
+ cairo_bool_t is_form,
+ cairo_bool_t is_group)
{
- cairo_status_t status;
+ cairo_int_status_t status;
assert (surface->pdf_stream.active == FALSE);
assert (surface->group_stream.active == FALSE);
@@ -1873,25 +1937,41 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
if (is_form) {
assert (bbox != NULL);
- status =
- _cairo_pdf_surface_open_stream (surface,
- resource,
- surface->compress_content,
- " /Type /XObject\n"
- " /Subtype /Form\n"
- " /BBox [ %f %f %f %f ]\n"
- " /Group <<\n"
- " /Type /Group\n"
- " /S /Transparency\n"
- " /I true\n"
- " /CS /DeviceRGB\n"
- " >>\n"
- " /Resources %d 0 R\n",
- bbox->p1.x,
- bbox->p1.y,
- bbox->p2.x,
- bbox->p2.y,
- surface->content_resources.id);
+ if (is_group) {
+ status =
+ _cairo_pdf_surface_open_stream (surface,
+ resource,
+ surface->compress_content,
+ " /Type /XObject\n"
+ " /Subtype /Form\n"
+ " /BBox [ %f %f %f %f ]\n"
+ " /Group <<\n"
+ " /Type /Group\n"
+ " /S /Transparency\n"
+ " /I true\n"
+ " /CS /DeviceRGB\n"
+ " >>\n"
+ " /Resources %d 0 R\n",
+ bbox->p1.x,
+ bbox->p1.y,
+ bbox->p2.x,
+ bbox->p2.y,
+ surface->content_resources.id);
+ } else {
+ status =
+ _cairo_pdf_surface_open_stream (surface,
+ resource,
+ surface->compress_content,
+ " /Type /XObject\n"
+ " /Subtype /Form\n"
+ " /BBox [ %f %f %f %f ]\n"
+ " /Resources %d 0 R\n",
+ bbox->p1.x,
+ bbox->p1.y,
+ bbox->p2.x,
+ bbox->p2.y,
+ surface->content_resources.id);
+ }
} else {
status =
_cairo_pdf_surface_open_stream (surface,
@@ -1909,10 +1989,10 @@ _cairo_pdf_surface_open_content_stream (cairo_pdf_surface_t *surface,
return _cairo_output_stream_get_status (surface->output);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
{
- cairo_status_t status;
+ cairo_int_status_t status;
assert (surface->pdf_stream.active == TRUE);
assert (surface->group_stream.active == FALSE);
@@ -1956,6 +2036,8 @@ _cairo_pdf_surface_finish (void *abstract_surface)
long offset;
cairo_pdf_resource_t info, catalog;
cairo_status_t status, status2;
+ int size, i;
+ cairo_pdf_jbig2_global_t *global;
status = surface->base.status;
if (status == CAIRO_STATUS_SUCCESS)
@@ -2045,6 +2127,17 @@ _cairo_pdf_surface_finish (void *abstract_surface)
surface->font_subsets = NULL;
}
+ size = _cairo_array_num_elements (&surface->jbig2_global);
+ for (i = 0; i < size; i++) {
+ global = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
+ free(global->id);
+ if (!global->emitted)
+ return _cairo_error (CAIRO_STATUS_JBIG2_GLOBAL_MISSING);
+ }
+ _cairo_array_fini (&surface->jbig2_global);
+
+ _cairo_array_truncate (&surface->page_surfaces, 0);
+
_cairo_surface_clipper_reset (&surface->clipper);
return status;
@@ -2085,7 +2178,7 @@ static cairo_int_status_t
_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
cairo_bool_t has_fallbacks)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_pdf_surface_t *surface = abstract_surface;
cairo_box_double_t bbox;
@@ -2094,7 +2187,7 @@ _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
bbox.p1.y = 0;
bbox.p2.x = surface->width;
bbox.p2.y = surface->height;
- status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks);
+ status = _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, has_fallbacks, has_fallbacks);
if (unlikely (status))
return status;
@@ -2107,7 +2200,7 @@ _cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
return TRUE;
}
-static cairo_status_t
+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,
@@ -2144,7 +2237,7 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa
h = image->height;
if (_cairo_fixed_integer_ceil(box.p1.x) < 0 ||
_cairo_fixed_integer_ceil(box.p1.y) < 0 ||
- _cairo_fixed_integer_floor(box.p2.y) > w ||
+ _cairo_fixed_integer_floor(box.p2.x) > w ||
_cairo_fixed_integer_floor(box.p2.y) > h)
{
pad_image = _cairo_image_surface_create_with_content (image->base.content,
@@ -2169,9 +2262,12 @@ _cairo_pdf_surface_add_padded_image_surface (cairo_pdf_surface_t *surfa
status = _cairo_pdf_surface_add_source_surface (surface,
pad_image,
NULL,
+ FALSE,
source->filter,
FALSE,
+ FALSE,
extents,
+ NULL,
surface_res,
width,
height,
@@ -2202,24 +2298,16 @@ BAIL:
return status;
}
-/* Emit alpha channel from the image into the given data, providing
- * an id that can be used to reference the resulting SMask object.
- *
- * In the case that the alpha channel happens to be all opaque, then
- * no SMask object will be emitted and *id_ret will be set to 0.
- *
- * When stencil_mask is TRUE, stream_res is an an input specifying the
- * resource to use. When stencil_mask is FALSE, a new resource will be
- * created and returned in stream_res.
+/* Emit alpha channel from the image into stream_res.
*/
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
cairo_image_surface_t *image,
cairo_bool_t stencil_mask,
- const char *interpolate,
+ cairo_bool_t interpolate,
cairo_pdf_resource_t *stream_res)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
char *alpha;
unsigned long alpha_size;
uint32_t *pixel32;
@@ -2229,6 +2317,7 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
/* This is the only image format we support, which simplifies things. */
assert (image->format == CAIRO_FORMAT_ARGB32 ||
+ image->format == CAIRO_FORMAT_RGB24 ||
image->format == CAIRO_FORMAT_A8 ||
image->format == CAIRO_FORMAT_A1 );
@@ -2237,11 +2326,10 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
assert (transparency == CAIRO_IMAGE_IS_OPAQUE ||
transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA);
} else {
- if (transparency == CAIRO_IMAGE_IS_OPAQUE)
- return status;
+ assert (transparency != CAIRO_IMAGE_IS_OPAQUE);
}
- if (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA) {
+ if (transparency == CAIRO_IMAGE_HAS_BILEVEL_ALPHA || transparency == CAIRO_IMAGE_IS_OPAQUE) {
alpha_size = (image->width + 7) / 8 * image->height;
alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
} else {
@@ -2256,7 +2344,10 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
i = 0;
for (y = 0; y < image->height; y++) {
- if (image->format == CAIRO_FORMAT_A1) {
+ if (transparency == CAIRO_IMAGE_IS_OPAQUE) {
+ for (x = 0; x < (image->width + 7) / 8; x++)
+ alpha[i++] = 0xff;
+ } else if (image->format == CAIRO_FORMAT_A1) {
pixel8 = (uint8_t *) (image->data + y * image->stride);
for (x = 0; x < (image->width + 7) / 8; x++, pixel8++) {
@@ -2308,11 +2399,11 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
" /Interpolate %s\n"
" /BitsPerComponent 1\n"
" /Decode [1 0]\n",
- image->width, image->height, interpolate);
+ image->width, image->height,
+ interpolate ? "true" : "false");
} else {
- stream_res->id = 0;
status = _cairo_pdf_surface_open_stream (surface,
- NULL,
+ stream_res,
TRUE,
" /Type /XObject\n"
" /Subtype /Image\n"
@@ -2321,15 +2412,13 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
" /ColorSpace /DeviceGray\n"
" /Interpolate %s\n"
" /BitsPerComponent %d\n",
- image->width, image->height, interpolate,
+ image->width, image->height,
+ interpolate ? "true" : "false",
transparency == CAIRO_IMAGE_HAS_ALPHA ? 8 : 1);
}
if (unlikely (status))
goto CLEANUP_ALPHA;
- if (!stencil_mask)
- *stream_res = surface->pdf_stream.self;
-
_cairo_output_stream_write (surface->output, alpha, alpha_size);
status = _cairo_pdf_surface_close_stream (surface);
@@ -2339,25 +2428,33 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
return status;
}
-/* Emit image data into the given surface, providing a resource that
- * can be used to reference the data in image_ret. */
-static cairo_status_t
-_cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
- cairo_image_surface_t *image_surf,
- cairo_pdf_resource_t *image_res,
- cairo_filter_t filter,
- cairo_bool_t stencil_mask)
+/**
+ * _cairo_pdf_surface_emit_image:
+ * @surface: the pdf surface
+ * @image_surf: The image to write
+ * @surface_entry: Contains image resource, smask resource, interpolate and stencil mask parameters.
+ *
+ * Emit an image stream using the @image_res resource and write out
+ * the image data from @image_surf. If @smask_res is not null, @smask_res will
+ * be specified as the smask for the image. Otherwise emit the an smask if
+ * the image is requires one.
+ **/
+static cairo_int_status_t
+_cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
+ cairo_image_surface_t *image_surf,
+ cairo_pdf_source_surface_entry_t *surface_entry)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
char *data;
unsigned long data_size;
uint32_t *pixel;
int i, x, y, bit;
cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
cairo_bool_t need_smask;
- const char *interpolate = "true";
cairo_image_color_t color;
cairo_image_surface_t *image;
+ cairo_image_transparency_t transparency;
+ char smask_buf[30];
image = image_surf;
if (image->format != CAIRO_FORMAT_RGB24 &&
@@ -2386,26 +2483,19 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
goto CLEANUP;
}
- switch (filter) {
- 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 (surface_entry->smask || surface_entry->stencil_mask) {
+ return _cairo_pdf_surface_emit_smask (surface, image,
+ surface_entry->stencil_mask,
+ surface_entry->interpolate,
+ &surface_entry->surface_res);
}
- if (stencil_mask)
- return _cairo_pdf_surface_emit_smask (surface, image, stencil_mask, interpolate, image_res);
-
color = _cairo_image_analyze_color (image);
switch (color) {
- case CAIRO_IMAGE_IS_COLOR:
+ default:
case CAIRO_IMAGE_UNKNOWN_COLOR:
+ ASSERT_NOT_REACHED;
+ case CAIRO_IMAGE_IS_COLOR:
data_size = image->height * image->width * 3;
data = _cairo_malloc_abc (image->width, image->height, 3);
break;
@@ -2484,46 +2574,53 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
i++;
}
- need_smask = FALSE;
- if (image->format == CAIRO_FORMAT_ARGB32 ||
- image->format == CAIRO_FORMAT_A8 ||
- image->format == CAIRO_FORMAT_A1) {
- status = _cairo_pdf_surface_emit_smask (surface, image, FALSE, interpolate, &smask);
- if (unlikely (status))
- goto CLEANUP_RGB;
+ if (surface_entry->smask_res.id != 0) {
+ need_smask = TRUE;
+ smask = surface_entry->smask_res;
+ } else {
+ need_smask = FALSE;
+ if (image->format == CAIRO_FORMAT_ARGB32 ||
+ image->format == CAIRO_FORMAT_A8 ||
+ image->format == CAIRO_FORMAT_A1)
+ {
+ transparency = _cairo_image_analyze_transparency (image);
+ if (transparency != CAIRO_IMAGE_IS_OPAQUE) {
+ need_smask = TRUE;
+ smask = _cairo_pdf_surface_new_object (surface);
+ if (smask.id == 0) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto CLEANUP_RGB;
+ }
- if (smask.id)
- need_smask = TRUE;
+ status = _cairo_pdf_surface_emit_smask (surface, image, FALSE, surface_entry->interpolate, &smask);
+ if (unlikely (status))
+ goto CLEANUP_RGB;
+ }
+ }
}
-#define IMAGE_DICTIONARY " /Type /XObject\n" \
- " /Subtype /Image\n" \
- " /Width %d\n" \
- " /Height %d\n" \
- " /ColorSpace %s\n" \
- " /Interpolate %s\n" \
- " /BitsPerComponent %d\n"
-
if (need_smask)
- status = _cairo_pdf_surface_open_stream (surface,
- image_res,
- TRUE,
- IMAGE_DICTIONARY
- " /SMask %d 0 R\n",
- image->width, image->height,
- color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray",
- interpolate,
- color == CAIRO_IMAGE_IS_MONOCHROME? 1 : 8,
- smask.id);
+ snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", smask.id);
else
- status = _cairo_pdf_surface_open_stream (surface,
- image_res,
- TRUE,
- IMAGE_DICTIONARY,
- image->width, image->height,
- color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray",
- interpolate,
- color == CAIRO_IMAGE_IS_MONOCHROME? 1 : 8);
+ smask_buf[0] = 0;
+
+ status = _cairo_pdf_surface_open_stream (surface,
+ &surface_entry->surface_res,
+ TRUE,
+ " /Type /XObject\n"
+ " /Subtype /Image\n"
+ " /Width %d\n"
+ " /Height %d\n"
+ " /ColorSpace %s\n"
+ " /Interpolate %s\n"
+ " /BitsPerComponent %d\n"
+ "%s",
+ image->width,
+ image->height,
+ color == CAIRO_IMAGE_IS_COLOR ? "/DeviceRGB" : "/DeviceGray",
+ surface_entry->interpolate ? "true" : "false",
+ color == CAIRO_IMAGE_IS_MONOCHROME? 1 : 8,
+ smask_buf);
if (unlikely (status))
goto CLEANUP_RGB;
@@ -2542,14 +2639,165 @@ CLEANUP:
}
static cairo_int_status_t
-_cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface,
- cairo_surface_t *source,
- cairo_pdf_resource_t res)
+_cairo_pdf_surface_lookup_jbig2_global (cairo_pdf_surface_t *surface,
+ const unsigned char *global_id,
+ unsigned long global_id_length,
+ cairo_pdf_jbig2_global_t **entry)
{
- cairo_status_t status;
+ cairo_pdf_jbig2_global_t global;
+ int size, i;
+ cairo_int_status_t status;
+
+ size = _cairo_array_num_elements (&surface->jbig2_global);
+ for (i = 0; i < size; i++) {
+ *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, i);
+ if ((*entry)->id && global_id && (*entry)->id_length == global_id_length
+ && memcmp((*entry)->id, global_id, global_id_length) == 0) {
+ return CAIRO_STATUS_SUCCESS;
+ }
+ }
+
+ global.id = malloc(global_id_length);
+ if (unlikely (global.id == NULL)) {
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ memcpy (global.id, global_id, global_id_length);
+ global.id_length = global_id_length;
+ global.res = _cairo_pdf_surface_new_object (surface);
+ if (global.res.id == 0) {
+ free(global.id);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ global.emitted = FALSE;
+ status = _cairo_array_append (&surface->jbig2_global, &global);
+ if (unlikely(status))
+ return status;
+
+ size = _cairo_array_num_elements (&surface->jbig2_global);
+ *entry = (cairo_pdf_jbig2_global_t *) _cairo_array_index (&surface->jbig2_global, size - 1);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+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_int_status_t status;
const unsigned char *mime_data;
unsigned long mime_data_length;
cairo_image_info_t info;
+ const unsigned char *global_id;
+ unsigned long global_id_length;
+ const unsigned char *global_data;
+ unsigned long global_data_length;
+ cairo_pdf_jbig2_global_t *global_entry = NULL; /* hide compiler warning */
+ char smask_buf[30];
+ char decode_parms_buf[100];
+
+ cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2,
+ &mime_data, &mime_data_length);
+ if (mime_data == NULL)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ status = _cairo_image_info_get_jbig2_info (&info, mime_data, mime_data_length);
+ if (status)
+ return status;
+
+ cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
+ &global_id, &global_id_length);
+ if (global_id && global_id_length > 0) {
+ status = _cairo_pdf_surface_lookup_jbig2_global (surface, global_id, global_id_length, &global_entry);
+ if (unlikely(status))
+ return status;
+
+ if (!global_entry->emitted) {
+ cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JBIG2_GLOBAL,
+ &global_data, &global_data_length);
+ if (global_data) {
+ status = _cairo_pdf_surface_open_stream (surface, &global_entry->res, FALSE, NULL);
+ if (unlikely(status))
+ return status;
+
+ _cairo_output_stream_write (surface->output, global_data, global_data_length);
+ status = _cairo_pdf_surface_close_stream (surface);
+ if (unlikely(status))
+ return status;
+
+ global_entry->emitted = TRUE;
+ }
+ }
+
+ snprintf(decode_parms_buf, sizeof(decode_parms_buf),
+ " /DecodeParms << /JBIG2Globals %d 0 R >>\n", global_entry->res.id);
+ } else {
+ decode_parms_buf[0] = 0;
+ }
+
+ if (surface_entry->smask_res.id)
+ snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id);
+ else
+ smask_buf[0] = 0;
+
+ 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 /JPXDecode\n"
+ "%s",
+ info.width,
+ info.height,
+ surface_entry->interpolate ? "true" : "false",
+ decode_parms_buf);
+ } else {
+ 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"
+ "%s"
+ " /Filter /JBIG2Decode\n"
+ "%s",
+ info.width,
+ info.height,
+ surface_entry->interpolate ? "true" : "false",
+ smask_buf,
+ decode_parms_buf);
+ }
+ if (unlikely(status))
+ return status;
+
+ _cairo_output_stream_write (surface->output, mime_data, mime_data_length);
+ status = _cairo_pdf_surface_close_stream (surface);
+
+ return status;
+}
+
+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_int_status_t status;
+ const unsigned char *mime_data;
+ unsigned long mime_data_length;
+ cairo_image_info_t info;
+ char smask_buf[30];
if (surface->pdf_version < CAIRO_PDF_VERSION_1_5)
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -2563,16 +2811,49 @@ _cairo_pdf_surface_emit_jpx_image (cairo_pdf_surface_t *surface,
if (status)
return status;
- status = _cairo_pdf_surface_open_stream (surface,
- &res,
- FALSE,
- " /Type /XObject\n"
- " /Subtype /Image\n"
- " /Width %d\n"
- " /Height %d\n"
- " /Filter /JPXDecode\n",
- info.width,
- info.height);
+ if ((surface_entry->smask || surface_entry->stencil_mask) && info.num_components != 1)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if ((surface_entry->stencil_mask) && info.bits_per_component != 1)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (surface_entry->smask_res.id)
+ snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id);
+ else
+ smask_buf[0] = 0;
+
+ 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 /JPXDecode\n",
+ info.width,
+ info.height,
+ surface_entry->interpolate ? "true" : "false");
+ } else {
+ status = _cairo_pdf_surface_open_stream (surface,
+ &surface_entry->surface_res,
+ FALSE,
+ " /Type /XObject\n"
+ " /Subtype /Image\n"
+ " /Width %d\n"
+ " /Height %d\n"
+ " /Interpolate %s\n"
+ "%s"
+ " /Filter /JPXDecode\n",
+ info.width,
+ info.height,
+ surface_entry->interpolate ? "true" : "false",
+ smask_buf);
+ }
if (status)
return status;
@@ -2583,15 +2864,16 @@ _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_resource_t res)
+_cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
+ cairo_surface_t *source,
+ cairo_pdf_source_surface_entry_t *surface_entry)
{
- cairo_status_t status;
+ cairo_int_status_t status;
const unsigned char *mime_data;
unsigned long mime_data_length;
cairo_image_info_t info;
const char *colorspace;
+ char smask_buf[30];
cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
&mime_data, &mime_data_length);
@@ -2604,6 +2886,12 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
if (unlikely (status))
return status;
+ if ((surface_entry->smask || surface_entry->stencil_mask) && info.num_components != 1)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if ((surface_entry->stencil_mask) && info.bits_per_component != 1)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
switch (info.num_components) {
case 1:
colorspace = "/DeviceGray";
@@ -2618,20 +2906,47 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
- status = _cairo_pdf_surface_open_stream (surface,
- &res,
- FALSE,
- " /Type /XObject\n"
- " /Subtype /Image\n"
- " /Width %d\n"
- " /Height %d\n"
- " /ColorSpace %s\n"
- " /BitsPerComponent %d\n"
- " /Filter /DCTDecode\n",
- info.width,
- info.height,
- colorspace,
- info.bits_per_component);
+ if (surface_entry->smask_res.id)
+ snprintf(smask_buf, sizeof(smask_buf), " /SMask %d 0 R\n", surface_entry->smask_res.id);
+ else
+ smask_buf[0] = 0;
+
+ 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 /DCTDecode\n",
+ info.width,
+ info.height,
+ surface_entry->interpolate ? "true" : "false");
+ } else {
+ 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 %s\n"
+ " /Interpolate %s\n"
+ " /BitsPerComponent %d\n"
+ "%s"
+ " /Filter /DCTDecode\n",
+ info.width,
+ info.height,
+ colorspace,
+ surface_entry->interpolate ? "true" : "false",
+ info.bits_per_component,
+ smask_buf);
+ }
if (unlikely (status))
return status;
@@ -2641,7 +2956,7 @@ _cairo_pdf_surface_emit_jpeg_image (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
cairo_pdf_source_surface_t *source)
{
@@ -2650,6 +2965,20 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
cairo_int_status_t status;
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;
+
+ status = _cairo_pdf_surface_emit_jpx_image (surface, source->surface, source->hash_entry);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
+ status = _cairo_pdf_surface_emit_jpeg_image (surface, source->surface, source->hash_entry);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+ }
+
+ 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,
@@ -2658,22 +2987,10 @@ _cairo_pdf_surface_emit_image_surface (cairo_pdf_surface_t *surface,
if (unlikely (status))
return status;
- if (!source->hash_entry->stencil_mask) {
- status = _cairo_pdf_surface_emit_jpx_image (surface, &image->base, source->hash_entry->surface_res);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- goto release_source;
+ status = _cairo_pdf_surface_emit_image (surface,
+ image,
+ source->hash_entry);
- status = _cairo_pdf_surface_emit_jpeg_image (surface, &image->base, source->hash_entry->surface_res);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- goto release_source;
- }
-
- status = _cairo_pdf_surface_emit_image (surface, image,
- &source->hash_entry->surface_res,
- source->hash_entry->interpolate,
- source->hash_entry->stencil_mask);
-
-release_source:
if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
_cairo_surface_release_source_image (source->surface, image, image_extra);
else
@@ -2683,7 +3000,7 @@ release_source:
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
cairo_pdf_source_surface_t *pdf_source)
{
@@ -2699,6 +3016,8 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
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;
@@ -2718,6 +3037,9 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
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_paginated_mode = surface->paginated_mode;
@@ -2734,7 +3056,16 @@ _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);
- status = _cairo_pdf_surface_open_content_stream (surface, &bbox, &pdf_source->hash_entry->surface_res, TRUE);
+
+ /* 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.
+ */
+ transparency_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);
if (unlikely (status))
goto err;
@@ -2772,7 +3103,7 @@ err:
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
cairo_pdf_source_surface_t *src_surface)
{
@@ -2783,12 +3114,12 @@ _cairo_pdf_surface_emit_surface (cairo_pdf_surface_t *surface,
return _cairo_pdf_surface_emit_image_surface (surface, src_surface);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_pdf_pattern_t *pdf_pattern)
{
cairo_pattern_t *pattern = pdf_pattern->pattern;
- cairo_status_t status;
+ 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);
@@ -2818,9 +3149,12 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_add_source_surface (surface,
NULL,
pattern,
+ pdf_pattern->operator,
pattern->filter,
FALSE,
+ FALSE,
&pdf_pattern->extents,
+ NULL,
&pattern_resource,
&pattern_width,
&pattern_height,
@@ -2911,7 +3245,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
cairo_p2d = pattern->matrix;
status = cairo_matrix_invert (&cairo_p2d);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
- assert (status == CAIRO_STATUS_SUCCESS);
+ 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);
@@ -2989,7 +3323,7 @@ typedef struct _cairo_pdf_color_stop {
cairo_pdf_resource_t resource;
} cairo_pdf_color_stop_t;
-static cairo_status_t
+static cairo_int_status_t
cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
cairo_pdf_color_stop_t *stop1,
cairo_pdf_color_stop_t *stop2,
@@ -2998,7 +3332,7 @@ cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
int num_elems, i;
cairo_pdf_rgb_linear_function_t elem;
cairo_pdf_resource_t res;
- cairo_status_t status;
+ cairo_int_status_t status;
num_elems = _cairo_array_num_elements (&surface->rgb_linear_functions);
for (i = 0; i < num_elems; i++) {
@@ -3042,7 +3376,7 @@ cairo_pdf_surface_emit_rgb_linear_function (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
cairo_pdf_color_stop_t *stop1,
cairo_pdf_color_stop_t *stop2,
@@ -3051,7 +3385,7 @@ cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
int num_elems, i;
cairo_pdf_alpha_linear_function_t elem;
cairo_pdf_resource_t res;
- cairo_status_t status;
+ cairo_int_status_t status;
num_elems = _cairo_array_num_elements (&surface->alpha_linear_functions);
for (i = 0; i < num_elems; i++) {
@@ -3091,7 +3425,7 @@ cairo_pdf_surface_emit_alpha_linear_function (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
unsigned int n_stops,
cairo_pdf_color_stop_t *stops,
@@ -3100,7 +3434,7 @@ _cairo_pdf_surface_emit_stitched_colorgradient (cairo_pdf_surface_t *surface,
{
cairo_pdf_resource_t res;
unsigned int i;
- cairo_status_t status;
+ cairo_int_status_t status;
/* emit linear gradients between pairs of subsequent stops... */
for (i = 0; i < n_stops-1; i++) {
@@ -3182,7 +3516,7 @@ calc_gradient_color (cairo_pdf_color_stop_t *new_stop,
#define COLOR_STOP_EPSILON 1e-6
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
cairo_gradient_pattern_t *pattern,
cairo_pdf_resource_t *color_function,
@@ -3192,7 +3526,7 @@ _cairo_pdf_surface_emit_pattern_stops (cairo_pdf_surface_t *surface,
unsigned int n_stops;
unsigned int i;
cairo_bool_t emit_alpha = FALSE;
- cairo_status_t status;
+ cairo_int_status_t status;
color_function->id = 0;
alpha_function->id = 0;
@@ -3326,7 +3660,7 @@ BAIL:
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
cairo_gradient_pattern_t *pattern,
cairo_pdf_resource_t *function,
@@ -3387,14 +3721,14 @@ _cairo_pdf_surface_emit_repeating_function (cairo_pdf_surface_t *surface,
return _cairo_output_stream_get_status (surface->output);
}
-static cairo_status_t
+static cairo_int_status_t
cairo_pdf_surface_emit_transparency_group (cairo_pdf_surface_t *surface,
cairo_pdf_pattern_t *pdf_pattern,
cairo_pdf_resource_t gstate_resource,
cairo_pdf_resource_t gradient_mask)
{
cairo_pdf_resource_t smask_resource;
- cairo_status_t status;
+ cairo_int_status_t status;
char buf[100];
double x1, y1, x2, y2;
@@ -3531,11 +3865,11 @@ _cairo_pdf_surface_output_gradient (cairo_pdf_surface_t *surface,
_cairo_output_stream_printf (surface->output,
"<< /Type /Pattern\n"
" /PatternType 2\n"
- " /Matrix [ %f %f %f %f %f %f ]\n"
- " /Shading\n",
- pat_to_pdf->xx, pat_to_pdf->yx,
- pat_to_pdf->xy, pat_to_pdf->yy,
- pat_to_pdf->x0, pat_to_pdf->y0);
+ " /Matrix [ ");
+ _cairo_output_stream_print_matrix (surface->output, pat_to_pdf);
+ _cairo_output_stream_printf (surface->output,
+ " ]\n"
+ " /Shading\n");
}
if (pdf_pattern->pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
@@ -3577,12 +3911,14 @@ _cairo_pdf_surface_output_gradient (cairo_pdf_surface_t *surface,
if (!pdf_pattern->is_shading) {
_cairo_output_stream_printf (surface->output,
- ">>\n"
- "endobj\n");
+ ">>\n");
}
+
+ _cairo_output_stream_printf (surface->output,
+ "endobj\n");
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface,
cairo_pdf_pattern_t *pdf_pattern)
{
@@ -3591,7 +3927,7 @@ _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface,
cairo_matrix_t pat_to_pdf;
cairo_circle_double_t start, end;
double domain[2];
- cairo_status_t status;
+ cairo_int_status_t status;
assert (pattern->n_stops != 0);
@@ -3605,7 +3941,7 @@ _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface,
pat_to_pdf = pattern->base.matrix;
status = cairo_matrix_invert (&pat_to_pdf);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
- assert (status == CAIRO_STATUS_SUCCESS);
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
if (pattern->base.extend == CAIRO_EXTEND_REPEAT ||
@@ -3728,12 +4064,12 @@ _cairo_pdf_surface_emit_gradient (cairo_pdf_surface_t *surface,
return _cairo_output_stream_get_status (surface->output);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
cairo_pdf_pattern_t *pdf_pattern)
{
cairo_matrix_t pat_to_pdf;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_pattern_t *pattern = pdf_pattern->pattern;
cairo_pdf_shading_t shading;
int i;
@@ -3742,7 +4078,7 @@ _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
pat_to_pdf = pattern->matrix;
status = cairo_matrix_invert (&pat_to_pdf);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
- assert (status == CAIRO_STATUS_SUCCESS);
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
@@ -3791,14 +4127,14 @@ _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
"%d 0 obj\n"
"<< /Type /Pattern\n"
" /PatternType 2\n"
- " /Matrix [ %f %f %f %f %f %f ]\n"
+ " /Matrix [ ",
+ pdf_pattern->pattern_res.id);
+ _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
+ _cairo_output_stream_printf (surface->output,
+ " ]\n"
" /Shading %d 0 R\n"
">>\n"
"endobj\n",
- pdf_pattern->pattern_res.id,
- pat_to_pdf.xx, pat_to_pdf.yx,
- pat_to_pdf.xy, pat_to_pdf.yy,
- pat_to_pdf.x0, pat_to_pdf.y0,
res.id);
if (pdf_pattern->gstate_res.id != 0) {
@@ -3852,14 +4188,14 @@ _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
"%d 0 obj\n"
"<< /Type /Pattern\n"
" /PatternType 2\n"
- " /Matrix [ %f %f %f %f %f %f ]\n"
+ " /Matrix [ ",
+ mask_resource.id);
+ _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
+ _cairo_output_stream_printf (surface->output,
+ " ]\n"
" /Shading %d 0 R\n"
">>\n"
"endobj\n",
- mask_resource.id,
- pat_to_pdf.xx, pat_to_pdf.yx,
- pat_to_pdf.xy, pat_to_pdf.yy,
- pat_to_pdf.x0, pat_to_pdf.y0,
res.id);
status = cairo_pdf_surface_emit_transparency_group (surface,
@@ -3873,11 +4209,11 @@ _cairo_pdf_surface_emit_mesh_pattern (cairo_pdf_surface_t *surface,
return _cairo_output_stream_get_status (surface->output);
}
-static cairo_status_t
+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_status_t status;
+ cairo_int_status_t status;
old_width = surface->width;
old_height = surface->height;
@@ -3918,16 +4254,18 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_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,
+ 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_status_t status;
+ cairo_int_status_t status;
int alpha;
cairo_rectangle_int_t extents2;
double x_offset;
@@ -3949,9 +4287,12 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_add_source_surface (surface,
NULL,
source,
+ op,
source->filter,
stencil_mask,
+ FALSE,
extents,
+ smask_res,
&surface_res,
&width,
&height,
@@ -3965,7 +4306,7 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
cairo_p2d = source->matrix;
status = cairo_matrix_invert (&cairo_p2d);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
- assert (status == CAIRO_STATUS_SUCCESS);
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
pdf_p2d = surface->cairo_to_pdf;
cairo_matrix_multiply (&pdf_p2d, &cairo_p2d, &pdf_p2d);
@@ -3983,11 +4324,8 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
return status;
if (! _cairo_matrix_is_identity (&pdf_p2d)) {
- _cairo_output_stream_printf (surface->output,
- "%f %f %f %f %f %f cm\n",
- pdf_p2d.xx, pdf_p2d.yx,
- pdf_p2d.xy, pdf_p2d.yy,
- pdf_p2d.x0, pdf_p2d.y0);
+ _cairo_output_stream_print_matrix (surface->output, &pdf_p2d);
+ _cairo_output_stream_printf (surface->output, " cm\n");
}
status = _cairo_pdf_surface_add_alpha (surface, 1.0, &alpha);
@@ -4008,28 +4346,29 @@ _cairo_pdf_surface_paint_surface_pattern (cairo_pdf_surface_t *surface,
return _cairo_pdf_surface_add_xobject (surface, surface_res);
}
-static cairo_status_t
+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)
{
cairo_pdf_resource_t shading_res, gstate_res;
cairo_matrix_t pat_to_pdf;
- cairo_status_t status;
+ cairo_int_status_t status;
int alpha;
status = _cairo_pdf_surface_add_pdf_shading (surface, source,
- extents,
+ op, extents,
&shading_res, &gstate_res);
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_SUCCESS;
if (unlikely (status))
return status;
pat_to_pdf = source->matrix;
status = cairo_matrix_invert (&pat_to_pdf);
/* cairo_pattern_set_matrix ensures the matrix is invertible */
- assert (status == CAIRO_STATUS_SUCCESS);
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
cairo_matrix_multiply (&pat_to_pdf, &pat_to_pdf, &surface->cairo_to_pdf);
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
@@ -4037,11 +4376,8 @@ _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t *surface,
return status;
if (! _cairo_matrix_is_identity (&pat_to_pdf)) {
- _cairo_output_stream_printf (surface->output,
- "%f %f %f %f %f %f cm\n",
- pat_to_pdf.xx, pat_to_pdf.yx,
- pat_to_pdf.xy, pat_to_pdf.yy,
- pat_to_pdf.x0, pat_to_pdf.y0);
+ _cairo_output_stream_print_matrix (surface->output, &pat_to_pdf);
+ _cairo_output_stream_printf (surface->output, " cm\n");
}
status = _cairo_pdf_surface_add_shading (surface, shading_res);
@@ -4071,8 +4407,9 @@ _cairo_pdf_surface_paint_gradient (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_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,
cairo_bool_t mask)
@@ -4081,13 +4418,16 @@ _cairo_pdf_surface_paint_pattern (cairo_pdf_surface_t *surface,
case CAIRO_PATTERN_TYPE_SURFACE:
case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
return _cairo_pdf_surface_paint_surface_pattern (surface,
+ op,
source,
extents,
+ NULL,
mask);
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
case CAIRO_PATTERN_TYPE_MESH:
return _cairo_pdf_surface_paint_gradient (surface,
+ op,
source,
extents);
@@ -4123,11 +4463,11 @@ _can_paint_pattern (const cairo_pattern_t *pattern)
}
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
cairo_operator_t op)
{
- cairo_status_t status;
+ cairo_int_status_t status;
if (op == surface->current_operator)
return CAIRO_STATUS_SUCCESS;
@@ -4144,13 +4484,13 @@ _cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_select_pattern (cairo_pdf_surface_t *surface,
const cairo_pattern_t *pattern,
cairo_pdf_resource_t pattern_res,
cairo_bool_t is_stroke)
{
- cairo_status_t status;
+ cairo_int_status_t status;
int alpha;
const cairo_color_t *solid_color = NULL;
@@ -4366,14 +4706,14 @@ _cairo_pdf_surface_write_pages (cairo_pdf_surface_t *surface)
"endobj\n");
}
-static cairo_status_t
+static cairo_int_status_t
_utf8_to_pdf_string (const char *utf8, char **str_out)
{
int i;
int len;
cairo_bool_t ascii;
char *str;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
ascii = TRUE;
len = strlen (utf8);
@@ -4421,13 +4761,13 @@ _utf8_to_pdf_string (const char *utf8, char **str_out)
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_unicode_for_glyph (cairo_pdf_surface_t *surface,
const char *utf8)
{
uint16_t *utf16 = NULL;
int utf16_len = 0;
- cairo_status_t status;
+ cairo_int_status_t status;
int i;
if (utf8 && *utf8) {
@@ -4651,7 +4991,7 @@ _cairo_pdf_surface_emit_to_unicode_stream (cairo_pdf_surface_t *surface,
#define PDF_UNITS_PER_EM 1000
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset,
cairo_cff_subset_t *subset)
@@ -4660,7 +5000,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t subset_resource, to_unicode_stream;
cairo_pdf_font_t font;
unsigned int i, last_glyph;
- cairo_status_t status;
+ cairo_int_status_t status;
char tag[10];
_create_font_subset_tag (font_subset, subset->ps_name, tag);
@@ -4690,7 +5030,7 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
font_subset,
&to_unicode_stream);
- if (_cairo_status_is_error (status))
+ if (_cairo_int_status_is_error (status))
return status;
descriptor = _cairo_pdf_surface_new_object (surface);
@@ -4848,11 +5188,11 @@ _cairo_pdf_surface_emit_cff_font (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_cff_subset_t subset;
char name[64];
@@ -4869,11 +5209,11 @@ _cairo_pdf_surface_emit_cff_font_subset (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_cff_subset_t subset;
char name[64];
@@ -4895,14 +5235,14 @@ _cairo_pdf_surface_emit_cff_fallback_font (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset,
cairo_type1_subset_t *subset)
{
cairo_pdf_resource_t stream, descriptor, subset_resource, to_unicode_stream;
cairo_pdf_font_t font;
- cairo_status_t status;
+ cairo_int_status_t status;
unsigned long length;
unsigned int i, last_glyph;
char tag[10];
@@ -4937,7 +5277,7 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
font_subset,
&to_unicode_stream);
- if (_cairo_status_is_error (status))
+ if (_cairo_int_status_is_error (status))
return status;
last_glyph = font_subset->num_glyphs - 1;
@@ -5037,11 +5377,11 @@ _cairo_pdf_surface_emit_type1_font (cairo_pdf_surface_t *surface,
return _cairo_array_append (&surface->fonts, &font);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_type1_subset_t subset;
char name[64];
@@ -5061,11 +5401,11 @@ _cairo_pdf_surface_emit_type1_font_subset (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_type1_subset_t subset;
char name[64];
@@ -5085,13 +5425,13 @@ _cairo_pdf_surface_emit_type1_fallback_font (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
cairo_pdf_resource_t stream, descriptor, cidfont_dict;
cairo_pdf_resource_t subset_resource, to_unicode_stream;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_pdf_font_t font;
cairo_truetype_subset_t subset;
unsigned int i, last_glyph;
@@ -5131,7 +5471,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
font_subset,
&to_unicode_stream);
- if (_cairo_status_is_error (status)) {
+ if (_cairo_int_status_is_error (status)) {
_cairo_truetype_subset_fini (&subset);
return status;
}
@@ -5298,7 +5638,7 @@ _cairo_pdf_surface_emit_truetype_font_subset (cairo_pdf_surface_t *surface,
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
cairo_output_stream_t *stream)
{
@@ -5343,8 +5683,8 @@ _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_su
void *closure)
{
cairo_pdf_surface_t *surface = closure;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_status_t status2;
+ cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
+ cairo_int_status_t status2;
unsigned int i;
cairo_surface_t *type3_surface;
cairo_output_stream_t *null_stream;
@@ -5353,7 +5693,8 @@ _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_su
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
null_stream,
_cairo_pdf_emit_imagemask,
- surface->font_subsets);
+ surface->font_subsets,
+ FALSE);
if (unlikely (type3_surface->status)) {
status2 = _cairo_output_stream_destroy (null_stream);
status = type3_surface->status;
@@ -5374,7 +5715,7 @@ _cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_su
cairo_surface_destroy (type3_surface);
status2 = _cairo_output_stream_destroy (null_stream);
- if (status == CAIRO_STATUS_SUCCESS)
+ if (status == CAIRO_INT_STATUS_SUCCESS)
status = status2;
return status;
@@ -5384,7 +5725,7 @@ static cairo_int_status_t
_cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
cairo_scaled_font_subset_t *font_subset)
{
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_pdf_resource_t *glyphs, encoding, char_procs, subset_resource, to_unicode_stream;
cairo_pdf_font_t font;
double *widths;
@@ -5416,7 +5757,8 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_pdf_emit_imagemask,
- surface->font_subsets);
+ surface->font_subsets,
+ FALSE);
if (unlikely (type3_surface->status)) {
free (glyphs);
free (widths);
@@ -5515,7 +5857,7 @@ _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t *surface,
status = _cairo_pdf_surface_emit_to_unicode_stream (surface,
font_subset,
&to_unicode_stream);
- if (_cairo_status_is_error (status)) {
+ if (_cairo_int_status_is_error (status)) {
free (widths);
return status;
}
@@ -5613,10 +5955,10 @@ _cairo_pdf_surface_emit_scaled_font_subset (cairo_scaled_font_subset_t *font_sub
return CAIRO_INT_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
{
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
_cairo_pdf_surface_analyze_user_font_subset,
@@ -5698,7 +6040,7 @@ _cairo_pdf_surface_write_xref (cairo_pdf_surface_t *surface)
return offset;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
cairo_pdf_smask_group_t *group)
{
@@ -5706,7 +6048,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
cairo_pdf_resource_t smask;
cairo_pdf_smask_group_t *smask_group;
cairo_pdf_resource_t pattern_res, gstate_res;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_box_double_t bbox;
/* Create mask group */
@@ -5718,6 +6060,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
if (_can_paint_pattern (group->mask)) {
_cairo_output_stream_printf (surface->output, "q\n");
status = _cairo_pdf_surface_paint_pattern (surface,
+ CAIRO_OPERATOR_OVER,
group->mask,
&group->extents,
FALSE);
@@ -5728,7 +6071,9 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
} else {
pattern_res.id = 0;
gstate_res.id = 0;
- status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask, NULL,
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, group->mask,
+ CAIRO_OPERATOR_OVER,
+ NULL,
&pattern_res, &gstate_res);
if (unlikely (status))
return status;
@@ -5791,6 +6136,7 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
if (_can_paint_pattern (group->source)) {
_cairo_output_stream_printf (surface->output, "q\n");
status = _cairo_pdf_surface_paint_pattern (surface,
+ CAIRO_OPERATOR_OVER,
group->source,
&group->extents,
FALSE);
@@ -5801,7 +6147,9 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
} else {
pattern_res.id = 0;
gstate_res.id = 0;
- status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source, NULL,
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, group->source,
+ CAIRO_OPERATOR_OVER,
+ NULL,
&pattern_res, &gstate_res);
if (unlikely (status))
return status;
@@ -5886,12 +6234,12 @@ _cairo_pdf_surface_write_mask_group (cairo_pdf_surface_t *surface,
return _cairo_output_stream_get_status (surface->output);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_write_smask_group (cairo_pdf_surface_t *surface,
cairo_pdf_smask_group_t *group)
{
double old_width, old_height;
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_box_double_t bbox;
old_width = surface->width;
@@ -5965,14 +6313,14 @@ RESTORE_SIZE:
return status;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface)
{
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;
- cairo_status_t status;
+ cairo_int_status_t status;
/* Writing out PDF_MASK groups will cause additional smask groups
* to be appended to surface->smask_groups. Additional patterns
@@ -6013,11 +6361,11 @@ _cairo_pdf_surface_write_patterns_and_smask_groups (cairo_pdf_surface_t *surface
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
{
cairo_pdf_resource_t page, knockout, res;
- cairo_status_t status;
+ cairo_int_status_t status;
unsigned int i, len;
_cairo_pdf_group_resources_clear (&surface->resources);
@@ -6056,7 +6404,7 @@ _cairo_pdf_surface_write_page (cairo_pdf_surface_t *surface)
return status;
_cairo_pdf_group_resources_clear (&surface->resources);
- status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE);
+ status = _cairo_pdf_surface_open_content_stream (surface, NULL, NULL, FALSE, FALSE);
if (unlikely (status))
return status;
@@ -6329,7 +6677,7 @@ static cairo_int_status_t
_cairo_pdf_surface_start_fallback (cairo_pdf_surface_t *surface)
{
cairo_box_double_t bbox;
- cairo_status_t status;
+ cairo_int_status_t status;
status = _cairo_pdf_surface_close_content_stream (surface);
if (unlikely (status))
@@ -6344,17 +6692,194 @@ _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);
+ return _cairo_pdf_surface_open_content_stream (surface, &bbox, NULL, TRUE, TRUE);
+}
+
+/* If source is an opaque image and mask is an image and both images
+ * have the same bounding box we can emit them as a image/smask pair.
+ */
+static cairo_int_status_t
+_cairo_pdf_surface_emit_combined_smask (cairo_pdf_surface_t *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ const cairo_pattern_t *mask,
+ const cairo_rectangle_int_t *extents)
+{
+ cairo_int_status_t status;
+ 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;
+ double mask_x_offset, mask_y_offset;
+ double src_x1, src_y1, src_x2, src_y2;
+ 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;
+
+ /* Check that source and mask are images */
+
+ if (!((source->type == CAIRO_PATTERN_TYPE_SURFACE || source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) &&
+ (mask->type == CAIRO_PATTERN_TYPE_SURFACE || mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+ ((cairo_surface_pattern_t *) source)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
+ {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ if (mask->type == CAIRO_PATTERN_TYPE_SURFACE &&
+ ((cairo_surface_pattern_t *) mask)->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
+ {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ if (source->extend != CAIRO_EXTEND_NONE || mask->extend != CAIRO_EXTEND_NONE)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ /* Check that source is opaque and get image sizes */
+
+ status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, source,
+ &image, &image_extra);
+ if (unlikely (status))
+ return status;
+
+ if (image->base.status)
+ return image->base.status;
+
+ src_width = image->width;
+ src_height = image->height;
+ if (source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
+ cairo_surface_get_device_offset (&image->base, &src_x_offset, &src_y_offset);
+ } else {
+ src_x_offset = 0;
+ src_y_offset = 0;
+ }
+
+ transparency = _cairo_image_analyze_transparency (image);
+ _cairo_pdf_surface_release_source_image_from_pattern (surface, source, image, image_extra);
+
+ if (transparency != CAIRO_IMAGE_IS_OPAQUE)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ status = _cairo_pdf_surface_acquire_source_image_from_pattern (surface, mask,
+ &image, &image_extra);
+ if (unlikely (status))
+ return status;
+
+ if (image->base.status)
+ return image->base.status;
+
+ mask_width = image->width;
+ mask_height = image->height;
+ if (mask->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
+ cairo_surface_get_device_offset (&image->base, &mask_x_offset, &mask_y_offset);
+ } else {
+ mask_x_offset = 0;
+ mask_y_offset = 0;
+ }
+
+ transparency = _cairo_image_analyze_transparency (image);
+ need_smask = transparency != CAIRO_IMAGE_IS_OPAQUE;
+
+ _cairo_pdf_surface_release_source_image_from_pattern (surface, mask, image, image_extra);
+
+ /* Check that both images have the same extents with a tolerance
+ * of half the smallest source pixel. */
+
+ p2u = source->matrix;
+ status = cairo_matrix_invert (&p2u);
+ /* cairo_pattern_set_matrix ensures the matrix is invertible */
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
+ src_x1 = 0;
+ src_y1 = 0;
+ src_x2 = src_width;
+ src_y2 = src_height;
+ cairo_matrix_transform_point (&p2u, &src_x1, &src_y1);
+ cairo_matrix_transform_point (&p2u, &src_x2, &src_y2);
+ src_radius = _cairo_matrix_transformed_circle_major_axis (&p2u, 0.5);
+
+ p2u = mask->matrix;
+ status = cairo_matrix_invert (&p2u);
+ /* cairo_pattern_set_matrix ensures the matrix is invertible */
+ assert (status == CAIRO_INT_STATUS_SUCCESS);
+ mask_x1 = 0;
+ mask_y1 = 0;
+ mask_x2 = mask_width;
+ mask_y2 = mask_height;
+ cairo_matrix_transform_point (&p2u, &mask_x1, &mask_y1);
+ cairo_matrix_transform_point (&p2u, &mask_x2, &mask_y2);
+ mask_radius = _cairo_matrix_transformed_circle_major_axis (&p2u, 0.5);
+
+ if (src_radius < mask_radius)
+ e = src_radius;
+ else
+ e = mask_radius;
+
+ if (fabs(src_x1 - mask_x1) > e ||
+ fabs(src_x2 - mask_x2) > e ||
+ fabs(src_y1 - mask_y1) > e ||
+ fabs(src_y2 - mask_y2) > e)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ /* Check both images have same device offset */
+ if (fabs(src_x_offset - mask_x_offset) > e ||
+ fabs(src_y_offset - mask_y_offset) > e)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (need_smask) {
+ status = _cairo_pdf_surface_add_source_surface (surface,
+ NULL,
+ mask,
+ op,
+ source->filter,
+ FALSE,
+ TRUE,
+ extents,
+ NULL,
+ &smask_res,
+ &mask_width,
+ &mask_height,
+ &mask_x_offset,
+ &mask_y_offset,
+ &extents2);
+ if (unlikely (status))
+ return status;
+ }
+
+ status = _cairo_pdf_operators_flush (&surface->pdf_operators);
+ if (unlikely (status))
+ return status;
+
+ _cairo_output_stream_printf (surface->output, "q\n");
+ status = _cairo_pdf_surface_paint_surface_pattern (surface, op, source, extents,
+ need_smask ? &smask_res : NULL,
+ FALSE);
+ if (unlikely (status))
+ return status;
+
+ _cairo_output_stream_printf (surface->output, "Q\n");
+
+ status = _cairo_output_stream_get_status (surface->output);
+
+
+ return status;
}
/* A PDF stencil mask is an A1 mask used with the current color */
static cairo_int_status_t
_cairo_pdf_surface_emit_stencil_mask (cairo_pdf_surface_t *surface,
+ cairo_operator_t op,
const cairo_pattern_t *source,
const cairo_pattern_t *mask,
const cairo_rectangle_int_t *extents)
{
- cairo_status_t status;
+ cairo_int_status_t status;
cairo_image_surface_t *image;
void *image_extra;
cairo_image_transparency_t transparency;
@@ -6396,7 +6921,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, mask, NULL, TRUE);
+ status = _cairo_pdf_surface_paint_surface_pattern (surface, op, mask, extents, NULL, TRUE);
if (unlikely (status))
return status;
@@ -6472,6 +6997,7 @@ _cairo_pdf_surface_paint (void *abstract_surface,
if (_can_paint_pattern (source)) {
_cairo_output_stream_printf (surface->output, "q\n");
status = _cairo_pdf_surface_paint_pattern (surface,
+ op,
source,
&extents.bounded,
FALSE);
@@ -6485,7 +7011,7 @@ _cairo_pdf_surface_paint (void *abstract_surface,
pattern_res.id = 0;
gstate_res.id = 0;
- status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
@@ -6567,7 +7093,7 @@ _cairo_pdf_surface_mask (void *abstract_surface,
return status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
- cairo_status_t source_status, mask_status;
+ cairo_int_status_t source_status, mask_status;
status = _cairo_pdf_surface_analyze_operation (surface, op, source, &extents.bounded);
if (_cairo_int_status_is_error (status))
@@ -6625,8 +7151,13 @@ _cairo_pdf_surface_mask (void *abstract_surface,
if (unlikely (status))
goto cleanup;
+ /* Check if we can combine source and mask into a smask image */
+ status = _cairo_pdf_surface_emit_combined_smask (surface, op, source, mask, &extents.bounded);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ goto cleanup;
+
/* Check if we can use a stencil mask */
- status = _cairo_pdf_surface_emit_stencil_mask (surface, source, mask, &extents.bounded);
+ status = _cairo_pdf_surface_emit_stencil_mask (surface, op, source, mask, &extents.bounded);
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto cleanup;
@@ -6743,7 +7274,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
pattern_res.id = 0;
gstate_res.id = 0;
- status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
@@ -6896,6 +7427,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
goto cleanup;
status = _cairo_pdf_surface_paint_pattern (surface,
+ op,
source,
&extents.bounded,
FALSE);
@@ -6909,7 +7441,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
pattern_res.id = 0;
gstate_res.id = 0;
- status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
@@ -7084,6 +7616,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
fill_pattern_res.id = 0;
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
+ fill_op,
&extents.bounded,
&fill_pattern_res,
&gstate_res);
@@ -7096,6 +7629,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
gstate_res.id = 0;
status = _cairo_pdf_surface_add_pdf_pattern (surface,
stroke_source,
+ stroke_op,
&extents.bounded,
&stroke_pattern_res,
&gstate_res);
@@ -7187,7 +7721,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
pattern_res.id = 0;
gstate_res.id = 0;
- status = _cairo_pdf_surface_add_pdf_pattern (surface, source,
+ status = _cairo_pdf_surface_add_pdf_pattern (surface, source, op,
&extents.bounded,
&pattern_res, &gstate_res);
if (unlikely (status))
diff --git a/src/cairo-pdf.h b/src/cairo-pdf.h
index 1bc8524f2..1bc8524f2 100755..100644
--- a/src/cairo-pdf.h
+++ b/src/cairo-pdf.h
diff --git a/src/cairo-pen.c b/src/cairo-pen.c
index 61be0e829..61be0e829 100755..100644
--- a/src/cairo-pen.c
+++ b/src/cairo-pen.c
diff --git a/src/cairo-tg-private.h b/src/cairo-pixman-private.h
index 6e2464ea4..d705025c8 100755..100644
--- a/src/cairo-tg-private.h
+++ b/src/cairo-pixman-private.h
@@ -1,5 +1,7 @@
-/*
- * Copyright © 2012 SCore Corporation
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright ©2013 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -24,34 +26,26 @@
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
- * Author: Taekyun Kim (podain77@gmail.com)
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * Chris Wilson <chris@chris-wilson.co.uk>
*/
-#ifndef CAIRO_TG_PRIVATE_H
-#define CAIRO_TG_PRIVATE_H
+#ifndef CAIRO_PIXMAN_PRIVATE_H
+#define CAIRO_PIXMAN_PRIVATE_H
-#include "cairo-default-context-private.h"
-#include "cairo-surface-private.h"
-#include "cairo-tg-journal-private.h"
-#include <pixman.h>
+#include "cairo-pixman-private.h" /* keep make check happy */
-#define CAIRO_TG_NUM_MAX_TILES 8
-
-typedef struct _cairo_tg_surface
-{
- cairo_surface_t base;
-
- cairo_format_t format;
- pixman_format_code_t pixman_format;
- unsigned char *data;
- int width;
- int height;
- int stride;
- int bpp;
+#include <pixman.h>
- cairo_surface_t *image_surface;
- cairo_surface_t *tile_surfaces[CAIRO_TG_NUM_MAX_TILES];
- cairo_tg_journal_t journal;
-} cairo_tg_surface_t;
+#if PIXMAN_VERSION < PIXMAN_VERSION_ENCODE(0,22,0)
+#define pixman_image_composite32 pixman_image_composite
+#define pixman_image_get_component_alpha(i) 0
+#define pixman_image_set_component_alpha(i, x) do { } while (0)
+#endif
-#endif /* CAIRO_TG_PRIVATE_H */
+#endif
diff --git a/src/cairo-png.c b/src/cairo-png.c
index e74a4a8bc..068617d58 100755..100644
--- a/src/cairo-png.c
+++ b/src/cairo-png.c
@@ -149,13 +149,13 @@ static void
png_simple_warning_callback (png_structp png,
png_const_charp error_msg)
{
- cairo_status_t *error = png_get_error_ptr (png);
-
- /* default to the most likely error */
- if (*error == CAIRO_STATUS_SUCCESS)
- *error = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- /* png does not expect to abort and will try to tidy up after a warning */
+ /* png does not expect to abort and will try to tidy up and continue
+ * loading the image after a warning. So we also want to return the
+ * (incorrect?) surface.
+ *
+ * We use our own warning callback to squelch any attempts by libpng
+ * to write to stderr as we may not be in control of that output.
+ */
}
diff --git a/src/cairo-polygon-intersect.c b/src/cairo-polygon-intersect.c
index 2cd73d2e5..2cd73d2e5 100755..100644
--- a/src/cairo-polygon-intersect.c
+++ b/src/cairo-polygon-intersect.c
diff --git a/src/cairo-polygon-reduce.c b/src/cairo-polygon-reduce.c
index ea457fe4e..ea457fe4e 100755..100644
--- a/src/cairo-polygon-reduce.c
+++ b/src/cairo-polygon-reduce.c
diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c
index b0424f6e7..b0424f6e7 100755..100644
--- a/src/cairo-polygon.c
+++ b/src/cairo-polygon.c
diff --git a/src/cairo-private.h b/src/cairo-private.h
index 9f4f55b7c..9f4f55b7c 100755..100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
diff --git a/src/cairo-ps-surface-private.h b/src/cairo-ps-surface-private.h
index 1d5d27d49..1d5d27d49 100755..100644
--- a/src/cairo-ps-surface-private.h
+++ b/src/cairo-ps-surface-private.h
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 01df6090b..4fc15f632 100755..100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -340,14 +340,48 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
"/rg { setrgbcolor } bind def\n"
"/d1 { setcachedevice } bind def\n");
+ if (!surface->eps) {
+ _cairo_output_stream_printf (surface->final_stream,
+ "/cairo_set_page_size {\n"
+ " %% Change paper size, but only if different from previous paper size otherwise\n"
+ " %% duplex fails. PLRM specifies a tolerance of 5 pts when matching paper size\n"
+ " %% so we use the same when checking if the size changes.\n"
+ " /setpagedevice where {\n"
+ " pop currentpagedevice\n"
+ " /PageSize known {\n"
+ " 2 copy\n"
+ " currentpagedevice /PageSize get aload pop\n"
+ " exch 4 1 roll\n"
+ " sub abs 5 gt\n"
+ " 3 1 roll\n"
+ " sub abs 5 gt\n"
+ " or\n"
+ " } {\n"
+ " true\n"
+ " } ifelse\n"
+ " {\n"
+ " 2 array astore\n"
+ " 2 dict begin\n"
+ " /PageSize exch def\n"
+ " /ImagingBBox null def\n"
+ " currentdict end\n"
+ " setpagedevice\n"
+ " } {\n"
+ " pop pop\n"
+ " } ifelse\n"
+ " } {\n"
+ " pop\n"
+ " } ifelse\n"
+ "} 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) {
- _cairo_output_stream_printf (surface->final_stream,
- "%%%%BeginSetup\n");
-
comments = _cairo_array_index (&surface->dsc_setup_comments, 0);
for (i = 0; i < num_comments; i++) {
_cairo_output_stream_printf (surface->final_stream,
@@ -355,9 +389,6 @@ _cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
free (comments[i]);
comments[i] = NULL;
}
-
- _cairo_output_stream_printf (surface->final_stream,
- "%%%%EndSetup\n");
}
}
@@ -385,8 +416,13 @@ _cairo_ps_surface_emit_type1_font_subset (cairo_ps_surface_t *surface,
"%% _cairo_ps_surface_emit_type1_font_subset\n");
#endif
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%BeginResource: font %s\n",
+ subset.base_font);
length = subset.header_length + subset.data_length + subset.trailer_length;
_cairo_output_stream_write (surface->final_stream, subset.data, length);
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%EndResource\n");
_cairo_type1_subset_fini (&subset);
@@ -409,15 +445,18 @@ _cairo_ps_surface_emit_type1_font_fallback (cairo_ps_surface_t *surface,
if (unlikely (status))
return status;
- /* FIXME: Figure out document structure convention for fonts */
-
#if DEBUG_PS
_cairo_output_stream_printf (surface->final_stream,
"%% _cairo_ps_surface_emit_type1_font_fallback\n");
#endif
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%BeginResource: font %s\n",
+ subset.base_font);
length = subset.header_length + subset.data_length + subset.trailer_length;
_cairo_output_stream_write (surface->final_stream, subset.data, length);
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%EndResource\n");
_cairo_type1_fallback_fini (&subset);
@@ -446,6 +485,9 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
#endif
_cairo_output_stream_printf (surface->final_stream,
+ "%%%%BeginResource: font %s\n",
+ subset.ps_name);
+ _cairo_output_stream_printf (surface->final_stream,
"11 dict begin\n"
"/FontType 42 def\n"
"/FontName /%s def\n"
@@ -527,13 +569,15 @@ _cairo_ps_surface_emit_truetype_font_subset (cairo_ps_surface_t *surface,
"/f-%d-%d currentdict end definefont pop\n",
font_subset->font_id,
font_subset->subset_id);
-
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%EndResource\n");
_cairo_truetype_subset_fini (&subset);
+
return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_ps_emit_imagemask (cairo_image_surface_t *image,
cairo_output_stream_t *stream)
{
@@ -587,7 +631,8 @@ _cairo_ps_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_sub
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_ps_emit_imagemask,
- surface->font_subsets);
+ surface->font_subsets,
+ TRUE);
for (i = 0; i < font_subset->num_glyphs; i++) {
status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
@@ -624,6 +669,8 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
#endif
_cairo_output_stream_printf (surface->final_stream,
+ "%%%%BeginResource: font\n");
+ _cairo_output_stream_printf (surface->final_stream,
"8 dict begin\n"
"/FontType 3 def\n"
"/FontMatrix [1 0 0 1 0 0] def\n"
@@ -633,7 +680,8 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
NULL,
_cairo_ps_emit_imagemask,
- surface->font_subsets);
+ surface->font_subsets,
+ TRUE);
status = type3_surface->status;
if (unlikely (status)) {
cairo_surface_destroy (type3_surface);
@@ -705,6 +753,8 @@ _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t *surface,
- _cairo_fixed_to_double (font_bbox.p1.y),
font_subset->font_id,
font_subset->subset_id);
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%EndResource\n");
return CAIRO_STATUS_SUCCESS;
}
@@ -1025,7 +1075,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
_cairo_pdf_operators_init (&surface->pdf_operators,
surface->stream,
&surface->cairo_to_ps,
- surface->font_subsets);
+ surface->font_subsets,
+ TRUE);
surface->num_pages = 0;
cairo_list_init (&surface->document_media);
@@ -1568,6 +1619,9 @@ _cairo_ps_surface_finish (void *abstract_surface)
if (unlikely (status))
goto CLEANUP;
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%EndSetup\n");
+
status = _cairo_ps_surface_emit_body (surface);
if (unlikely (status))
goto CLEANUP;
@@ -2738,11 +2792,9 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
}
_cairo_output_stream_printf (surface->stream,
- " /Interpolate %s def\n"
" /ImageMatrix [ 1 0 0 -1 0 %d ] def\n"
"end\n"
"%s\n",
- interpolate,
ps_image->height,
stencil_mask ? "imagemask" : "image");
}
@@ -3113,6 +3165,16 @@ _cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface,
{
cairo_int_status_t 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;
+
+ status = _cairo_ps_surface_emit_jpeg_image (surface, surf, width, height);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+ }
+
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;
@@ -3122,12 +3184,6 @@ _cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface,
}
} else {
cairo_image_surface_t *image = (cairo_image_surface_t *) source_surface;
- if (source_pattern->extend != CAIRO_EXTEND_PAD) {
- status = _cairo_ps_surface_emit_jpeg_image (surface, source_surface,
- width, height);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
- }
status = _cairo_ps_surface_emit_image (surface, image,
op, source_pattern->filter, stencil_mask);
@@ -3267,11 +3323,9 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t *surface,
cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
if (! _cairo_matrix_is_identity (&ps_p2d)) {
- _cairo_output_stream_printf (surface->stream,
- "[ %f %f %f %f %f %f ] concat\n",
- ps_p2d.xx, ps_p2d.yx,
- ps_p2d.xy, ps_p2d.yy,
- ps_p2d.x0, ps_p2d.y0);
+ _cairo_output_stream_printf (surface->stream, "[ ");
+ _cairo_output_stream_print_matrix (surface->stream, &ps_p2d);
+ _cairo_output_stream_printf (surface->stream, " ] concat\n");
}
status = _cairo_ps_surface_emit_surface (surface,
@@ -3419,7 +3473,7 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
_cairo_output_stream_printf (surface->stream,
" /BBox [0 0 %d %d]\n"
" /PaintProc {\n"
- " CairoPattern\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"
@@ -3440,7 +3494,7 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
pattern_width, pattern_height);
}
_cairo_output_stream_printf (surface->stream,
- " /PaintProc { CairoPattern }\n");
+ " /PaintProc { pop CairoPattern }\n");
}
_cairo_output_stream_printf (surface->stream,
@@ -3458,12 +3512,10 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
cairo_matrix_translate (&ps_p2d, 0.0, pattern_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);
_cairo_output_stream_printf (surface->stream,
- "[ %f %f %f %f %f %f ]\n",
- ps_p2d.xx, ps_p2d.yx,
- ps_p2d.xy, ps_p2d.yy,
- ps_p2d.x0, ps_p2d.y0);
- _cairo_output_stream_printf (surface->stream,
+ " ]\n"
"makepattern setpattern\n");
release_source:
@@ -3837,11 +3889,10 @@ _cairo_ps_surface_emit_gradient (cairo_ps_surface_t *surface,
if (is_ps_pattern) {
_cairo_output_stream_printf (surface->stream,
">>\n"
- "[ %f %f %f %f %f %f ]\n"
- "makepattern setpattern\n",
- pat_to_ps.xx, pat_to_ps.yx,
- pat_to_ps.xy, pat_to_ps.yy,
- pat_to_ps.x0, pat_to_ps.y0);
+ "[ ");
+ _cairo_output_stream_print_matrix (surface->stream, &pat_to_ps);
+ _cairo_output_stream_printf (surface->stream, " ]\n"
+ "makepattern setpattern\n");
} else {
_cairo_output_stream_printf (surface->stream,
"shfill\n");
@@ -3919,11 +3970,10 @@ _cairo_ps_surface_emit_mesh_pattern (cairo_ps_surface_t *surface,
if (is_ps_pattern) {
_cairo_output_stream_printf (surface->stream,
">>\n"
- "[ %f %f %f %f %f %f ]\n",
- pat_to_ps.xx, pat_to_ps.yx,
- pat_to_ps.xy, pat_to_ps.yy,
- pat_to_ps.x0, pat_to_ps.y0);
+ "[ \n");
+ _cairo_output_stream_print_matrix (surface->stream, &pat_to_ps);
_cairo_output_stream_printf (surface->stream,
+ " ]\n"
"makepattern\n"
"setpattern\n");
} else {
@@ -4022,11 +4072,9 @@ _cairo_ps_surface_paint_gradient (cairo_ps_surface_t *surface,
cairo_matrix_multiply (&pat_to_ps, &pat_to_ps, &surface->cairo_to_ps);
if (! _cairo_matrix_is_identity (&pat_to_ps)) {
- _cairo_output_stream_printf (surface->stream,
- "[%f %f %f %f %f %f] concat\n",
- pat_to_ps.xx, pat_to_ps.yx,
- pat_to_ps.xy, pat_to_ps.yy,
- pat_to_ps.x0, pat_to_ps.y0);
+ _cairo_output_stream_printf (surface->stream, "[");
+ _cairo_output_stream_print_matrix (surface->stream, &pat_to_ps);
+ _cairo_output_stream_printf (surface->stream, "] concat\n");
}
if (source->type == CAIRO_PATTERN_TYPE_MESH) {
@@ -4578,6 +4626,13 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
x1, y1, x2, y2);
}
+ if (!surface->eps) {
+ _cairo_output_stream_printf (surface->stream,
+ "%f %f cairo_set_page_size\n",
+ ceil(surface->width),
+ ceil(surface->height));
+ }
+
_cairo_output_stream_printf (surface->stream,
"%%%%EndPageSetup\n"
"q %d %d %d %d rectclip q\n",
diff --git a/src/cairo-ps.h b/src/cairo-ps.h
index 33d0e0d94..33d0e0d94 100755..100644
--- a/src/cairo-ps.h
+++ b/src/cairo-ps.h
diff --git a/src/cairo-qt-surface.cpp b/src/cairo-qt-surface.cpp
index ce05dba7e..7ddad77df 100755..100644
--- a/src/cairo-qt-surface.cpp
+++ b/src/cairo-qt-surface.cpp
@@ -306,6 +306,8 @@ _qimage_format_from_cairo_format (cairo_format_t fmt)
#else
return QImage::Format_MonoLSB;
#endif
+ case CAIRO_FORMAT_RGB30:
+ return QImage::Format_Mono;
}
return QImage::Format_Mono;
@@ -386,7 +388,7 @@ _cairo_path_to_qpainterpath_close_path (void *closure)
return CAIRO_STATUS_SUCCESS;
}
-static inline QPainterPath
+static QPainterPath
path_to_qt (const cairo_path_fixed_t *path,
const cairo_matrix_t *ctm_inverse = NULL)
{
@@ -849,7 +851,8 @@ _cairo_qt_surface_set_clip (cairo_qt_surface_t *qs,
*/
struct PatternToBrushConverter {
- PatternToBrushConverter (const cairo_pattern_t *pattern) :
+ PatternToBrushConverter (const cairo_pattern_t *pattern)
+ __attribute__ ((noinline)) :
mAcquiredImageParent(0),
mAcquiredImage(0),
mAcquiredImageExtra(0)
@@ -1048,7 +1051,7 @@ struct PatternToBrushConverter {
}
}
- ~PatternToBrushConverter () {
+ ~PatternToBrushConverter () __attribute__ ((noinline)){
if (mAcquiredImageParent)
_cairo_surface_release_source_image (mAcquiredImageParent, mAcquiredImage, mAcquiredImageExtra);
}
@@ -1657,13 +1660,30 @@ cairo_qt_surface_create_with_qpixmap (cairo_content_t content,
return &qs->base;
}
+/**
+ * _cairo_surface_is_qt:
+ * @surface: a #cairo_surface_t
+ *
+ * Checks if a surface is a #cairo_qt_surface_t
+ *
+ * Return value: True if the surface is an qt surface
+ **/
+static inline cairo_bool_t
+_cairo_surface_is_qt (cairo_surface_t *surface)
+{
+ return surface->backend == &cairo_qt_surface_backend;
+}
+
QPainter *
cairo_qt_surface_get_qpainter (cairo_surface_t *surface)
{
cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface;
- if (surface->type != CAIRO_SURFACE_TYPE_QT)
+ /* Throw an error for a non-qt surface */
+ if (! _cairo_surface_is_qt (surface)) {
+ _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return NULL;
+ }
return qs->p;
}
@@ -1673,8 +1693,11 @@ cairo_qt_surface_get_qimage (cairo_surface_t *surface)
{
cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface;
- if (surface->type != CAIRO_SURFACE_TYPE_QT)
+ /* Throw an error for a non-qt surface */
+ if (! _cairo_surface_is_qt (surface)) {
+ _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return NULL;
+ }
return qs->image;
}
@@ -1684,8 +1707,10 @@ cairo_qt_surface_get_image (cairo_surface_t *surface)
{
cairo_qt_surface_t *qs = (cairo_qt_surface_t*) surface;
- if (surface->type != CAIRO_SURFACE_TYPE_QT)
- return NULL;
+ /* Throw an error for a non-qt surface */
+ if (! _cairo_surface_is_qt (surface)) {
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
+ }
return qs->image_equiv;
}
diff --git a/src/cairo-qt.h b/src/cairo-qt.h
index c20bbb18d..c20bbb18d 100755..100644
--- a/src/cairo-qt.h
+++ b/src/cairo-qt.h
diff --git a/src/cairo-quartz-filters.c b/src/cairo-quartz-filters.c
index 804cddfde..aafceaf68 100755..100644
--- a/src/cairo-quartz-filters.c
+++ b/src/cairo-quartz-filters.c
@@ -363,7 +363,7 @@ _cairo_quartz_gaussian_filter (const cairo_pattern_t *src,
if (! image_ctx) {
free (kernel);
*out_image = NULL;
- return CAIRO_INT_STATUS_NO_MEMORY;
+ return CAIRO_INT_STATUS_NO_MEMORY;
}
#else
image_provider = CGImageGetDataProvider (resized_image);
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index a9bbbdc7a..02f34267b 100755..100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -81,9 +81,6 @@ 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;
-
/* CGFontGetHMetrics isn't public, but the other functions are public/present in 10.5 */
typedef struct {
int ascent;
@@ -127,7 +124,6 @@ quartz_font_ensure_symbols(void)
/* These have the same name in 10.4 and 10.5 */
CGFontGetUnitsPerEmPtr = dlsym(RTLD_DEFAULT, "CGFontGetUnitsPerEm");
CGFontGetGlyphAdvancesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphAdvances");
- CGFontGetGlyphPathPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphPath");
CGFontGetHMetricsPtr = dlsym(RTLD_DEFAULT, "CGFontGetHMetrics");
CGFontGetAscentPtr = dlsym(RTLD_DEFAULT, "CGFontGetAscent");
@@ -144,7 +140,6 @@ quartz_font_ensure_symbols(void)
CGFontGetGlyphsForUnicharsPtr &&
CGFontGetUnitsPerEmPtr &&
CGFontGetGlyphAdvancesPtr &&
- CGFontGetGlyphPathPtr &&
(CGFontGetHMetricsPtr || (CGFontGetAscentPtr && CGFontGetDescentPtr && CGFontGetLeadingPtr)))
_cairo_quartz_font_symbols_present = TRUE;
@@ -241,12 +236,13 @@ _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
return CAIRO_STATUS_SUCCESS;
}
-static void
+static cairo_bool_t
_cairo_quartz_font_face_destroy (void *abstract_face)
{
cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face;
CGFontRelease (font_face->cgFont);
+ return TRUE;
}
static const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend;
@@ -549,6 +545,7 @@ _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) {
@@ -563,7 +560,9 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font,
-font->base.scale.yy,
0, 0);
- glyphPath = CGFontGetGlyphPathPtr (font_face->cgFont, &textMatrix, 0, glyph);
+ ctFont = CTFontCreateWithGraphicsFont (font_face->cgFont, 0.0, NULL, NULL);
+ glyphPath = CTFontCreatePathForGlyph (ctFont, glyph, &textMatrix);
+ CFRelease (ctFont);
if (!glyphPath)
return CAIRO_INT_STATUS_UNSUPPORTED;
diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c
index 2715abd06..498a7b064 100755..100644
--- a/src/cairo-quartz-image-surface.c
+++ b/src/cairo-quartz-image-surface.c
@@ -378,8 +378,10 @@ cairo_quartz_image_surface_get_image (cairo_surface_t *asurface)
{
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t*) asurface;
- if (asurface->type != CAIRO_SURFACE_TYPE_QUARTZ_IMAGE)
- return NULL;
+ /* Throw an error for a non-quartz surface */
+ if (! _cairo_surface_is_quartz (asurface)) {
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
+ }
return (cairo_surface_t*) surface->imageSurface;
}
diff --git a/src/cairo-quartz-image.h b/src/cairo-quartz-image.h
index dae234dac..dae234dac 100755..100644
--- a/src/cairo-quartz-image.h
+++ b/src/cairo-quartz-image.h
diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index 58b97ac99..5e97392db 100755..100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -83,6 +83,9 @@ typedef struct cairo_quartz_image_surface {
cairo_private cairo_bool_t
_cairo_quartz_verify_surface_size(int width, int height);
+cairo_private cairo_bool_t
+_cairo_surface_is_quartz (const cairo_surface_t *surface);
+
cairo_private CGImageRef
CairoQuartzCreateCGImage (cairo_format_t format,
unsigned int width,
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 6d0a0c079..a27128150 100755..100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -257,9 +257,6 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
unsigned int width,
unsigned int height);
-static cairo_bool_t
-_cairo_surface_is_quartz (const cairo_surface_t *surface);
-
/* Load all extra symbols */
static void quartz_ensure_symbols (void)
{
@@ -1521,7 +1518,6 @@ _cairo_quartz_teardown_state (cairo_quartz_drawing_state_t *state,
CGContextDrawLayerInRect (surface->cgContext,
state->clipRect,
state->layer);
- CGContextRelease (state->cgDrawContext);
CGLayerRelease (state->layer);
}
@@ -1805,7 +1801,7 @@ _cairo_quartz_cg_mask_with_surface (cairo_composite_rectangles_t *extents,
cairo_matrix_t m = *mask_mat;
_cairo_surface_get_extents (extents->surface, &dest_extents);
- status = _cairo_surface_to_cgimage (&extents->mask_pattern.base,
+ status = _cairo_surface_to_cgimage (&extents->mask_pattern.base,
mask_surf, &dest_extents, format,
&m, extents->clip, &img);
if (unlikely (status))
@@ -2791,7 +2787,15 @@ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface)
return NULL;
}
-static cairo_bool_t
+/**
+ * _cairo_surface_is_quartz:
+ * @surface: a #cairo_surface_t
+ *
+ * Checks if a surface is a #cairo_quartz_surface_t
+ *
+ * Return value: True if the surface is an quartz surface
+ **/
+cairo_bool_t
_cairo_surface_is_quartz (const cairo_surface_t *surface)
{
return surface->backend == &cairo_quartz_surface_backend;
diff --git a/src/cairo-quartz.h b/src/cairo-quartz.h
index 9be5f9ae5..9be5f9ae5 100755..100644
--- a/src/cairo-quartz.h
+++ b/src/cairo-quartz.h
diff --git a/src/cairo-raster-source-pattern.c b/src/cairo-raster-source-pattern.c
index 2fd8bdb63..bcaa29dc9 100755..100644
--- a/src/cairo-raster-source-pattern.c
+++ b/src/cairo-raster-source-pattern.c
@@ -57,8 +57,6 @@
* Other callbacks are provided for when the pattern is copied temporarily
* during rasterisation, or more permanently as a snapshot in order to keep
* the pixel data available for printing.
- *
- * Since: 1.12
**/
cairo_surface_t *
diff --git a/src/cairo-recording-surface-inline.h b/src/cairo-recording-surface-inline.h
index 9002ccd69..9002ccd69 100755..100644
--- a/src/cairo-recording-surface-inline.h
+++ b/src/cairo-recording-surface-inline.h
diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h
index 0235b0f3f..456c63389 100755..100644
--- a/src/cairo-recording-surface-private.h
+++ b/src/cairo-recording-surface-private.h
@@ -133,9 +133,11 @@ typedef struct _cairo_recording_surface {
cairo_bool_t unbounded;
cairo_array_t commands;
- int *indices;
- int num_indices;
+ unsigned int *indices;
+ unsigned int num_indices;
cairo_bool_t optimize_clears;
+ cairo_bool_t has_bilevel_alpha;
+ cairo_bool_t has_only_op_over;
struct bbtree {
cairo_box_t extents;
@@ -184,4 +186,10 @@ _cairo_recording_surface_get_ink_bbox (cairo_recording_surface_t *surface,
cairo_box_t *bbox,
const cairo_matrix_t *transform);
+cairo_private cairo_bool_t
+_cairo_recording_surface_has_only_bilevel_alpha (cairo_recording_surface_t *surface);
+
+cairo_private cairo_bool_t
+_cairo_recording_surface_has_only_op_over (cairo_recording_surface_t *surface);
+
#endif /* CAIRO_RECORDING_SURFACE_H */
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index 9e672df2c..ee9304746 100755..100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -87,6 +87,7 @@
#include "cairo-error-private.h"
#include "cairo-image-surface-private.h"
#include "cairo-recording-surface-inline.h"
+#include "cairo-surface-snapshot-inline.h"
#include "cairo-surface-wrapper-private.h"
#include "cairo-traps-private.h"
@@ -257,7 +258,7 @@ static cairo_bool_t box_outside (const cairo_box_t *a, const cairo_box_t *b)
static void
bbtree_foreach_mark_visible (struct bbtree *bbt,
const cairo_box_t *box,
- int **indices)
+ unsigned int **indices)
{
cairo_command_header_t *chain;
@@ -270,13 +271,13 @@ bbtree_foreach_mark_visible (struct bbtree *bbt,
bbtree_foreach_mark_visible (bbt->right, box, indices);
}
-static inline int intcmp (const int a, const int b)
+static inline int intcmp (const unsigned int a, const unsigned int b)
{
return a - b;
}
-CAIRO_COMBSORT_DECLARE (sort_indices, int, intcmp)
+CAIRO_COMBSORT_DECLARE (sort_indices, unsigned int, intcmp)
-static inline int sizecmp (int a, int b, cairo_command_header_t **elements)
+static inline int sizecmp (unsigned int a, unsigned int b, cairo_command_header_t **elements)
{
const cairo_rectangle_int_t *r;
@@ -288,7 +289,7 @@ static inline int sizecmp (int a, int b, cairo_command_header_t **elements)
return b - a;
}
-CAIRO_COMBSORT_DECLARE_WITH_DATA (sort_commands, int, sizecmp)
+CAIRO_COMBSORT_DECLARE_WITH_DATA (sort_commands, unsigned int, sizecmp)
static void
_cairo_recording_surface_destroy_bbtree (cairo_recording_surface_t *surface)
@@ -323,9 +324,9 @@ _cairo_recording_surface_create_bbtree (cairo_recording_surface_t *surface)
if (unlikely (elements == NULL))
return _cairo_error (CAIRO_STATUS_NULL_POINTER);
+ unsigned int *indices;
cairo_status_t status;
- int i, count;
- int *indices;
+ unsigned int i, count;
count = surface->commands.num_elements;
if (count > surface->num_indices) {
@@ -423,6 +424,8 @@ cairo_recording_surface_create (cairo_content_t content,
surface->indices = NULL;
surface->num_indices = 0;
surface->optimize_clears = TRUE;
+ surface->has_bilevel_alpha = FALSE;
+ surface->has_only_op_over = FALSE;
return &surface->base;
}
@@ -1589,9 +1592,12 @@ static int
_cairo_recording_surface_get_visible_commands (cairo_recording_surface_t *surface,
const cairo_rectangle_int_t *extents)
{
- int num_visible, *indices;
+ unsigned int num_visible, *indices;
cairo_box_t box;
+ if (surface->commands.num_elements == 0)
+ return 0;
+
_cairo_box_from_rectangle (&box, extents);
if (surface->bbtree.chain == INVALID_CHAIN)
@@ -1606,6 +1612,68 @@ _cairo_recording_surface_get_visible_commands (cairo_recording_surface_t *surfac
return num_visible;
}
+static void
+_cairo_recording_surface_merge_source_attributes (cairo_recording_surface_t *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *source)
+{
+ if (op != CAIRO_OPERATOR_OVER)
+ surface->has_only_op_over = FALSE;
+
+ if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
+ cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) source;
+ cairo_surface_t *surf = surf_pat->surface;
+ cairo_surface_t *free_me = NULL;
+
+ if (_cairo_surface_is_snapshot (surf))
+ free_me = surf = _cairo_surface_snapshot_get_target (surf);
+
+ if (surf->type == CAIRO_SURFACE_TYPE_RECORDING) {
+ cairo_recording_surface_t *rec_surf = (cairo_recording_surface_t *) surf;
+
+ if (! _cairo_recording_surface_has_only_bilevel_alpha (rec_surf))
+ surface->has_bilevel_alpha = FALSE;
+
+ if (! _cairo_recording_surface_has_only_op_over (rec_surf))
+ surface->has_only_op_over = FALSE;
+
+ } else if (surf->type == CAIRO_SURFACE_TYPE_IMAGE) {
+ cairo_image_surface_t *img_surf = (cairo_image_surface_t *) surf;
+
+ if (_cairo_image_analyze_transparency (img_surf) == CAIRO_IMAGE_HAS_ALPHA)
+ surface->has_bilevel_alpha = FALSE;
+
+ } else {
+ if (!_cairo_pattern_is_clear (source) && !_cairo_pattern_is_opaque (source, NULL))
+ surface->has_bilevel_alpha = FALSE;
+ }
+
+ cairo_surface_destroy (free_me);
+ return;
+
+ } else if (source->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) {
+ cairo_surface_t *image;
+ cairo_surface_t *raster;
+
+ image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+ raster = _cairo_raster_source_pattern_acquire (source, image, NULL);
+ cairo_surface_destroy (image);
+ if (raster) {
+ if (raster->type == CAIRO_SURFACE_TYPE_IMAGE) {
+ if (_cairo_image_analyze_transparency ((cairo_image_surface_t *)raster) == CAIRO_IMAGE_HAS_ALPHA)
+ surface->has_bilevel_alpha = FALSE;
+ }
+
+ _cairo_raster_source_pattern_release (source, raster);
+ if (raster->type == CAIRO_SURFACE_TYPE_IMAGE)
+ return;
+ }
+ }
+
+ if (!_cairo_pattern_is_clear (source) && !_cairo_pattern_is_opaque (source, NULL))
+ surface->has_bilevel_alpha = FALSE;
+}
+
static cairo_status_t
_cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
const cairo_rectangle_int_t *surface_extents,
@@ -1624,7 +1692,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
cairo_rectangle_int_t extents;
cairo_bool_t use_indices = FALSE;
const cairo_rectangle_int_t *r;
- int i, num_elements;
+ unsigned int i, num_elements;
if (unlikely (surface->base.status))
return surface->base.status;
@@ -1655,6 +1723,9 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
if (! _cairo_surface_wrapper_get_target_extents (&wrapper, &extents))
goto done;
+ surface->has_bilevel_alpha = TRUE;
+ surface->has_only_op_over = TRUE;
+
num_elements = surface->commands.num_elements;
elements = _cairo_array_index (&surface->commands, 0);
if (elements == NULL) {
@@ -1665,7 +1736,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
if (extents.width < r->width || extents.height < r->height) {
num_elements =
_cairo_recording_surface_get_visible_commands (surface, &extents);
- use_indices = TRUE;
+ use_indices = num_elements != surface->commands.num_elements;
}
for (i = 0; i < num_elements; i++) {
@@ -1683,6 +1754,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
command->header.op,
&command->paint.source.base,
command->header.clip);
+ if (type == CAIRO_RECORDING_CREATE_REGIONS) {
+ _cairo_recording_surface_merge_source_attributes (surface,
+ command->header.op,
+ &command->paint.source.base);
+ }
break;
case CAIRO_COMMAND_MASK:
@@ -1691,6 +1767,14 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
&command->mask.source.base,
&command->mask.mask.base,
command->header.clip);
+ if (type == CAIRO_RECORDING_CREATE_REGIONS) {
+ _cairo_recording_surface_merge_source_attributes (surface,
+ command->header.op,
+ &command->mask.source.base);
+ _cairo_recording_surface_merge_source_attributes (surface,
+ command->header.op,
+ &command->mask.mask.base);
+ }
break;
case CAIRO_COMMAND_STROKE:
@@ -1704,6 +1788,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
command->stroke.tolerance,
command->stroke.antialias,
command->header.clip);
+ if (type == CAIRO_RECORDING_CREATE_REGIONS) {
+ _cairo_recording_surface_merge_source_attributes (surface,
+ command->header.op,
+ &command->stroke.source.base);
+ }
break;
case CAIRO_COMMAND_FILL:
@@ -1745,6 +1834,14 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
stroke_command->stroke.tolerance,
stroke_command->stroke.antialias,
command->header.clip);
+ if (type == CAIRO_RECORDING_CREATE_REGIONS) {
+ _cairo_recording_surface_merge_source_attributes (surface,
+ command->header.op,
+ &command->fill.source.base);
+ _cairo_recording_surface_merge_source_attributes (surface,
+ command->header.op,
+ &command->stroke.source.base);
+ }
i++;
}
}
@@ -1757,6 +1854,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
command->fill.tolerance,
command->fill.antialias,
command->header.clip);
+ if (type == CAIRO_RECORDING_CREATE_REGIONS) {
+ _cairo_recording_surface_merge_source_attributes (surface,
+ command->header.op,
+ &command->fill.source.base);
+ }
}
break;
@@ -1770,6 +1872,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface,
command->show_text_glyphs.cluster_flags,
command->show_text_glyphs.scaled_font,
command->header.clip);
+ if (type == CAIRO_RECORDING_CREATE_REGIONS) {
+ _cairo_recording_surface_merge_source_attributes (surface,
+ command->header.op,
+ &command->show_text_glyphs.source.base);
+ }
break;
default:
@@ -2083,3 +2190,15 @@ cairo_recording_surface_get_extents (cairo_surface_t *surface,
*extents = record->extents_pixels;
return TRUE;
}
+
+cairo_bool_t
+_cairo_recording_surface_has_only_bilevel_alpha (cairo_recording_surface_t *surface)
+{
+ return surface->has_bilevel_alpha;
+}
+
+cairo_bool_t
+_cairo_recording_surface_has_only_op_over (cairo_recording_surface_t *surface)
+{
+ return surface->has_only_op_over;
+}
diff --git a/src/cairo-rectangle.c b/src/cairo-rectangle.c
index c8f90e671..c8f90e671 100755..100644
--- a/src/cairo-rectangle.c
+++ b/src/cairo-rectangle.c
diff --git a/src/cairo-rectangular-scan-converter.c b/src/cairo-rectangular-scan-converter.c
index e353b34e8..e353b34e8 100755..100644
--- a/src/cairo-rectangular-scan-converter.c
+++ b/src/cairo-rectangular-scan-converter.c
diff --git a/src/cairo-reference-count-private.h b/src/cairo-reference-count-private.h
index 75fdf3538..75fdf3538 100755..100644
--- a/src/cairo-reference-count-private.h
+++ b/src/cairo-reference-count-private.h
diff --git a/src/cairo-region-private.h b/src/cairo-region-private.h
index 549e50878..549e50878 100755..100644
--- a/src/cairo-region-private.h
+++ b/src/cairo-region-private.h
diff --git a/src/cairo-region.c b/src/cairo-region.c
index a51e2247f..ccfb2200e 100755..100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -106,6 +106,7 @@ _cairo_region_create_in_error (cairo_status_t status)
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
case CAIRO_STATUS_DEVICE_FINISHED:
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_region_t *) &_cairo_region_nil;
@@ -841,18 +842,6 @@ cairo_region_translate (cairo_region_t *region,
slim_hidden_def (cairo_region_translate);
/**
- * cairo_region_overlap_t:
- * @CAIRO_REGION_OVERLAP_IN: The contents are entirely inside the region. (Since 1.10)
- * @CAIRO_REGION_OVERLAP_OUT: The contents are entirely outside the region. (Since 1.10)
- * @CAIRO_REGION_OVERLAP_PART: The contents are partially inside and
- * partially outside the region. (Since 1.10)
- *
- * Used as the return value for cairo_region_contains_rectangle().
- *
- * Since: 1.10
- **/
-
-/**
* cairo_region_contains_rectangle:
* @region: a #cairo_region_t
* @rectangle: a #cairo_rectangle_int_t
diff --git a/src/cairo-rtree-private.h b/src/cairo-rtree-private.h
index 27806cab6..27806cab6 100755..100644
--- a/src/cairo-rtree-private.h
+++ b/src/cairo-rtree-private.h
diff --git a/src/cairo-rtree.c b/src/cairo-rtree.c
index dbc040929..dbc040929 100755..100644
--- a/src/cairo-rtree.c
+++ b/src/cairo-rtree.c
diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index da7b34698..da7b34698 100755..100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
diff --git a/src/cairo-scaled-font-subsets-private.h b/src/cairo-scaled-font-subsets-private.h
index dd1996258..866e63d7b 100755..100644
--- a/src/cairo-scaled-font-subsets-private.h
+++ b/src/cairo-scaled-font-subsets-private.h
@@ -715,6 +715,21 @@ _cairo_truetype_get_style (cairo_scaled_font_t *scaled_font,
cairo_bool_t *bold,
cairo_bool_t *italic);
+/**
+ * _cairo_escape_ps_name:
+ * @ps_name: returns the PostScript name with all invalid characters escaped
+ *
+ * Ensure that PostSript name is a valid PDF/PostSript name object.
+ * In PDF names are treated as UTF8 and non ASCII bytes, ' ',
+ * and '#' are encoded as '#' followed by 2 hex digits that
+ * encode the byte.
+ *
+ * Return value: %CAIRO_STATUS_SUCCESS if successful. Possible errors include
+ * %CAIRO_STATUS_NO_MEMORY.
+ **/
+cairo_private cairo_int_status_t
+_cairo_escape_ps_name (char **ps_name);
+
#endif /* CAIRO_HAS_FONT_SUBSET */
#endif /* CAIRO_SCALED_FONT_SUBSETS_PRIVATE_H */
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index e78e0c283..212176183 100755..100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -1256,4 +1256,44 @@ CLEANUP_HASH:
return status;
}
+cairo_int_status_t
+_cairo_escape_ps_name (char **ps_name)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ /* Ensure PS name is a valid PDF/PS name object. In PDF names are
+ * treated as UTF8 and non ASCII bytes, ' ', and '#' are encoded
+ * as '#' followed by 2 hex digits that encode the byte. By also
+ * encoding the characters in the reserved string we ensure the
+ * name is also PS compatible. */
+ if (*ps_name) {
+ static const char *reserved = "()<>[]{}/%#\\";
+ char buf[128]; /* max name length is 127 bytes */
+ char *src = *ps_name;
+ char *dst = buf;
+
+ while (*src && dst < buf + 127) {
+ unsigned char c = *src;
+ if (c < 0x21 || c > 0x7e || strchr (reserved, c)) {
+ if (dst + 4 > buf + 127)
+ break;
+
+ snprintf (dst, 4, "#%02X", c);
+ src++;
+ dst += 3;
+ } else {
+ *dst++ = *src++;
+ }
+ }
+ *dst = 0;
+ free (*ps_name);
+ *ps_name = strdup (buf);
+ if (*ps_name == NULL) {
+ status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+ }
+
+ return status;
+}
+
#endif /* CAIRO_HAS_FONT_SUBSET */
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index ea4435aff..660ff7ce0 100755..100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -2938,8 +2938,12 @@ _cairo_scaled_font_free_last_glyph (cairo_scaled_font_t *scaled_font,
if (--page->num_glyphs == 0) {
CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
+ /* Temporarily disconnect callback to avoid recursive locking */
+ cairo_scaled_glyph_page_cache.entry_destroy = NULL;
_cairo_cache_remove (&cairo_scaled_glyph_page_cache,
&page->cache_entry);
+ _cairo_scaled_glyph_page_destroy (scaled_font, page);
+ cairo_scaled_glyph_page_cache.entry_destroy = _cairo_scaled_glyph_page_pluck;
CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
}
}
diff --git a/src/cairo-script-private.h b/src/cairo-script-private.h
index 5b506f500..5b506f500 100755..100644
--- a/src/cairo-script-private.h
+++ b/src/cairo-script-private.h
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index 68c1528f6..68c1528f6 100755..100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
diff --git a/src/cairo-script.h b/src/cairo-script.h
index b5a8cf32d..b5a8cf32d 100755..100644
--- a/src/cairo-script.h
+++ b/src/cairo-script.h
diff --git a/src/cairo-shape-mask-compositor.c b/src/cairo-shape-mask-compositor.c
index c2425b08c..3117267cc 100755..100644
--- a/src/cairo-shape-mask-compositor.c
+++ b/src/cairo-shape-mask-compositor.c
@@ -62,10 +62,11 @@ _cairo_shape_mask_compositor_stroke (const cairo_compositor_t *_compositor,
return CAIRO_INT_STATUS_UNSUPPORTED;
TRACE ((stderr, "%s\n", __FUNCTION__));
- mask = _cairo_surface_create_similar_scratch (extents->surface,
- CAIRO_CONTENT_ALPHA,
- extents->bounded.width,
- extents->bounded.height);
+ mask = _cairo_surface_create_scratch (extents->surface,
+ CAIRO_CONTENT_ALPHA,
+ extents->bounded.width,
+ extents->bounded.height,
+ NULL);
if (unlikely (mask->status))
return mask->status;
@@ -156,10 +157,11 @@ _cairo_shape_mask_compositor_fill (const cairo_compositor_t *_compositor,
if (! extents->is_bounded)
return CAIRO_INT_STATUS_UNSUPPORTED;
- mask = _cairo_surface_create_similar_scratch (extents->surface,
- CAIRO_CONTENT_ALPHA,
- extents->bounded.width,
- extents->bounded.height);
+ mask = _cairo_surface_create_scratch (extents->surface,
+ CAIRO_CONTENT_ALPHA,
+ extents->bounded.width,
+ extents->bounded.height,
+ NULL);
if (unlikely (mask->status))
return mask->status;
@@ -248,10 +250,11 @@ _cairo_shape_mask_compositor_glyphs (const cairo_compositor_t *_compositor,
return CAIRO_INT_STATUS_UNSUPPORTED;
TRACE ((stderr, "%s\n", __FUNCTION__));
- mask = _cairo_surface_create_similar_scratch (extents->surface,
- CAIRO_CONTENT_ALPHA,
- extents->bounded.width,
- extents->bounded.height);
+ mask = _cairo_surface_create_scratch (extents->surface,
+ CAIRO_CONTENT_ALPHA,
+ extents->bounded.width,
+ extents->bounded.height,
+ NULL);
if (unlikely (mask->status))
return mask->status;
diff --git a/src/cairo-skia-surface.cpp b/src/cairo-skia-surface.cpp
index bf6b14a5e..0282c2b51 100755..100644
--- a/src/cairo-skia-surface.cpp
+++ b/src/cairo-skia-surface.cpp
@@ -51,6 +51,27 @@
#include <SkGradientShader.h>
#include <SkDashPathEffect.h>
+/**
+ * SECTION:cairo-skia
+ * @Title: Skia Surfaces
+ * @Short_Description: Rendering to Skia surfaces
+ * @See_Also: #cairo_surface_t
+ *
+ * Originally written by Vladimir Vukicevic to investigate using Skia for
+ * Mozilla, it provides a nice integration with a rather interesting code
+ * base. By hooking Skia underneath Cairo it allows us to directly compare
+ * code paths... which is interesting.
+ **/
+
+/**
+ * CAIRO_HAS_SKIA_SURFACE:
+ *
+ * Defined if the Skia surface backend is available.
+ * This macro can be used to conditionally compile backend-specific code.
+ *
+ * Since: 1.10
+ **/
+
#if (CAIRO_FIXED_BITS == 32) && (CAIRO_FIXED_FRAC_BITS == 16) && defined(SK_SCALAR_IS_FIXED)
# define CAIRO_FIXED_TO_SK_SCALAR(x) (x)
#elif defined(SK_SCALAR_IS_FIXED)
@@ -64,13 +85,20 @@
# define CAIRO_INT_STATUS_SUCCESS ((cairo_int_status_t) CAIRO_STATUS_SUCCESS)
#endif
-#define CAIRO_MAYBE_UNSUPPORTED CAIRO_INT_STATUS_UNSUPPORTED
-//#define CAIRO_MAYBE_UNSUPPORTED _skia_unsupported ()
+#define DEBUG_SKIA 0
+
+#if DEBUG_SKIA
+#define UNSUPPORTED(reason) ({ \
+ fprintf (stderr, \
+ "cairo-skia : hit unsupported operation in %s(), line %d: %s\n", \
+ __FUNCTION__, __LINE__, reason); \
+ return CAIRO_INT_STATUS_UNSUPPORTED; \
+})
+#else
+#define UNSUPPORTED(reason) ({ \
+ return CAIRO_INT_STATUS_UNSUPPORTED; \
+})#endif
-static cairo_int_status_t _skia_unsupported () {
- printf ("unsupported!\n");
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
typedef struct cairo_skia_surface {
cairo_surface_t base;
@@ -542,8 +570,7 @@ _cairo_skia_surface_create_similar (void *asurface,
if (! format_to_sk_config (_cairo_format_from_content (content),
config, opaque))
{
- _skia_unsupported ();
- return NULL;
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
}
return &_cairo_skia_surface_create_internal (config, opaque,
@@ -781,7 +808,7 @@ _cairo_skia_surface_paint (void *asurface,
shader = pattern_to_sk_shader (surface, source, &image, &image_extra);
if (!bitmap && !shader)
- return CAIRO_MAYBE_UNSUPPORTED;
+ return UNSUPPORTED("pattern to bitmap and shader conversion");
SkPaint paint;
paint.setFilterBitmap (pattern_filter_to_sk (source));
@@ -838,7 +865,7 @@ _cairo_skia_surface_stroke (void *asurface,
SkShader *shader = pattern_to_sk_shader (surface,
source, &image, &image_extra);
if (shader == NULL)
- return CAIRO_MAYBE_UNSUPPORTED;
+ return UNSUPPORTED("pattern to shader conversion");
paint.setShader (shader);
shader->unref ();
@@ -941,7 +968,7 @@ _cairo_skia_surface_fill (void *asurface,
SkShader *shader = pattern_to_sk_shader (surface,
source, &image, &image_extra);
if (shader == NULL)
- return CAIRO_MAYBE_UNSUPPORTED;
+ return UNSUPPORTED("pattern to shader conversion");
paint.setShader (shader);
shader->unref ();
diff --git a/src/cairo-skia.h b/src/cairo-skia.h
index 99b928656..99b928656 100755..100644
--- a/src/cairo-skia.h
+++ b/src/cairo-skia.h
diff --git a/src/cairo-slope-private.h b/src/cairo-slope-private.h
index 6a58c9f45..6a58c9f45 100755..100644
--- a/src/cairo-slope-private.h
+++ b/src/cairo-slope-private.h
diff --git a/src/cairo-slope.c b/src/cairo-slope.c
index cc5f30cb0..cc5f30cb0 100755..100644
--- a/src/cairo-slope.c
+++ b/src/cairo-slope.c
diff --git a/src/cairo-spans-compositor-private.h b/src/cairo-spans-compositor-private.h
index 0babebd26..0babebd26 100755..100644
--- a/src/cairo-spans-compositor-private.h
+++ b/src/cairo-spans-compositor-private.h
diff --git a/src/cairo-spans-compositor.c b/src/cairo-spans-compositor.c
index 8580da383..ef213b491 100755..100644
--- a/src/cairo-spans-compositor.c
+++ b/src/cairo-spans-compositor.c
@@ -95,11 +95,11 @@ get_clip_surface (const cairo_spans_compositor_t *compositor,
assert (clip->path);
- surface = _cairo_surface_create_similar_solid (dst,
- CAIRO_CONTENT_ALPHA,
- extents->width,
- extents->height,
- CAIRO_COLOR_TRANSPARENT);
+ surface = _cairo_surface_create_scratch (dst,
+ CAIRO_CONTENT_ALPHA,
+ extents->width,
+ extents->height,
+ CAIRO_COLOR_TRANSPARENT);
_cairo_box_from_rectangle (&box, extents);
_cairo_polygon_init (&polygon, &box, 1);
@@ -588,20 +588,34 @@ composite_aligned_boxes (const cairo_spans_compositor_t *compositor,
{
cairo_clip_t *recording_clip;
const cairo_pattern_t *source = &extents->source_pattern.base;
+ const cairo_matrix_t *m;
+ cairo_matrix_t matrix;
/* XXX could also do tiling repeat modes... */
/* first clear the area about to be overwritten */
- if (! dst->is_clear)
+ if (! dst->is_clear) {
status = compositor->fill_boxes (dst,
CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
boxes);
+ if (unlikely (status))
+ return status;
+
+ dst->is_clear = TRUE;
+ }
+
+ m = &source->matrix;
+ if (_cairo_surface_has_device_transform (dst)) {
+ cairo_matrix_multiply (&matrix,
+ &source->matrix,
+ &dst->device_transform);
+ m = &matrix;
+ }
recording_clip = _cairo_clip_from_boxes (boxes);
status = _cairo_recording_surface_replay_with_clip (unwrap_source (source),
- &source->matrix,
- dst, recording_clip);
+ m, dst, recording_clip);
_cairo_clip_destroy (recording_clip);
return status;
diff --git a/src/cairo-spans-private.h b/src/cairo-spans-private.h
index c42b5afa7..b158f4d36 100755..100644
--- a/src/cairo-spans-private.h
+++ b/src/cairo-spans-private.h
@@ -53,7 +53,7 @@ struct _cairo_span_renderer {
/* Render the spans on row y of the destination by whatever compositing
* method is required. */
- cairo_warn cairo_status_t
+ cairo_status_t
(*render_rows) (void *abstract_renderer,
int y, int height,
const cairo_half_open_span_t *coverages,
diff --git a/src/cairo-spans.c b/src/cairo-spans.c
index b8d41800e..182390c20 100755..100644
--- a/src/cairo-spans.c
+++ b/src/cairo-spans.c
@@ -127,6 +127,7 @@ _cairo_scan_converter_create_in_error (cairo_status_t status)
case CAIRO_STATUS_DEVICE_ERROR: RETURN_NIL;
case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: RETURN_NIL;
case CAIRO_STATUS_DEVICE_FINISHED: RETURN_NIL;
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
default:
break;
}
@@ -239,6 +240,7 @@ _cairo_span_renderer_create_in_error (cairo_status_t status)
case CAIRO_STATUS_DEVICE_ERROR: RETURN_NIL;
case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: RETURN_NIL;
case CAIRO_STATUS_DEVICE_FINISHED: RETURN_NIL;
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: RETURN_NIL;
default:
break;
}
diff --git a/src/cairo-spline.c b/src/cairo-spline.c
index 9ebb949c7..6341d71b3 100755..100644
--- a/src/cairo-spline.c
+++ b/src/cairo-spline.c
@@ -38,6 +38,7 @@
#include "cairo-box-inline.h"
#include "cairo-slope-private.h"
+#include "cairo-convex-fill-private.h"
cairo_bool_t
_cairo_spline_intersects (const cairo_point_t *a,
diff --git a/src/cairo-stroke-dash-private.h b/src/cairo-stroke-dash-private.h
index 75c000cd7..75c000cd7 100755..100644
--- a/src/cairo-stroke-dash-private.h
+++ b/src/cairo-stroke-dash-private.h
diff --git a/src/cairo-stroke-dash.c b/src/cairo-stroke-dash.c
index 9494010f5..9494010f5 100755..100644
--- a/src/cairo-stroke-dash.c
+++ b/src/cairo-stroke-dash.c
diff --git a/src/cairo-stroke-style.c b/src/cairo-stroke-style.c
index 51c9414c0..51c9414c0 100755..100644
--- a/src/cairo-stroke-style.c
+++ b/src/cairo-stroke-style.c
diff --git a/src/cairo-surface-backend-private.h b/src/cairo-surface-backend-private.h
index be624dfbe..be624dfbe 100755..100644
--- a/src/cairo-surface-backend-private.h
+++ b/src/cairo-surface-backend-private.h
diff --git a/src/cairo-surface-clipper-private.h b/src/cairo-surface-clipper-private.h
index e5b00af7c..e5b00af7c 100755..100644
--- a/src/cairo-surface-clipper-private.h
+++ b/src/cairo-surface-clipper-private.h
diff --git a/src/cairo-surface-clipper.c b/src/cairo-surface-clipper.c
index 5309362c6..5309362c6 100755..100644
--- a/src/cairo-surface-clipper.c
+++ b/src/cairo-surface-clipper.c
diff --git a/src/cairo-surface-fallback-private.h b/src/cairo-surface-fallback-private.h
index ecf7b0edf..ecf7b0edf 100755..100644
--- a/src/cairo-surface-fallback-private.h
+++ b/src/cairo-surface-fallback-private.h
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index a0af15969..a0af15969 100755..100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
diff --git a/src/cairo-surface-inline.h b/src/cairo-surface-inline.h
index 85fbc9192..85fbc9192 100755..100644
--- a/src/cairo-surface-inline.h
+++ b/src/cairo-surface-inline.h
diff --git a/src/cairo-surface-observer-inline.h b/src/cairo-surface-observer-inline.h
index 07b94770d..07b94770d 100755..100644
--- a/src/cairo-surface-observer-inline.h
+++ b/src/cairo-surface-observer-inline.h
diff --git a/src/cairo-surface-observer-private.h b/src/cairo-surface-observer-private.h
index 6ed0c18d1..6ed0c18d1 100755..100644
--- a/src/cairo-surface-observer-private.h
+++ b/src/cairo-surface-observer-private.h
diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index 8bbd6109c..ee65b72d1 100755..100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -653,7 +653,7 @@ add_record (cairo_observation_t *log,
}
static void
-sync (cairo_surface_t *target, int x, int y)
+_cairo_surface_sync (cairo_surface_t *target, int x, int y)
{
cairo_rectangle_int_t extents;
@@ -751,7 +751,7 @@ _cairo_surface_observer_paint (void *abstract_surface,
if (unlikely (status))
return status;
- sync (surface->target, x, y);
+ _cairo_surface_sync (surface->target, x, y);
t = _cairo_time_get_delta (t);
add_record_paint (&surface->log, surface->target, op, source, clip, t);
@@ -837,7 +837,7 @@ _cairo_surface_observer_mask (void *abstract_surface,
if (unlikely (status))
return status;
- sync (surface->target, x, y);
+ _cairo_surface_sync (surface->target, x, y);
t = _cairo_time_get_delta (t);
add_record_mask (&surface->log,
@@ -944,7 +944,7 @@ _cairo_surface_observer_fill (void *abstract_surface,
if (unlikely (status))
return status;
- sync (surface->target, x, y);
+ _cairo_surface_sync (surface->target, x, y);
t = _cairo_time_get_delta (t);
add_record_fill (&surface->log,
@@ -1063,7 +1063,7 @@ _cairo_surface_observer_stroke (void *abstract_surface,
if (unlikely (status))
return status;
- sync (surface->target, x, y);
+ _cairo_surface_sync (surface->target, x, y);
t = _cairo_time_get_delta (t);
add_record_stroke (&surface->log,
@@ -1183,7 +1183,7 @@ _cairo_surface_observer_glyphs (void *abstract_surface,
if (unlikely (status))
return status;
- sync (surface->target, x, y);
+ _cairo_surface_sync (surface->target, x, y);
t = _cairo_time_get_delta (t);
add_record_glyphs (&surface->log,
@@ -1368,11 +1368,16 @@ static const cairo_surface_backend_t _cairo_surface_observer_backend = {
/**
* cairo_surface_create_observer:
* @target: an existing surface for which the observer will watch
+ * @mode: sets the mode of operation (normal vs. record)
*
* Create a new surface that exists solely to watch another is doing. In
* the process it will log operations and times, which are fast, which are
* slow, which are frequent, etc.
*
+ * The @mode parameter can be set to either CAIRO_SURFACE_OBSERVER_NORMAL
+ * or CAIRO_SURFACE_OBSERVER_RECORD_OPERATIONS, to control whether or not
+ * the internal observer should record operations.
+ *
* Return value: a pointer to the newly allocated surface. The caller
* owns the surface and should call cairo_surface_destroy() when done
* with it.
diff --git a/src/cairo-surface-offset-private.h b/src/cairo-surface-offset-private.h
index 310ba5691..310ba5691 100755..100644
--- a/src/cairo-surface-offset-private.h
+++ b/src/cairo-surface-offset-private.h
diff --git a/src/cairo-surface-offset.c b/src/cairo-surface-offset.c
index 98f57f298..98f57f298 100755..100644
--- a/src/cairo-surface-offset.c
+++ b/src/cairo-surface-offset.c
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index f20ab0739..f20ab0739 100755..100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
diff --git a/src/cairo-surface-scale-translate-private.h b/src/cairo-surface-scale-translate-private.h
index b13d3366d..b13d3366d 100755..100644
--- a/src/cairo-surface-scale-translate-private.h
+++ b/src/cairo-surface-scale-translate-private.h
diff --git a/src/cairo-surface-scale-translate.c b/src/cairo-surface-scale-translate.c
index 1729b81ad..1729b81ad 100755..100644
--- a/src/cairo-surface-scale-translate.c
+++ b/src/cairo-surface-scale-translate.c
diff --git a/src/cairo-surface-shadow-private.h b/src/cairo-surface-shadow-private.h
index 43c7e6d2a..43c7e6d2a 100755..100644
--- a/src/cairo-surface-shadow-private.h
+++ b/src/cairo-surface-shadow-private.h
diff --git a/src/cairo-surface-shadow.c b/src/cairo-surface-shadow.c
index 5224bee40..921258ec3 100755..100644
--- a/src/cairo-surface-shadow.c
+++ b/src/cairo-surface-shadow.c
@@ -319,7 +319,8 @@ _cairo_ensure_shadow_surface (cairo_surface_t *target,
content,
width_out,
height_out);
- _cairo_surface_release_device_reference (shadow_surface);
+ if (shadow_surface->device)
+ _cairo_surface_release_device_reference (shadow_surface);
}
shadow_surface_extents->x = 0;
@@ -407,13 +408,13 @@ _cairo_surface_shadow_paint (cairo_surface_t *target,
&shadow_source.base,
&shadow_extents,
&bounded);
- if (unlikely (status))
+ if (unlikely (status))
goto FINISH;
if (shadow_extents.width == 0 || shadow_extents.height == 0)
goto FINISH;
- x_offset = shadow_extents.x - x_blur;
+ x_offset = shadow_extents.x - x_blur;
y_offset = shadow_extents.y - y_blur;
cairo_matrix_init_scale (&m, shadow_cache->scale, shadow_cache->scale);
@@ -678,13 +679,13 @@ _cairo_surface_shadow_mask (cairo_surface_t *target,
&shadow_mask.base,
&shadow_extents,
&bounded);
- if (unlikely (status))
+ if (unlikely (status))
goto FINISH;
if (shadow_extents.width == 0 || shadow_extents.height == 0)
goto FINISH;
- x_offset = shadow_extents.x - x_blur;
+ x_offset = shadow_extents.x - x_blur;
y_offset = shadow_extents.y - y_blur;
cairo_matrix_init_scale (&m, shadow_cache->scale, shadow_cache->scale);
@@ -918,13 +919,13 @@ _cairo_surface_inset_shadow_stroke (cairo_surface_t *target,
&shadow_ctm,
&shadow_ctm_inverse,
&shadow_extents);
- if (unlikely (status))
+ if (unlikely (status))
goto FINISH;
if (shadow_extents.width == 0 || shadow_extents.height == 0)
goto FINISH;
- x_offset = shadow_extents.x - x_blur;
+ x_offset = shadow_extents.x - x_blur;
y_offset = shadow_extents.y - y_blur;
cairo_matrix_init_scale (&m, shadow_cache->scale, shadow_cache->scale);
@@ -1205,13 +1206,13 @@ _cairo_surface_shadow_stroke (cairo_surface_t *target,
&shadow_ctm,
&shadow_ctm_inverse,
&shadow_extents);
- if (unlikely (status))
+ if (unlikely (status))
goto FINISH;
if (shadow_extents.width == 0 || shadow_extents.height == 0)
goto FINISH;
- x_offset = shadow_extents.x - x_blur;
+ x_offset = shadow_extents.x - x_blur;
y_offset = shadow_extents.y - y_blur;
cairo_matrix_init_scale (&m, shadow_cache->scale, shadow_cache->scale);
@@ -1437,7 +1438,7 @@ _cairo_surface_inset_shadow_fill (cairo_surface_t *target,
if (shadow_cache != NULL) {
/* paint the shadow surface to target */
- color_pattern = cairo_pattern_create_rgba (shadow_copy.color.red,
+ color_pattern = cairo_pattern_create_rgba (shadow_copy.color.red,
shadow_copy.color.green,
shadow_copy.color.blue,
1.0);
@@ -1455,13 +1456,13 @@ _cairo_surface_inset_shadow_fill (cairo_surface_t *target,
&shadow_source.base,
&shadow_path,
&shadow_extents);
- if (unlikely (status))
+ if (unlikely (status))
goto FINISH;
if (shadow_extents.width == 0 || shadow_extents.height == 0)
goto FINISH;
- x_offset = shadow_extents.x - x_blur;
+ x_offset = shadow_extents.x - x_blur;
y_offset = shadow_extents.y - y_blur;
cairo_matrix_init_scale (&m, shadow_cache->scale, shadow_cache->scale);
@@ -1533,7 +1534,7 @@ _cairo_surface_inset_shadow_fill (cairo_surface_t *target,
cache_surface = cairo_surface_create_similar (target, content,
shadow_surface_extents.width,
shadow_surface_extents.height);
- if (unlikely (cache_surface->status))
+ if (unlikely (cache_surface->status))
goto FINISH;
if (device)
@@ -1587,7 +1588,7 @@ _cairo_surface_inset_shadow_fill (cairo_surface_t *target,
if (unlikely (status))
goto FINISH;
- cairo_pattern_destroy (shadow_pattern);
+ cairo_pattern_destroy (shadow_pattern);
size = shadow_surface_extents.width * shadow_surface_extents.height;
_cairo_shadow_cache_list_shrink_to_accomodate (&shadow_cache_list,
@@ -1755,7 +1756,7 @@ _cairo_surface_shadow_fill (cairo_surface_t *target,
if (shadow_cache != NULL) {
/* paint the shadow surface to target */
- color_pattern = cairo_pattern_create_rgba (shadow_copy.color.red,
+ color_pattern = cairo_pattern_create_rgba (shadow_copy.color.red,
shadow_copy.color.green,
shadow_copy.color.blue,
1.0);
@@ -1773,13 +1774,13 @@ _cairo_surface_shadow_fill (cairo_surface_t *target,
&shadow_source.base,
&shadow_path,
&shadow_extents);
- if (unlikely (status))
+ if (unlikely (status))
goto FINISH;
if (shadow_extents.width == 0 || shadow_extents.height == 0)
goto FINISH;
- x_offset = shadow_extents.x - x_blur;
+ x_offset = shadow_extents.x - x_blur;
y_offset = shadow_extents.y - y_blur;
cairo_matrix_init_scale (&m, shadow_cache->scale, shadow_cache->scale);
@@ -1843,7 +1844,7 @@ _cairo_surface_shadow_fill (cairo_surface_t *target,
cache_surface = cairo_surface_create_similar (target, content,
shadow_surface_extents.width,
shadow_surface_extents.height);
- if (unlikely (cache_surface->status))
+ if (unlikely (cache_surface->status))
goto FINISH;
if (device)
@@ -1889,7 +1890,7 @@ _cairo_surface_shadow_fill (cairo_surface_t *target,
if (unlikely (status))
goto FINISH;
- cairo_pattern_destroy (shadow_pattern);
+ cairo_pattern_destroy (shadow_pattern);
size = shadow_surface_extents.width * shadow_surface_extents.height;
_cairo_shadow_cache_list_shrink_to_accomodate (&shadow_cache_list,
@@ -2026,7 +2027,8 @@ _cairo_surface_inset_shadow_glyphs (cairo_surface_t *target,
content,
shadow_width,
shadow_height);
- _cairo_surface_release_device_reference (shadow_surface);
+ if (shadow_surface->device)
+ _cairo_surface_release_device_reference (shadow_surface);
}
if (! shadow_surface || unlikely (shadow_surface->status))
goto FINISH;
@@ -2045,7 +2047,8 @@ _cairo_surface_inset_shadow_glyphs (cairo_surface_t *target,
CAIRO_CONTENT_COLOR_ALPHA,
shadow_surface_extents.width,
shadow_surface_extents.height);
- _cairo_surface_release_device_reference (mask_surface);
+ if (mask_surface->device)
+ _cairo_surface_release_device_reference (mask_surface);
}
if (! mask_surface || unlikely (mask_surface->status))
goto FINISH;
@@ -2230,7 +2233,8 @@ _cairo_surface_shadow_glyphs (cairo_surface_t *target,
content,
shadow_width,
shadow_height);
- _cairo_surface_release_device_reference (shadow_surface);
+ if (shadow_surface->device)
+ _cairo_surface_release_device_reference (shadow_surface);
}
if (! shadow_surface || unlikely (shadow_surface->status))
goto FINISH;
diff --git a/src/cairo-surface-snapshot-inline.h b/src/cairo-surface-snapshot-inline.h
index bf89c772b..bf89c772b 100755..100644
--- a/src/cairo-surface-snapshot-inline.h
+++ b/src/cairo-surface-snapshot-inline.h
diff --git a/src/cairo-surface-snapshot-private.h b/src/cairo-surface-snapshot-private.h
index 58bee7b49..58bee7b49 100755..100644
--- a/src/cairo-surface-snapshot-private.h
+++ b/src/cairo-surface-snapshot-private.h
diff --git a/src/cairo-surface-snapshot.c b/src/cairo-surface-snapshot.c
index 68bf9054e..68bf9054e 100755..100644
--- a/src/cairo-surface-snapshot.c
+++ b/src/cairo-surface-snapshot.c
diff --git a/src/cairo-surface-subsurface-inline.h b/src/cairo-surface-subsurface-inline.h
index 0cd09e63e..0cd09e63e 100755..100644
--- a/src/cairo-surface-subsurface-inline.h
+++ b/src/cairo-surface-subsurface-inline.h
diff --git a/src/cairo-surface-subsurface-private.h b/src/cairo-surface-subsurface-private.h
index 89c5cc01b..89c5cc01b 100755..100644
--- a/src/cairo-surface-subsurface-private.h
+++ b/src/cairo-surface-subsurface-private.h
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index 0b4915e7e..5c55ac12f 100755..100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -354,10 +354,11 @@ _cairo_surface_subsurface_snapshot (void *abstract_surface)
TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, surface->target->unique_id));
- clone = _cairo_surface_create_similar_scratch (surface->target,
- surface->target->content,
- surface->extents.width,
- surface->extents.height);
+ clone = _cairo_surface_create_scratch (surface->target,
+ surface->target->content,
+ surface->extents.width,
+ surface->extents.height,
+ NULL);
if (unlikely (clone->status))
return clone;
@@ -468,7 +469,12 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target,
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- assert (_cairo_matrix_is_translation (&target->device_transform));
+ x *= target->device_transform.xx;
+ y *= target->device_transform.yy;
+
+ width *= target->device_transform.xx;
+ height *= target->device_transform.yy;
+
x += target->device_transform.x0;
y += target->device_transform.y0;
@@ -498,6 +504,10 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target,
surface->snapshot = NULL;
+ cairo_surface_set_device_scale (&surface->base,
+ target->device_transform.xx,
+ target->device_transform.yy);
+
return &surface->base;
}
@@ -518,14 +528,16 @@ _cairo_surface_create_for_rectangle_int (cairo_surface_t *target,
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- assert (_cairo_matrix_is_translation (&target->device_transform));
-
_cairo_surface_init (&surface->base,
&_cairo_surface_subsurface_backend,
NULL, /* device */
target->content);
surface->extents = *extents;
+ surface->extents.x *= target->device_transform.xx;
+ surface->extents.y *= target->device_transform.yy;
+ surface->extents.width *= target->device_transform.xx;
+ surface->extents.height *= target->device_transform.yy;
surface->extents.x += target->device_transform.x0;
surface->extents.y += target->device_transform.y0;
@@ -534,6 +546,10 @@ _cairo_surface_create_for_rectangle_int (cairo_surface_t *target,
surface->snapshot = NULL;
+ cairo_surface_set_device_scale (&surface->base,
+ target->device_transform.xx,
+ target->device_transform.yy);
+
return &surface->base;
}
/* XXX observe mark-dirty */
diff --git a/src/cairo-surface-wrapper-private.h b/src/cairo-surface-wrapper-private.h
index 6529ebc11..6529ebc11 100755..100644
--- a/src/cairo-surface-wrapper-private.h
+++ b/src/cairo-surface-wrapper-private.h
diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c
index 578e8e2be..9236c8bf4 100755..100644
--- a/src/cairo-surface-wrapper.c
+++ b/src/cairo-surface-wrapper.c
@@ -437,12 +437,11 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
_cairo_surface_wrapper_get_transform (wrapper, &m);
- if (! _cairo_matrix_is_translation (&wrapper->transform)) {
+ if (! _cairo_matrix_is_translation (&m)) {
cairo_matrix_t ctm;
- /* XXX No device-transform? A bug in the tangle of layers? */
_cairo_matrix_multiply (&ctm,
- &wrapper->transform,
+ &m,
&scaled_font->ctm);
dev_scaled_font = cairo_scaled_font_create (scaled_font->font_face,
&scaled_font->font_matrix,
@@ -514,8 +513,8 @@ _cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper,
int width,
int height)
{
- return _cairo_surface_create_similar_scratch (wrapper->target,
- content, width, height);
+ return _cairo_surface_create_scratch (wrapper->target,
+ content, width, height, NULL);
}
cairo_bool_t
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 5c6969c8a..24ad24901 100755..100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -454,33 +454,6 @@ _cairo_surface_copy_similar_properties (cairo_surface_t *surface,
other->y_fallback_resolution);
}
-cairo_surface_t *
-_cairo_surface_create_similar_scratch (cairo_surface_t *other,
- cairo_content_t content,
- int width,
- int height)
-{
- cairo_surface_t *surface;
-
- if (unlikely (other->status))
- return _cairo_surface_create_in_error (other->status);
-
- surface = NULL;
- if (other->backend->create_similar)
- surface = other->backend->create_similar (other, content, width, height);
- if (surface == NULL)
- surface = cairo_surface_create_similar_image (other,
- _cairo_format_from_content (content),
- width, height);
-
- if (unlikely (surface->status))
- return surface;
-
- _cairo_surface_copy_similar_properties (surface, other);
-
- return surface;
-}
-
/**
* cairo_surface_create_similar:
* @other: an existing surface used to select the backend of the new surface
@@ -518,6 +491,8 @@ cairo_surface_create_similar (cairo_surface_t *other,
int height)
{
cairo_surface_t *surface;
+ cairo_status_t status;
+ cairo_solid_pattern_t pattern;
if (unlikely (other->status))
return _cairo_surface_create_in_error (other->status);
@@ -529,9 +504,41 @@ cairo_surface_create_similar (cairo_surface_t *other,
if (unlikely (! CAIRO_CONTENT_VALID (content)))
return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_CONTENT);
- surface = _cairo_surface_create_similar_solid (other,
- content, width, height,
- CAIRO_COLOR_TRANSPARENT);
+ 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;
+
+ surface = NULL;
+ if (other->backend->create_similar)
+ surface = other->backend->create_similar (other, content, width, height);
+ if (surface == NULL)
+ surface = cairo_surface_create_similar_image (other,
+ _cairo_format_from_content (content),
+ width, height);
+
+ if (unlikely (surface->status))
+ return surface;
+
+ _cairo_surface_copy_similar_properties (surface, other);
+ cairo_surface_set_device_scale (surface,
+ other->device_transform.xx,
+ other->device_transform.yy);
+
+ if (unlikely (surface->status))
+ return surface;
+
+ _cairo_pattern_init_solid (&pattern, CAIRO_COLOR_TRANSPARENT);
+ status = _cairo_surface_paint (surface,
+ CAIRO_OPERATOR_CLEAR,
+ &pattern.base, NULL);
+ if (unlikely (status)) {
+ cairo_surface_destroy (surface);
+ surface = _cairo_surface_create_in_error (status);
+ }
+
assert (surface->is_clear);
return surface;
@@ -852,34 +859,78 @@ error:
}
cairo_surface_t *
-_cairo_surface_create_similar_solid (cairo_surface_t *other,
- cairo_content_t content,
- int width,
- int height,
- const cairo_color_t *color)
+_cairo_surface_create_scratch (cairo_surface_t *other,
+ cairo_content_t content,
+ int width,
+ int height,
+ const cairo_color_t *color)
{
- cairo_status_t status;
cairo_surface_t *surface;
+ cairo_status_t status;
cairo_solid_pattern_t pattern;
- surface = _cairo_surface_create_similar_scratch (other, content,
- width, height);
+ if (unlikely (other->status))
+ return _cairo_surface_create_in_error (other->status);
+
+ surface = NULL;
+ if (other->backend->create_similar)
+ surface = other->backend->create_similar (other, content, width, height);
+ if (surface == NULL)
+ surface = cairo_surface_create_similar_image (other,
+ _cairo_format_from_content (content),
+ width, height);
+
if (unlikely (surface->status))
return surface;
- _cairo_pattern_init_solid (&pattern, color);
- status = _cairo_surface_paint (surface,
- color == CAIRO_COLOR_TRANSPARENT ?
- CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
- &pattern.base, NULL);
- if (unlikely (status)) {
- cairo_surface_destroy (surface);
- surface = _cairo_surface_create_in_error (status);
+ _cairo_surface_copy_similar_properties (surface, other);
+
+ if (unlikely (surface->status))
+ return surface;
+
+ if (color) {
+ _cairo_pattern_init_solid (&pattern, color);
+ status = _cairo_surface_paint (surface,
+ color == CAIRO_COLOR_TRANSPARENT ?
+ CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
+ &pattern.base, NULL);
+ if (unlikely (status)) {
+ cairo_surface_destroy (surface);
+ surface = _cairo_surface_create_in_error (status);
+ }
}
return surface;
}
+cairo_surface_t *
+_cairo_surface_create_similar_scratch (cairo_surface_t *other,
+ cairo_content_t content,
+ int width,
+ int height)
+{
+ cairo_surface_t *surface;
+
+ if (unlikely (other->status))
+ return _cairo_surface_create_in_error (other->status);
+
+ surface = NULL;
+ if (other->backend->create_similar)
+ surface = other->backend->create_similar (other, content, width, height);
+ if (surface == NULL)
+ surface = cairo_surface_create_similar_image (other,
+ _cairo_format_from_content (content),
+ width, height);
+
+ if (unlikely (surface->status))
+ return surface;
+
+ _cairo_surface_copy_similar_properties (surface, other);
+
+ return surface;
+}
+
+
/**
* cairo_surface_reference:
* @surface: a #cairo_surface_t
@@ -1200,6 +1251,31 @@ _cairo_mime_data_destroy (void *ptr)
}
/**
+ * CAIRO_MIME_TYPE_JBIG2:
+ *
+ * Joint Bi-level Image Experts Group image coding standard (ISO/IEC 11544).
+ *
+ * Since: 1.14
+ **/
+
+/**
+ * CAIRO_MIME_TYPE_JBIG2_GLOBAL:
+ *
+ * Joint Bi-level Image Experts Group image coding standard (ISO/IEC 11544) global segment.
+ *
+ * Since: 1.14
+ **/
+
+/**
+ * CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID:
+ *
+ * An unique identifier shared by a JBIG2 global segment and all JBIG2 images
+ * that depend on the global segment.
+ *
+ * Since: 1.14
+ **/
+
+/**
* CAIRO_MIME_TYPE_JP2:
*
* The Joint Photographic Experts Group (JPEG) 2000 image coding standard (ISO/IEC 15444-1).
@@ -1234,7 +1310,8 @@ _cairo_mime_data_destroy (void *ptr)
/**
* CAIRO_MIME_TYPE_UNIQUE_ID:
*
- * Unique identifier for a surface (cairo specific MIME type).
+ * Unique identifier for a surface (cairo specific MIME type). All surfaces with
+ * the same unique identifier will only be embedded once.
*
* Since: 1.12
**/
@@ -1262,13 +1339,24 @@ _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_UNIQUE_ID, %CAIRO_MIME_TYPE_JBIG2,
+ * %CAIRO_MIME_TYPE_JBIG2_GLOBAL, %CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID.
*
* See corresponding backend surface docs for details about which MIME
* types it can handle. Caution: the associated MIME data will be
* discarded if you draw on the surface afterwards. Use this function
* with care.
*
+ * Even if a backend supports a MIME type, that does not mean cairo
+ * will always be able to use the attached MIME data. For example, if
+ * the backend does not natively support the compositing operation used
+ * to apply the MIME data to the backend. In that case, the MIME data
+ * will be ignored. Therefore, to apply an image in all cases, it is best
+ * to create an image surface which contains the decoded image data and
+ * then attach the MIME data to that. This ensures the image will always
+ * be used while still allowing the MIME data to be used whenever
+ * possible.
+ *
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
* slot could not be allocated for the user data.
*
@@ -1346,6 +1434,13 @@ cairo_surface_supports_mime_type (cairo_surface_t *surface,
{
const char **types;
+ if (unlikely (surface->status))
+ return FALSE;
+ if (unlikely (surface->finished)) {
+ _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
+ return FALSE;
+ }
+
if (surface->backend->get_supported_mime_types) {
types = surface->backend->get_supported_mime_types (surface);
if (types) {
@@ -1617,26 +1712,28 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
slim_hidden_def (cairo_surface_mark_dirty_rectangle);
/**
- * _cairo_surface_set_device_scale:
+ * cairo_surface_set_device_scale:
* @surface: a #cairo_surface_t
- * @sx: a scale factor in the X direction
- * @sy: a scale factor in the Y direction
- *
- * Private function for setting an extra scale factor to affect all
- * drawing to a surface. This is used, for example, when replaying a
- * recording surface to an image fallback intended for an eventual
- * vector-oriented backend. Since the recording surface will record
- * coordinates in one backend space, but the image fallback uses a
- * different backend space, (differing by the fallback resolution
- * scale factors), we need a scale factor correction.
- *
- * Caution: Not all places we use device transform correctly handle
- * both a translate and a scale. An audit would be nice.
+ * @x_scale: a scale factor in the X direction
+ * @y_scale: a scale factor in the Y direction
+ *
+ * Sets a scale that is multiplied to the device coordinates determined
+ * by the CTM when drawing to @surface. One common use for this is to
+ * render to very high resolution display devices at a scale factor, so
+ * that code that assumes 1 pixel will be a certain size will still work.
+ * Setting a transformation via cairo_translate() isn't
+ * sufficient to do this, since functions like
+ * cairo_device_to_user() will expose the hidden scale.
+ *
+ * Note that the scale affects drawing to the surface as well as
+ * using the surface in a source pattern.
+ *
+ * Since: 1.14
**/
void
-_cairo_surface_set_device_scale (cairo_surface_t *surface,
- double sx,
- double sy)
+cairo_surface_set_device_scale (cairo_surface_t *surface,
+ double x_scale,
+ double y_scale)
{
cairo_status_t status;
@@ -1656,8 +1753,8 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
return;
}
- surface->device_transform.xx = sx;
- surface->device_transform.yy = sy;
+ surface->device_transform.xx = x_scale;
+ surface->device_transform.yy = y_scale;
surface->device_transform.xy = 0.0;
surface->device_transform.yx = 0.0;
@@ -1668,6 +1765,30 @@ _cairo_surface_set_device_scale (cairo_surface_t *surface,
_cairo_observers_notify (&surface->device_transform_observers, surface);
}
+slim_hidden_def (cairo_surface_set_device_scale);
+
+/**
+ * cairo_surface_get_device_scale:
+ * @surface: a #cairo_surface_t
+ * @x_scale: the scale in the X direction, in device units
+ * @y_scale: the scale in the Y direction, in device units
+ *
+ * This function returns the previous device offset set by
+ * cairo_surface_set_device_scale().
+ *
+ * Since: 1.14
+ **/
+void
+cairo_surface_get_device_scale (cairo_surface_t *surface,
+ double *x_scale,
+ double *y_scale)
+{
+ if (x_scale)
+ *x_scale = surface->device_transform.xx;
+ if (y_scale)
+ *y_scale = surface->device_transform.yy;
+}
+slim_hidden_def (cairo_surface_get_device_scale);
/**
* cairo_surface_set_device_offset:
@@ -2004,6 +2125,8 @@ _cairo_surface_paint (cairo_surface_t *surface,
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 (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
@@ -2040,6 +2163,8 @@ _cairo_surface_mask (cairo_surface_t *surface,
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 (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
@@ -2097,6 +2222,8 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
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 (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
@@ -2177,6 +2304,8 @@ _cairo_surface_stroke (cairo_surface_t *surface,
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 (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
@@ -2220,6 +2349,8 @@ _cairo_surface_fill (cairo_surface_t *surface,
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 (_cairo_clip_is_all_clipped (clip))
return CAIRO_STATUS_SUCCESS;
@@ -2351,6 +2482,13 @@ _cairo_surface_get_extents (cairo_surface_t *surface,
{
cairo_bool_t bounded;
+ if (unlikely (surface->status))
+ goto zero_extents;
+ if (unlikely (surface->finished)) {
+ _cairo_surface_set_error(surface, CAIRO_STATUS_SURFACE_FINISHED);
+ goto zero_extents;
+ }
+
bounded = FALSE;
if (surface->backend->get_extents != NULL)
bounded = surface->backend->get_extents (surface, extents);
@@ -2359,6 +2497,11 @@ _cairo_surface_get_extents (cairo_surface_t *surface,
_cairo_unbounded_rectangle_init (extents);
return bounded;
+
+zero_extents:
+ extents->x = extents->y = 0;
+ extents->width = extents->height = 0;
+ return TRUE;
}
/**
@@ -2430,11 +2573,12 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
const cairo_clip_t *clip)
{
cairo_int_status_t status;
- cairo_scaled_font_t *dev_scaled_font = scaled_font;
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 (num_glyphs == 0 && utf8_len == 0)
return CAIRO_STATUS_SUCCESS;
@@ -2453,25 +2597,6 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
if (unlikely (status))
return status;
- if (_cairo_surface_has_device_transform (surface) &&
- ! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL))
- {
- cairo_font_options_t font_options;
- cairo_matrix_t dev_ctm, font_matrix;
-
- cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
- cairo_scaled_font_get_ctm (scaled_font, &dev_ctm);
- cairo_matrix_multiply (&dev_ctm, &dev_ctm, &surface->device_transform);
- cairo_scaled_font_get_font_options (scaled_font, &font_options);
- dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font),
- &font_matrix,
- &dev_ctm,
- &font_options);
- }
- status = cairo_scaled_font_status (dev_scaled_font);
- if (unlikely (status))
- return _cairo_surface_set_error (surface, status);
-
status = CAIRO_INT_STATUS_UNSUPPORTED;
/* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
@@ -2485,7 +2610,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters, cluster_flags,
- dev_scaled_font,
+ scaled_font,
clip);
}
if (status == CAIRO_INT_STATUS_UNSUPPORTED &&
@@ -2494,7 +2619,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
status = surface->backend->show_glyphs (surface, op,
source,
glyphs, num_glyphs,
- dev_scaled_font,
+ scaled_font,
clip);
}
} else {
@@ -2503,7 +2628,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
status = surface->backend->show_glyphs (surface, op,
source,
glyphs, num_glyphs,
- dev_scaled_font,
+ scaled_font,
clip);
} else if (surface->backend->show_text_glyphs != NULL) {
/* Intentionally only try show_text_glyphs method for show_glyphs
@@ -2519,14 +2644,11 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters, cluster_flags,
- dev_scaled_font,
+ scaled_font,
clip);
}
}
- if (dev_scaled_font != scaled_font)
- cairo_scaled_font_destroy (dev_scaled_font);
-
if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
surface->is_clear = FALSE;
surface->serial++;
@@ -2557,6 +2679,16 @@ _cairo_surface_set_resolution (cairo_surface_t *surface,
surface->y_resolution = y_res;
}
+/**
+ * _cairo_surface_create_in_error:
+ * @status: the error status
+ *
+ * Return an appropriate static error surface for the error status.
+ * On error, surface creation functions should always return a surface
+ * created with _cairo_surface_create_in_error() instead of a new surface
+ * in an error state. This simplifies internal code as no refcounting has
+ * to be done.
+ **/
cairo_surface_t *
_cairo_surface_create_in_error (cairo_status_t status)
{
@@ -2617,6 +2749,7 @@ _cairo_surface_create_in_error (cairo_status_t status)
case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
case CAIRO_STATUS_DEVICE_FINISHED:
+ case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t *) &_cairo_surface_nil;
diff --git a/src/cairo-svg-surface-private.h b/src/cairo-svg-surface-private.h
index ddbf464b1..ddbf464b1 100755..100644
--- a/src/cairo-svg-surface-private.h
+++ b/src/cairo-svg-surface-private.h
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index e2d99499d..04bb7a093 100755..100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -56,6 +56,7 @@
#include "cairo-paginated-private.h"
#include "cairo-scaled-font-subsets-private.h"
#include "cairo-surface-clipper-private.h"
+#include "cairo-surface-snapshot-inline.h"
#include "cairo-svg-surface-private.h"
/**
@@ -810,7 +811,7 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
_cairo_output_stream_printf (document->xml_node_glyphs, "<g");
_cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform",
&image->base.device_transform_inverse, NULL);
- _cairo_output_stream_printf (document->xml_node_glyphs, ">/n");
+ _cairo_output_stream_printf (document->xml_node_glyphs, ">\n");
for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) {
for (x = 0, byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
@@ -1120,6 +1121,9 @@ _cairo_surface_base64_encode_jpeg (cairo_surface_t *surface,
if (unlikely (status))
return status;
+ if (image_info.num_components == 4)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
_cairo_output_stream_printf (output, "data:image/jpeg;base64,");
info.output = output;
@@ -1493,6 +1497,17 @@ _cairo_svg_surface_emit_recording_surface (cairo_svg_document_t *document,
document, NULL);
}
+static cairo_recording_surface_t *
+to_recording_surface (const cairo_surface_pattern_t *pattern)
+{
+ cairo_surface_t *surface = pattern->surface;
+ if (_cairo_surface_is_paginated (surface))
+ surface = _cairo_paginated_surface_get_recording (surface);
+ if (_cairo_surface_is_snapshot (surface))
+ surface = _cairo_surface_snapshot_get_target (surface);
+ return (cairo_recording_surface_t *) surface;
+}
+
static cairo_status_t
_cairo_svg_surface_emit_composite_recording_pattern (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
@@ -1512,7 +1527,7 @@ _cairo_svg_surface_emit_composite_recording_pattern (cairo_output_stream_t *outp
/* cairo_pattern_set_matrix ensures the matrix is invertible */
assert (status == CAIRO_STATUS_SUCCESS);
- recording_surface = (cairo_recording_surface_t *) pattern->surface;
+ recording_surface = to_recording_surface (pattern);
status = _cairo_svg_surface_emit_recording_surface (document, recording_surface);
if (unlikely (status))
return status;
@@ -1559,7 +1574,7 @@ _cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output,
const char *extra_attributes)
{
- if (_cairo_surface_is_recording (pattern->surface)) {
+ if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
return _cairo_svg_surface_emit_composite_recording_pattern (output, surface,
op, pattern,
pattern_id,
diff --git a/src/cairo-svg.h b/src/cairo-svg.h
index 592c645f6..592c645f6 100755..100644
--- a/src/cairo-svg.h
+++ b/src/cairo-svg.h
diff --git a/src/cairo-tee-surface-private.h b/src/cairo-tee-surface-private.h
index a83cfc959..a83cfc959 100755..100644
--- a/src/cairo-tee-surface-private.h
+++ b/src/cairo-tee-surface-private.h
diff --git a/src/cairo-tee-surface.c b/src/cairo-tee-surface.c
index 294e5f162..294e5f162 100755..100644
--- a/src/cairo-tee-surface.c
+++ b/src/cairo-tee-surface.c
diff --git a/src/cairo-tee.h b/src/cairo-tee.h
index 9125a3a4a..9125a3a4a 100755..100644
--- a/src/cairo-tee.h
+++ b/src/cairo-tee.h
diff --git a/src/cairo-tg-allocator-private.h b/src/cairo-tg-allocator-private.h
deleted file mode 100755
index f62b2e211..000000000
--- a/src/cairo-tg-allocator-private.h
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef CAIRO_TG_ALLOCATOR_H
-#define CAIRO_TG_ALLOCATOR_H
-
-#include "cairoint.h"
-
-typedef struct _cairo_tg_mem_chunk cairo_tg_mem_chunk_t;
-
-struct _cairo_tg_mem_chunk
-{
- cairo_tg_mem_chunk_t *next;
- uint8_t *buffer;
- int chunk_size;
- int remaining_size;
-};
-
-typedef struct _cairo_tg_mono_allocator
-{
- cairo_tg_mem_chunk_t *chunk_head;
- int chunk_size;
-} cairo_tg_mono_allocator_t;
-
-static inline cairo_tg_mem_chunk_t *
-_cairo_tg_mem_chunk_create (int chunk_size)
-{
- cairo_tg_mem_chunk_t *chunk;
-
- chunk = (cairo_tg_mem_chunk_t *) malloc (sizeof (cairo_tg_mem_chunk_t) + chunk_size);
-
- if (chunk)
- {
- chunk->next = NULL;
- chunk->buffer = (uint8_t *) chunk + sizeof (cairo_tg_mem_chunk_t);
- chunk->chunk_size = chunk_size;
- chunk->remaining_size = chunk_size;
- }
-
- return chunk;
-}
-
-static inline void
-_cairo_tg_mem_chunk_destroy (cairo_tg_mem_chunk_t *chunk)
-{
- free (chunk);
-}
-
-static inline cairo_status_t
-_cairo_tg_mono_allocator_init (cairo_tg_mono_allocator_t *allocator, int chunk_size)
-{
- cairo_tg_mem_chunk_t *chunk;
-
- chunk = _cairo_tg_mem_chunk_create (chunk_size);
-
- if (! chunk)
- return CAIRO_STATUS_NO_MEMORY;
-
- allocator->chunk_size = chunk_size;
- allocator->chunk_head = chunk;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static inline void
-_cairo_tg_mono_allocator_fini (cairo_tg_mono_allocator_t *allocator)
-{
- cairo_tg_mem_chunk_t *chunk = allocator->chunk_head, *next;
-
- while (chunk != NULL)
- {
- next = chunk->next;
- _cairo_tg_mem_chunk_destroy (chunk);
- chunk = next;
- }
-
- allocator->chunk_head = NULL;
-}
-
-static inline void *
-_cairo_tg_mono_allocator_alloc (cairo_tg_mono_allocator_t *allocator, int size)
-{
- cairo_tg_mem_chunk_t *chunk = allocator->chunk_head;
- int chunk_size;
-
- if (chunk && chunk->remaining_size >= size)
- {
- void *buffer = (void*)(chunk->buffer + chunk->chunk_size - chunk->remaining_size);
- chunk->remaining_size -= size;
- return buffer;
- }
-
- chunk_size = MAX (allocator->chunk_size, size);
-
- chunk = _cairo_tg_mem_chunk_create (chunk_size);
-
- if (chunk == NULL)
- return NULL;
-
- chunk->next = allocator->chunk_head;
- chunk->buffer = (uint8_t *) chunk + sizeof (cairo_tg_mem_chunk_t);
- chunk->chunk_size = chunk_size;
- chunk->remaining_size = chunk_size - size;
-
- allocator->chunk_head = chunk;
-
- return (void *) chunk->buffer;
-}
-
-static inline void
-_cairo_tg_mono_allocator_reset (cairo_tg_mono_allocator_t *allocator)
-{
- cairo_tg_mem_chunk_t *chunk = allocator->chunk_head, *next;
- cairo_tg_mem_chunk_t *stock = NULL;
-
- while (chunk != NULL)
- {
- next = chunk->next;
-
- if (stock)
- _cairo_tg_mem_chunk_destroy (chunk);
- else
- stock = chunk;
-
- chunk = next;
- }
-
- if (stock)
- {
- stock->next = NULL;
- stock->remaining_size = stock->chunk_size;
- }
-
- allocator->chunk_head = stock;
-}
-
-#endif /* CAIRO_TG_ALLOCATOR_H */
diff --git a/src/cairo-tg-composite-extents-private.h b/src/cairo-tg-composite-extents-private.h
deleted file mode 100755
index 22de139bf..000000000
--- a/src/cairo-tg-composite-extents-private.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright © 2012 SCore Corporation
- *
- * 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.
- *
- * Author: Taekyun Kim (podain77@gmail.com)
- */
-
-#ifndef CAIRO_TG_COMPOSITE_EXTENTS_PRIVATE_H
-#define CAIRO_TG_COMPOSITE_EXTENTS_PRIVATE_H
-
-#include "cairoint.h"
-#include "cairo-pattern-private.h"
-#include "cairo-clip-private.h"
-#include "cairo-surface-private.h"
-
-static inline void
-_cairo_tg_approximate_paint_extents (cairo_rectangle_int_t *extents,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_clip_t *clip)
-{
- *extents = * (_cairo_clip_get_extents (clip));
-}
-
-static inline void
-_cairo_tg_approximate_mask_extents (cairo_rectangle_int_t *extents,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
- const cairo_clip_t *clip)
-{
- *extents = * (_cairo_clip_get_extents (clip));
-}
-
-static inline void
-_cairo_tg_approximate_stroke_extents (cairo_rectangle_int_t *extents,
- 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_rectangle_int_t rect;
-
- *extents = * (_cairo_clip_get_extents (clip));
-
- if (_cairo_operator_bounded_by_either (op))
- {
- _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &rect);
- _cairo_rectangle_intersect (extents, &rect);
- }
-}
-
-static inline void
-_cairo_tg_approximate_fill_extents (cairo_rectangle_int_t *extents,
- 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_rectangle_int_t rect;
-
- *extents = * (_cairo_clip_get_extents (clip));
-
- if (_cairo_operator_bounded_by_either (op))
- {
- _cairo_path_fixed_approximate_fill_extents (path, &rect);
- _cairo_rectangle_intersect (extents, &rect);
- }
-}
-
-static inline void
-_cairo_tg_approximate_glyphs_extents (cairo_rectangle_int_t *extents,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- const cairo_clip_t *clip)
-{
- cairo_rectangle_int_t rect;
-
- *extents = * (_cairo_clip_get_extents (clip));
-
- if (_cairo_operator_bounded_by_either (op))
- {
- if (_cairo_scaled_font_glyph_approximate_extents (scaled_font, glyphs, num_glyphs, &rect))
- _cairo_rectangle_intersect (extents, &rect);
- }
-}
-
-#endif /* CAIRO_TG_COMPOSITE_EXTENTS_PRIVATE_H */
diff --git a/src/cairo-tg-journal-private.h b/src/cairo-tg-journal-private.h
deleted file mode 100755
index 694f77cfd..000000000
--- a/src/cairo-tg-journal-private.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright © 2012 SCore Corporation
- *
- * 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.
- *
- * Author: Taekyun Kim (podain77@gmail.com)
- */
-
-#ifndef CAIRO_TG_JOURNAL_PRIVATE_H
-#define CAIRO_TG_JOURNAL_PRIVATE_H
-
-#include "cairoint.h"
-#include "cairo-pattern-private.h"
-#include "cairo-clip-private.h"
-#include "cairo-surface-private.h"
-#include "cairo-list-private.h"
-#include "cairo-list-inline.h"
-#include "cairo-tg-allocator-private.h"
-#include "cairo-mutex-private.h"
-
-typedef enum
-{
- CAIRO_TG_JOURNAL_ENTRY_PAINT,
- CAIRO_TG_JOURNAL_ENTRY_MASK,
- CAIRO_TG_JOURNAL_ENTRY_FILL,
- CAIRO_TG_JOURNAL_ENTRY_STROKE,
- CAIRO_TG_JOURNAL_ENTRY_GLYPHS,
-} cairo_tg_journal_entry_type_t;
-
-typedef struct _cairo_tg_journal_entry cairo_tg_journal_entry_t;
-
-struct _cairo_tg_journal_entry
-{
- cairo_list_t link;
- cairo_tg_journal_entry_type_t type;
-
- cairo_rectangle_int_t extents;
-
- cairo_operator_t op;
- cairo_pattern_union_t source;
- cairo_clip_t *clip;
-};
-
-typedef struct _cairo_tg_journal_entry_paint
-{
- cairo_tg_journal_entry_t base;
-} cairo_tg_journal_entry_paint_t;
-
-typedef struct _cairo_tg_journal_entry_mask
-{
- cairo_tg_journal_entry_t base;
-
- cairo_pattern_union_t mask;
-} cairo_tg_journal_entry_mask_t;
-
-typedef struct _cairo_tg_journal_entry_stroke
-{
- cairo_tg_journal_entry_t base;
-
- cairo_path_fixed_t path;
- cairo_stroke_style_t style;
- cairo_matrix_t ctm;
- cairo_matrix_t ctm_inverse;
- double tolerance;
- cairo_antialias_t antialias;
-} cairo_tg_journal_entry_stroke_t;
-
-typedef struct _cairo_tg_journal_entry_fill
-{
- cairo_tg_journal_entry_t base;
-
- cairo_path_fixed_t path;
- cairo_fill_rule_t fill_rule;
- double tolerance;
- cairo_antialias_t antialias;
-} cairo_tg_journal_entry_fill_t;
-
-typedef struct _cairo_tg_journal_entry_glyphs
-{
- cairo_tg_journal_entry_t base;
-
- cairo_glyph_t *glyphs;
- int num_glyphs;
- cairo_scaled_font_t *scaled_font;
-} cairo_tg_journal_entry_glyphs_t;
-
-typedef struct _cairo_tg_journal
-{
- cairo_rectangle_int_t extents;
- cairo_list_t entry_list;
- int num_entries;
- cairo_tg_mono_allocator_t allocator;
- cairo_mutex_t mutex;
-} cairo_tg_journal_t;
-
-typedef struct _cairo_tg_journal_replay_funcs
-{
- cairo_int_status_t
- (*paint) (void *closure,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_clip_t *clip);
-
- cairo_int_status_t
- (*mask) (void *closure,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
- const cairo_clip_t *clip);
-
- cairo_int_status_t
- (*stroke) (void *closure,
- 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_int_status_t
- (*fill) (void *closure,
- 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_int_status_t
- (*glyphs) (void *closure,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- const cairo_clip_t *clip);
-} cairo_tg_journal_replay_funcs_t;
-
-cairo_int_status_t
-_cairo_tg_journal_init (cairo_tg_journal_t *journal);
-
-void
-_cairo_tg_journal_fini (cairo_tg_journal_t *journal);
-
-void
-_cairo_tg_journal_lock (cairo_tg_journal_t *journal);
-
-void
-_cairo_tg_journal_unlock (cairo_tg_journal_t *journal);
-
-cairo_int_status_t
-_cairo_tg_journal_log_paint (cairo_tg_journal_t *journal,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_clip_t *clip);
-
-cairo_int_status_t
-_cairo_tg_journal_log_mask (cairo_tg_journal_t *journal,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
- const cairo_clip_t *clip);
-
-cairo_int_status_t
-_cairo_tg_journal_log_stroke (cairo_tg_journal_t *journal,
- 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_int_status_t
-_cairo_tg_journal_log_fill (cairo_tg_journal_t *journal,
- 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_int_status_t
-_cairo_tg_journal_log_glyphs (cairo_tg_journal_t *journal,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- const cairo_clip_t *clip);
-
-void
-_cairo_tg_journal_clear (cairo_tg_journal_t *journal);
-
-cairo_int_status_t
-_cairo_tg_journal_replay (const cairo_tg_journal_t *journal,
- void *closure,
- const cairo_rectangle_int_t *extents,
- const cairo_tg_journal_replay_funcs_t *funcs);
-
-#endif /* CAIRO_TG_JOURNAL_PRIVATE_H */
diff --git a/src/cairo-tg-journal.c b/src/cairo-tg-journal.c
deleted file mode 100755
index 1d3902134..000000000
--- a/src/cairo-tg-journal.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright © 2012 SCore Corporation
- *
- * 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.
- *
- * Author: Taekyun Kim (podain77@gmail.com)
- */
-
-#include "cairo-tg.h"
-#include "cairo-tg-private.h"
-#include "cairo-tg-journal-private.h"
-#include "cairo-tg-allocator-private.h"
-#include "cairo-tg-composite-extents-private.h"
-
-static inline cairo_int_status_t
-_cairo_tg_journal_pattern_snapshot (cairo_pattern_t *dst,
- const cairo_pattern_t *src)
-{
- return _cairo_pattern_init_snapshot (dst, src);
-}
-
-/* Allocator for various types of journal entries. */
-static cairo_tg_journal_entry_t *
-_cairo_tg_journal_entry_alloc (cairo_tg_mono_allocator_t *allocator,
- cairo_tg_journal_entry_type_t type)
-{
- cairo_tg_journal_entry_t *entry = NULL;
-
- switch (type)
- {
- case CAIRO_TG_JOURNAL_ENTRY_PAINT:
- entry = _cairo_tg_mono_allocator_alloc (allocator,
- sizeof (cairo_tg_journal_entry_paint_t));
- break;
- case CAIRO_TG_JOURNAL_ENTRY_MASK:
- entry = _cairo_tg_mono_allocator_alloc (allocator,
- sizeof (cairo_tg_journal_entry_mask_t));
- break;
- case CAIRO_TG_JOURNAL_ENTRY_STROKE:
- entry = _cairo_tg_mono_allocator_alloc (allocator,
- sizeof (cairo_tg_journal_entry_stroke_t));
- break;
- case CAIRO_TG_JOURNAL_ENTRY_FILL:
- entry = _cairo_tg_mono_allocator_alloc (allocator,
- sizeof (cairo_tg_journal_entry_fill_t));
- break;
- case CAIRO_TG_JOURNAL_ENTRY_GLYPHS:
- entry = _cairo_tg_mono_allocator_alloc (allocator,
- sizeof (cairo_tg_journal_entry_glyphs_t));
- break;
- default:
- ASSERT_NOT_REACHED;
- return NULL;
- }
-
- /* One should not change the type of an entry.
- * It is determined at the moment of allocation. */
- entry->type = type;
-
- return entry;
-}
-
-static void
-_cairo_tg_journal_entry_fini (cairo_tg_journal_entry_t *entry)
-{
- /* common part. */
- _cairo_pattern_fini (&entry->source.base);
-
- if (entry->clip)
- _cairo_clip_destroy (entry->clip);
-
- /* For each entry types... */
- switch (entry->type)
- {
- case CAIRO_TG_JOURNAL_ENTRY_PAINT:
- break;
- case CAIRO_TG_JOURNAL_ENTRY_MASK:
- {
- cairo_tg_journal_entry_mask_t *entry_mask =
- (cairo_tg_journal_entry_mask_t *) entry;
-
- _cairo_pattern_fini (&entry_mask->mask.base);
- }
- break;
- case CAIRO_TG_JOURNAL_ENTRY_STROKE:
- {
- cairo_tg_journal_entry_stroke_t *entry_stroke =
- (cairo_tg_journal_entry_stroke_t *) entry;
-
- _cairo_path_fixed_fini (&entry_stroke->path);
- _cairo_stroke_style_fini (&entry_stroke->style);
- }
- break;
- case CAIRO_TG_JOURNAL_ENTRY_FILL:
- {
- cairo_tg_journal_entry_fill_t *entry_fill =
- (cairo_tg_journal_entry_fill_t *) entry;
-
- _cairo_path_fixed_fini (&entry_fill->path);
- }
- break;
- case CAIRO_TG_JOURNAL_ENTRY_GLYPHS:
- {
- cairo_tg_journal_entry_glyphs_t *entry_glyphs =
- (cairo_tg_journal_entry_glyphs_t *) entry;
-
- free (entry_glyphs->glyphs);
- cairo_scaled_font_destroy (entry_glyphs->scaled_font);
- }
- break;
- default:
- ASSERT_NOT_REACHED;
- }
-}
-
-cairo_int_status_t
-_cairo_tg_journal_init (cairo_tg_journal_t *journal)
-{
- cairo_int_status_t status;
-
- CAIRO_MUTEX_INIT (journal->mutex);
- journal->num_entries = 0;
- cairo_list_init (&journal->entry_list);
- journal->extents = _cairo_empty_rectangle;
-
- status = _cairo_tg_mono_allocator_init (&journal->allocator, 4096 -
- sizeof (cairo_tg_mem_chunk_t));
-
- return status;
-}
-
-void
-_cairo_tg_journal_fini (cairo_tg_journal_t *journal)
-{
- cairo_tg_journal_entry_t *entry;
- cairo_tg_journal_entry_t *next;
-
- CAIRO_MUTEX_FINI (journal->mutex);
- cairo_list_foreach_entry_safe (entry, next, cairo_tg_journal_entry_t,
- &journal->entry_list, link)
- {
- _cairo_tg_journal_entry_fini (entry);
- }
-
- _cairo_tg_mono_allocator_fini (&journal->allocator);
-}
-
-void
-_cairo_tg_journal_lock (cairo_tg_journal_t *journal)
-{
- CAIRO_MUTEX_LOCK (journal->mutex);
-}
-
-void
-_cairo_tg_journal_unlock (cairo_tg_journal_t *journal)
-{
- CAIRO_MUTEX_UNLOCK (journal->mutex);
-}
-
-cairo_int_status_t
-_cairo_tg_journal_log_paint (cairo_tg_journal_t *journal,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_clip_t *clip)
-{
- cairo_int_status_t status;
- cairo_tg_journal_entry_paint_t *entry;
-
- entry = (cairo_tg_journal_entry_paint_t *)
- _cairo_tg_journal_entry_alloc (&journal->allocator, CAIRO_TG_JOURNAL_ENTRY_PAINT);
-
- if (unlikely (entry == NULL))
- return CAIRO_INT_STATUS_NO_MEMORY;
-
- status = _cairo_tg_journal_pattern_snapshot (&entry->base.source.base, source);
-
- if (unlikely (status))
- return status;
-
- entry->base.op = op;
- entry->base.clip = _cairo_clip_copy (clip);
- _cairo_tg_approximate_paint_extents (&entry->base.extents, op, source, clip);
- _cairo_rectangle_union (&journal->extents, &entry->base.extents);
-
- cairo_list_add_tail (&entry->base.link, &journal->entry_list);
- journal->num_entries++;
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-cairo_int_status_t
-_cairo_tg_journal_log_mask (cairo_tg_journal_t *journal,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
- const cairo_clip_t *clip)
-{
- cairo_int_status_t status;
- cairo_tg_journal_entry_mask_t *entry;
-
- entry = (cairo_tg_journal_entry_mask_t *)
- _cairo_tg_journal_entry_alloc (&journal->allocator, CAIRO_TG_JOURNAL_ENTRY_MASK);
-
- if (unlikely (entry == NULL))
- return CAIRO_INT_STATUS_NO_MEMORY;
-
- status = _cairo_tg_journal_pattern_snapshot (&entry->base.source.base, source);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_tg_journal_pattern_snapshot (&entry->mask.base, mask);
-
- if (unlikely (status))
- {
- _cairo_pattern_fini (&entry->base.source.base);
- return status;
- }
-
- entry->base.op = op;
- entry->base.clip = _cairo_clip_copy (clip);
- _cairo_tg_approximate_mask_extents (&entry->base.extents, op, source, mask, clip);
- _cairo_rectangle_union (&journal->extents, &entry->base.extents);
-
- cairo_list_add_tail (&entry->base.link, &journal->entry_list);
- journal->num_entries++;
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-cairo_int_status_t
-_cairo_tg_journal_log_stroke (cairo_tg_journal_t *journal,
- 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_int_status_t status;
- cairo_tg_journal_entry_stroke_t *entry;
-
- entry = (cairo_tg_journal_entry_stroke_t *)
- _cairo_tg_journal_entry_alloc (&journal->allocator, CAIRO_TG_JOURNAL_ENTRY_STROKE);
-
- if (unlikely (entry == NULL))
- return CAIRO_INT_STATUS_NO_MEMORY;
-
- status = _cairo_tg_journal_pattern_snapshot (&entry->base.source.base, source);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_path_fixed_init_copy (&entry->path, path);
-
- if (unlikely (status))
- {
- _cairo_pattern_fini (&entry->base.source.base);
- return status;
- }
-
- status = _cairo_stroke_style_init_copy (&entry->style, style);
-
- if (unlikely (status))
- {
- _cairo_path_fixed_fini (&entry->path);
- _cairo_pattern_fini (&entry->base.source.base);
- return status;
- }
-
- entry->base.op = op;
- entry->base.clip = _cairo_clip_copy (clip);
- entry->ctm = *ctm;
- entry->ctm_inverse = *ctm_inverse;
- entry->tolerance = tolerance;
- entry->antialias = antialias;
- _cairo_tg_approximate_stroke_extents (&entry->base.extents, op, source,
- path, style, ctm, ctm_inverse,
- tolerance, antialias, clip);
- _cairo_rectangle_union (&journal->extents, &entry->base.extents);
-
- cairo_list_add_tail (&entry->base.link, &journal->entry_list);
- journal->num_entries++;
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-cairo_int_status_t
-_cairo_tg_journal_log_fill (cairo_tg_journal_t *journal,
- 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_int_status_t status;
- cairo_tg_journal_entry_fill_t *entry;
-
- entry = (cairo_tg_journal_entry_fill_t *)
- _cairo_tg_journal_entry_alloc (&journal->allocator, CAIRO_TG_JOURNAL_ENTRY_FILL);
-
- if (unlikely (entry == NULL))
- return CAIRO_INT_STATUS_NO_MEMORY;
-
- status = _cairo_tg_journal_pattern_snapshot (&entry->base.source.base, source);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_path_fixed_init_copy (&entry->path, path);
-
- if (unlikely (status))
- {
- _cairo_pattern_fini (&entry->base.source.base);
- return status;
- }
-
- entry->base.op = op;
- entry->base.clip = _cairo_clip_copy (clip);
- entry->fill_rule = fill_rule;
- entry->tolerance = tolerance;
- entry->antialias = antialias;
- _cairo_tg_approximate_fill_extents (&entry->base.extents, op, source,
- path, fill_rule, tolerance, antialias, clip);
- _cairo_rectangle_union (&journal->extents, &entry->base.extents);
-
- cairo_list_add_tail (&entry->base.link, &journal->entry_list);
- journal->num_entries++;
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-cairo_int_status_t
-_cairo_tg_journal_log_glyphs (cairo_tg_journal_t *journal,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- const cairo_clip_t *clip)
-{
- cairo_int_status_t status;
- cairo_tg_journal_entry_glyphs_t *entry;
-
- entry = (cairo_tg_journal_entry_glyphs_t *)
- _cairo_tg_journal_entry_alloc (&journal->allocator, CAIRO_TG_JOURNAL_ENTRY_GLYPHS);
-
- if (unlikely (entry == NULL))
- return CAIRO_INT_STATUS_NO_MEMORY;
-
- status = _cairo_tg_journal_pattern_snapshot (&entry->base.source.base, source);
-
- if (unlikely (status))
- return status;
-
- entry->scaled_font = cairo_scaled_font_reference (scaled_font);
-
- if (unlikely (entry->scaled_font == NULL))
- {
- _cairo_pattern_fini (&entry->base.source.base);
- return CAIRO_INT_STATUS_NO_MEMORY;
- }
-
- if (num_glyphs)
- {
- entry->glyphs = malloc (sizeof (cairo_glyph_t) * num_glyphs);
-
- if (unlikely (entry->glyphs == NULL))
- {
- cairo_scaled_font_destroy (entry->scaled_font);
- _cairo_pattern_fini (&entry->base.source.base);
- return CAIRO_INT_STATUS_NO_MEMORY;
- }
-
- memcpy (entry->glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
- }
- else
- {
- entry->glyphs = NULL;
- }
-
- entry->num_glyphs = num_glyphs;
- entry->base.op = op;
- entry->base.clip = _cairo_clip_copy (clip);
- _cairo_tg_approximate_glyphs_extents (&entry->base.extents, op, source,
- glyphs, num_glyphs, scaled_font, clip);
- _cairo_rectangle_union (&journal->extents, &entry->base.extents);
-
- cairo_list_add_tail (&entry->base.link, &journal->entry_list);
- journal->num_entries++;
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-void
-_cairo_tg_journal_clear (cairo_tg_journal_t *journal)
-{
- cairo_tg_journal_entry_t *entry;
- cairo_tg_journal_entry_t *next;
-
- cairo_list_foreach_entry_safe (entry, next, cairo_tg_journal_entry_t,
- &journal->entry_list, link)
- {
- _cairo_tg_journal_entry_fini (entry);
- }
-
- journal->num_entries = 0;
- cairo_list_init (&journal->entry_list);
- _cairo_tg_mono_allocator_reset(&journal->allocator);
- journal->extents = _cairo_empty_rectangle;
-}
-
-cairo_int_status_t
-_cairo_tg_journal_replay (const cairo_tg_journal_t *journal,
- void *closure,
- const cairo_rectangle_int_t *extents,
- const cairo_tg_journal_replay_funcs_t *funcs)
-{
- const cairo_tg_journal_entry_t *entry;
- const cairo_tg_journal_entry_t *next;
- cairo_int_status_t status;
-
- cairo_list_foreach_entry_safe (entry, next, cairo_tg_journal_entry_t,
- &journal->entry_list, link)
- {
- if (extents && ! _cairo_rectangle_intersects (extents, &entry->extents))
- {
- continue;
- }
-
- switch (entry->type)
- {
- case CAIRO_TG_JOURNAL_ENTRY_PAINT:
- {
- cairo_tg_journal_entry_paint_t *e =
- (cairo_tg_journal_entry_paint_t *) entry;
-
- status = funcs->paint (closure, e->base.op, &e->base.source.base,
- e->base.clip);
- }
- break;
- case CAIRO_TG_JOURNAL_ENTRY_MASK:
- {
- cairo_tg_journal_entry_mask_t *e =
- (cairo_tg_journal_entry_mask_t *) entry;
-
- status = funcs->mask (closure, e->base.op, &e->base.source.base,
- &e->mask.base, e->base.clip);
- }
- break;
- case CAIRO_TG_JOURNAL_ENTRY_STROKE:
- {
- cairo_tg_journal_entry_stroke_t *e =
- (cairo_tg_journal_entry_stroke_t *) entry;
-
- status = funcs->stroke (closure, e->base.op, &e->base.source.base,
- &e->path, &e->style, &e->ctm, &e->ctm_inverse,
- e->tolerance, e->antialias, e->base.clip);
- }
- break;
- case CAIRO_TG_JOURNAL_ENTRY_FILL:
- {
- cairo_tg_journal_entry_fill_t *e =
- (cairo_tg_journal_entry_fill_t *) entry;
-
- status = funcs->fill (closure, e->base.op, &e->base.source.base,
- &e->path, e->fill_rule,
- e->tolerance, e->antialias, e->base.clip);
- }
- break;
- case CAIRO_TG_JOURNAL_ENTRY_GLYPHS:
- {
- cairo_tg_journal_entry_glyphs_t *e =
- (cairo_tg_journal_entry_glyphs_t *) entry;
-
- status = funcs->glyphs (closure, e->base.op, &e->base.source.base,
- e->glyphs, e->num_glyphs,
- e->scaled_font, e->base.clip);
- }
- break;
- default:
- ASSERT_NOT_REACHED;
- break;
- }
-
- if (unlikely (status) && status != CAIRO_INT_STATUS_NOTHING_TO_DO)
- {
- assert (0);
- return status;
- }
- }
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
diff --git a/src/cairo-tg-surface.c b/src/cairo-tg-surface.c
deleted file mode 100755
index c32799fa4..000000000
--- a/src/cairo-tg-surface.c
+++ /dev/null
@@ -1,1372 +0,0 @@
-/*
- * Copyright © 2012 SCore Corporation
- *
- * 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.
- *
- * Author: Taekyun Kim (podain77@gmail.com)
- */
-
-#include "cairoint.h"
-#include "cairo-surface-fallback-private.h"
-#include "cairo-tg.h"
-#include "cairo-tg-private.h"
-#include "cairo-image-surface-inline.h"
-#include "cairo-surface-subsurface-inline.h"
-#include "cairo-compositor-private.h"
-#include "cairo-clip-inline.h"
-#include "cairo-recording-surface-inline.h"
-
-#if CAIRO_HAS_OPENMP
-#include <omp.h>
-#endif
-
-#define CAIRO_TG_THREAD_POOL_BUSY_WAIT
-#define CAIRO_TG_NUM_MIN_ENTRIES_FOR_PARALLEL_FLUSH 2
-
-static inline int
-get_num_cpu_cores (void)
-{
- static int num_cpu_cores = 0;
-
- if (num_cpu_cores == 0)
- {
-#if CAIRO_HAS_OPENMP
- num_cpu_cores = omp_get_num_procs ();
-#elif defined (__WIN32)
- SYSTEM_INFO sysinfo;
-
- GetSystemInfo (&sysinfo);
- num_cpu_cores = sysinfo.dwNumberOfProcessors;
-#elif defined (__linux__)
- cpu_set_t cs;
- int i;
-
- CPU_ZERO (&cs);
-
- if (sched_getaffinity (0, sizeof (cs), &cs) != 0)
- num_cpu_cores = 1;
-
- for (i = 0; i < 8; i++)
- {
- if (CPU_ISSET (i, &cs))
- num_cpu_cores++;
- }
-#else
- num_cpu_cores = 1;
-#endif
- }
-
- return num_cpu_cores;
-}
-
-static inline int
-get_bpp_for_format (cairo_format_t format)
-{
- switch (format)
- {
- case CAIRO_FORMAT_ARGB32:
- case CAIRO_FORMAT_RGB24:
- case CAIRO_FORMAT_RGB30:
- return 32;
- case CAIRO_FORMAT_RGB16_565:
- return 16;
- case CAIRO_FORMAT_A8:
- return 8;
- case CAIRO_FORMAT_A1:
- return 1;
- case CAIRO_FORMAT_INVALID:
- default:
- ASSERT_NOT_REACHED;
- return 0;
- }
-}
-
-static inline cairo_bool_t
-_cairo_surface_is_tg(const cairo_surface_t *surface)
-{
- return surface->backend && surface->backend->type == CAIRO_SURFACE_TYPE_TG;
-}
-
-static inline cairo_bool_t
-_cairo_tg_surface_is_size_valid (int width, int height)
-{
- if (width < 0 || height < 0)
- return FALSE;
-
- /* TODO: Check for upper limit of surface size. */
-
- return TRUE;
-}
-
-static inline cairo_bool_t
-_cairo_pattern_is_self_copy (cairo_surface_t *surface,
- const cairo_pattern_t *pattern)
-{
- if (unlikely (surface == NULL))
- return FALSE;
-
- if (unlikely (pattern == NULL))
- return FALSE;
-
- if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE )
- {
- cairo_surface_t *pattern_surface =
- ((cairo_surface_pattern_t *) pattern)->surface;
-
- while (_cairo_surface_is_subsurface (pattern_surface))
- {
- pattern_surface =
- _cairo_surface_subsurface_get_target (pattern_surface);
- }
-
- return pattern_surface == surface;
- }
-
- return FALSE;
-}
-
-static inline cairo_bool_t
-_cairo_pattern_is_recording (const cairo_pattern_t *pattern)
-{
- cairo_surface_t *surface;
-
- if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
- return FALSE;
-
- surface = ((const cairo_surface_pattern_t *) pattern)->surface;
- return _cairo_surface_is_recording (surface);
-}
-
-static inline cairo_bool_t
-_cairo_tg_surface_owns_data (cairo_tg_surface_t *surface)
-{
- return ((cairo_image_surface_t *) surface->image_surface)->owns_data;
-}
-
-static inline cairo_int_status_t
-_cairo_tg_image_surface_paint (void *closure,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_clip_t *clip)
-{
- cairo_image_surface_t *surface = (cairo_image_surface_t *) closure;
- cairo_int_status_t status;
-
- status = _cairo_surface_begin_modification (&surface->base);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_compositor_paint (surface->compositor, &surface->base,
- op, source, clip);
-
- if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
- {
- surface->base.is_clear = op == CAIRO_OPERATOR_CLEAR && clip == NULL;
- surface->base.serial++;
- }
-
- return status;
-}
-
-static inline cairo_int_status_t
-_cairo_tg_image_surface_mask (void *closure,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
- const cairo_clip_t *clip)
-{
- cairo_image_surface_t *surface = (cairo_image_surface_t *) closure;
- cairo_int_status_t status;
-
- status = _cairo_surface_begin_modification (&surface->base);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_compositor_mask (surface->compositor, &surface->base,
- op, source, mask, clip);
-
- if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
- {
- surface->base.is_clear = FALSE;
- surface->base.serial++;
- }
-
- return status;
-}
-
-static inline cairo_int_status_t
-_cairo_tg_image_surface_stroke (void *closure,
- 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_image_surface_t *surface = (cairo_image_surface_t *) closure;
- cairo_int_status_t status;
-
- status = _cairo_surface_begin_modification (&surface->base);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_compositor_stroke (surface->compositor, &surface->base,
- op, source, path,
- style, ctm, ctm_inverse,
- tolerance, antialias, clip);
-
- if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
- {
- surface->base.is_clear = FALSE;
- surface->base.serial++;
- }
-
- return status;
-}
-
-
-static inline cairo_int_status_t
-_cairo_tg_image_surface_fill (void *closure,
- 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_image_surface_t *surface = (cairo_image_surface_t *) closure;
- cairo_int_status_t status;
-
- status = _cairo_surface_begin_modification (&surface->base);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_compositor_fill (surface->compositor, &surface->base,
- op, source, path,
- fill_rule, tolerance, antialias, clip);
-
- if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
- {
- surface->base.is_clear = FALSE;
- surface->base.serial++;
- }
-
- return status;
-}
-
-static inline cairo_int_status_t
-_cairo_tg_image_surface_glyphs (void *closure,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- const cairo_clip_t *clip)
-{
- cairo_image_surface_t *surface = (cairo_image_surface_t *) closure;
- cairo_int_status_t status;
-
- status = _cairo_surface_begin_modification (&surface->base);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_compositor_glyphs (surface->compositor, &surface->base,
- op, source,
- glyphs, num_glyphs, scaled_font,
- clip);
-
- if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
- {
- surface->base.is_clear = FALSE;
- surface->base.serial++;
- }
-
- return status;
-}
-
-const cairo_tg_journal_replay_funcs_t replay_funcs_image_fallback =
-{
- _cairo_tg_image_surface_paint,
- _cairo_tg_image_surface_mask,
- _cairo_tg_image_surface_stroke,
- _cairo_tg_image_surface_fill,
- _cairo_tg_image_surface_glyphs,
-};
-
-typedef struct _cairo_tg_surface_tile
-{
- cairo_surface_t *surface;
- cairo_rectangle_int_t tile_rect;
-} cairo_tg_surface_tile_t;
-
-static inline int
-_cairo_tg_surface_tiles_init (cairo_tg_surface_t *surface,
- const cairo_rectangle_int_t *extents,
- int num_tiles,
- cairo_tg_surface_tile_t *tiles)
-{
- int tile_height;
- int i;
-
- if (extents->height <= 0)
- return 0;
-
- if (extents->height <= num_tiles)
- num_tiles = extents->height;
-
- tile_height = extents->height / num_tiles;
-
- for (i = 0; i < num_tiles; i++)
- {
- tiles[i].surface = surface->tile_surfaces[i];
- tiles[i].tile_rect.x = extents->x;
- tiles[i].tile_rect.y = extents->y + i * tile_height;
- tiles[i].tile_rect.width = extents->width;
- tiles[i].tile_rect.height = tile_height;
- }
-
- tiles[num_tiles - 1].tile_rect.height = extents->height - i * (num_tiles - 1);
-
- return num_tiles;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_tile_paint (void *closure,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_clip_t *clip)
-{
- cairo_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
- cairo_clip_t *tile_clip;
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-
- tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
-
- if (! _cairo_clip_is_all_clipped (tile_clip))
- status = _cairo_tg_image_surface_paint (tile->surface, op, source, tile_clip);
-
- _cairo_clip_destroy (tile_clip);
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_tile_mask (void *closure,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
- const cairo_clip_t *clip)
-{
- cairo_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
- cairo_clip_t *tile_clip;
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-
- tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
-
- if (! _cairo_clip_is_all_clipped (tile_clip))
- {
- status = _cairo_tg_image_surface_mask (tile->surface, op, source,
- mask, tile_clip);
- }
-
- _cairo_clip_destroy (tile_clip);
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_tile_stroke (void *closure,
- 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_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
- cairo_clip_t *tile_clip;
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-
- tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
-
- if (! _cairo_clip_is_all_clipped (tile_clip))
- {
- status = _cairo_tg_image_surface_stroke (tile->surface, op, source,
- path, style, ctm, ctm_inverse,
- tolerance, antialias, tile_clip);
- }
-
- _cairo_clip_destroy (tile_clip);
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_tile_fill (void *closure,
- 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_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
- cairo_clip_t *tile_clip;
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-
- tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
-
- if (! _cairo_clip_is_all_clipped (tile_clip))
- {
- status = _cairo_tg_image_surface_fill (tile->surface, op, source,
- path, fill_rule, tolerance,
- antialias, tile_clip);
- }
-
- _cairo_clip_destroy (tile_clip);
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_tile_glyphs (void *closure,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- const cairo_clip_t *clip)
-{
- cairo_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
- cairo_clip_t *tile_clip;
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-
- tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
-
- if (! _cairo_clip_is_all_clipped (tile_clip))
- {
- status = _cairo_tg_image_surface_glyphs (tile->surface, op, source,
- glyphs, num_glyphs, scaled_font,
- tile_clip);
- }
-
- _cairo_clip_destroy (tile_clip);
-
- return status;
-}
-
-const cairo_tg_journal_replay_funcs_t replay_funcs_tile =
-{
- _cairo_tg_surface_tile_paint,
- _cairo_tg_surface_tile_mask,
- _cairo_tg_surface_tile_stroke,
- _cairo_tg_surface_tile_fill,
- _cairo_tg_surface_tile_glyphs,
-};
-
-#if ! CAIRO_HAS_OPENMP
-#define CAIRO_TG_NUM_MAX_WORKERS CAIRO_TG_NUM_MAX_TILES
-
-typedef enum _cairo_tg_worker_status
-{
- CAIRO_TG_WORKER_STATUS_IDLE, /* can transit to either OCCUPIED or KILLED */
- CAIRO_TG_WORKER_STATUS_TO_DO, /* only can transit to IDLE state */
- CAIRO_TG_WORKER_STATUS_KILLED, /* worker will be no longer valid */
-} cairo_tg_worker_status_t;
-
-typedef struct _cairo_tg_worker
-{
- cairo_tg_journal_t *journal;
- cairo_tg_surface_tile_t *tile;
-
- pthread_t thread;
- pthread_mutex_t lock;
- pthread_cond_t cond_wake_up;
- cairo_tg_worker_status_t status;
-
-#ifdef CAIRO_TG_THREAD_POOL_BUSY_WAIT
- pthread_spinlock_t spinlock;
-#else
- pthread_cond_t cond_done;
-#endif
-} cairo_tg_worker_t;
-
-cairo_tg_worker_t workers[CAIRO_TG_NUM_MAX_WORKERS];
-
-pthread_mutex_t workers_lock;
-cairo_bool_t workers_occupied;
-
-static void *
-_cairo_tg_worker_mainloop (void *arg)
-{
- cairo_tg_worker_t *worker = (cairo_tg_worker_t *) arg;
-
- while (1)
- {
- pthread_mutex_lock (&worker->lock);
-
- while (worker->status == CAIRO_TG_WORKER_STATUS_IDLE)
- pthread_cond_wait (&worker->cond_wake_up, &worker->lock);
-
- /* Here, worker is kicked off to do some action. */
-
- if (worker->status == CAIRO_TG_WORKER_STATUS_KILLED)
- {
- /* Worker is killed, so release mutex and exit. */
- pthread_mutex_unlock (&worker->lock);
- pthread_exit (NULL);
- }
-
- assert (worker->status == CAIRO_TG_WORKER_STATUS_TO_DO);
-
- _cairo_tg_journal_replay (worker->journal, (void *)worker->tile,
- &worker->tile->tile_rect, &replay_funcs_tile);
-
- worker->status = CAIRO_TG_WORKER_STATUS_IDLE;
-
-#ifndef CAIRO_TG_THREAD_POOL_BUSY_WAIT
- pthread_cond_signal (&worker->cond_done);
-#endif
-
- pthread_mutex_unlock (&worker->lock);
- }
-
- return NULL;
-}
-
-static void
-_cairo_tg_workers_init (void)
-{
- int i;
-
- for (i = 0; i < CAIRO_TG_NUM_MAX_WORKERS; i++)
- {
- workers[i].status = CAIRO_TG_WORKER_STATUS_IDLE;
-
- pthread_mutex_init (&workers[i].lock, NULL);
- pthread_cond_init (&workers[i].cond_wake_up, NULL);
-
-#ifdef CAIRO_TG_THREAD_POOL_BUSY_WAIT
- pthread_spin_init (&workers[i].spinlock, 0);
-#else
- pthread_cond_init (&workers[i].cond_done, NULL);
-#endif
-
- pthread_create (&workers[i].thread, NULL, _cairo_tg_worker_mainloop, (void *) &workers[i]);
- }
-
- pthread_mutex_init (&workers_lock, NULL);
- workers_occupied = FALSE;
-}
-
-static void
-_cairo_tg_workers_fini (void)
-{
- int i;
-
- for (i = 0; i < CAIRO_TG_NUM_MAX_WORKERS; i++)
- {
- pthread_mutex_lock (&workers[i].lock);
-
- workers[i].status = CAIRO_TG_WORKER_STATUS_KILLED;
- pthread_cond_signal (&workers[i].cond_wake_up);
- pthread_mutex_unlock (&workers[i].lock);
- }
-
- for (i = 0; i < CAIRO_TG_NUM_MAX_WORKERS; i++)
- pthread_join (workers[i].thread, NULL);
-
- for (i = 0; i < CAIRO_TG_NUM_MAX_WORKERS; i++)
- {
- pthread_mutex_destroy (&workers[i].lock);
- pthread_cond_destroy (&workers[i].cond_wake_up);
-
-#ifdef CAIRO_TG_THREAD_POOL_BUSY_WAIT
- pthread_spin_destroy (&workers[i].spinlock);
-#else
- pthread_cond_destroy (&workers[i].cond_done);
-#endif
- }
-}
-
-static void __attribute__((constructor))
-_cairo_tg_constructor (void)
-{
- pthread_atfork (NULL, NULL, _cairo_tg_workers_init);
- _cairo_tg_workers_init ();
-}
-
-static void __attribute__((destructor))
-_cairo_tg_destructor (void)
-{
- _cairo_tg_workers_fini ();
-}
-
-#endif /* ! CAIRO_HAS_OPENMP */
-
-static void
-_cairo_tg_surface_prepare_flush_parallel (cairo_tg_surface_t *surface)
-{
- const cairo_tg_journal_entry_t *entry;
- const cairo_tg_journal_entry_t *next;
-
- cairo_list_foreach_entry_safe (entry, next, cairo_tg_journal_entry_t,
- &surface->journal.entry_list, link)
- {
- if (entry->source.base.type == CAIRO_PATTERN_TYPE_SURFACE)
- {
- cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) (&entry->source.base);
- cairo_surface_flush (pattern->surface);
- }
-
- if (entry->type == CAIRO_TG_JOURNAL_ENTRY_MASK)
- {
- cairo_tg_journal_entry_mask_t *e =
- (cairo_tg_journal_entry_mask_t *) entry;
-
- if (e->mask.base.type == CAIRO_PATTERN_TYPE_SURFACE)
- {
- cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) (&e->mask.base);
- cairo_surface_flush (pattern->surface);
- }
- }
- }
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_flush_parallel (cairo_tg_surface_t *surface)
-{
- int num_tiles, i;
- cairo_tg_surface_tile_t tiles[CAIRO_TG_NUM_MAX_TILES];
- cairo_rectangle_int_t extents;
-
- if (surface->journal.num_entries < CAIRO_TG_NUM_MIN_ENTRIES_FOR_PARALLEL_FLUSH)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- _cairo_tg_surface_prepare_flush_parallel (surface);
-
- extents.x = 0;
- extents.y = 0;
- extents.width = surface->width;
- extents.height = surface->height;
-
- _cairo_rectangle_intersect (&extents, &surface->journal.extents);
-
- num_tiles = get_num_cpu_cores ();
-
-#if ! CAIRO_HAS_OPENMP
- if (num_tiles > CAIRO_TG_NUM_MAX_WORKERS)
- num_tiles = CAIRO_TG_NUM_MAX_WORKERS;
-#endif
-
- num_tiles = _cairo_tg_surface_tiles_init (surface, &extents, num_tiles, &tiles[0]);
-
-#if CAIRO_HAS_OPENMP
- #pragma omp parallel for
- for (i = 0; i < num_tiles; i++)
- {
- _cairo_tg_journal_replay (&surface->journal, (void *) &tiles[i],
- &tiles[i].tile_rect, &replay_funcs_tile);
- }
-#else
- pthread_mutex_lock (&workers_lock);
-
- if (workers_occupied)
- {
- pthread_mutex_unlock (&workers_lock);
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- workers_occupied = TRUE;
- pthread_mutex_unlock (&workers_lock);
-
- /* Kick workers to start. */
- for (i = 0; i < num_tiles - 1; i++)
- {
- pthread_mutex_lock (&workers[i].lock);
-
- workers[i].status = CAIRO_TG_WORKER_STATUS_TO_DO;
- workers[i].journal = &surface->journal;
- workers[i].tile = &tiles[i];
-
- pthread_cond_signal (&workers[i].cond_wake_up);
- pthread_mutex_unlock (&workers[i].lock);
- }
-
- _cairo_tg_journal_replay (&surface->journal, &tiles[num_tiles - 1],
- &tiles[num_tiles - 1].tile_rect, &replay_funcs_tile);
-
- /* Wait for workers to finish. */
- for (i = 0; i < num_tiles - 1; i++)
- {
-#ifdef CAIRO_TG_THREAD_POOL_BUSY_WAIT
- pthread_spin_lock (&workers[i].spinlock);
-
- while (workers[i].status == CAIRO_TG_WORKER_STATUS_TO_DO)
- {
- pthread_spin_unlock (&workers[i].spinlock);
- pthread_spin_lock (&workers[i].spinlock);
- }
-
- pthread_spin_unlock (&workers[i].spinlock);
-#else
- pthread_mutex_lock (&workers[i].lock);
-
- while (workers[i].status == CAIRO_TG_WORKER_STATUS_TO_DO)
- pthread_cond_wait (&workers[i].cond_done, &workers[i].lock);
-
- pthread_mutex_unlock (&workers[i].lock);
-#endif
- }
-
- /* Release thread pool. */
- pthread_mutex_lock (&workers_lock);
- workers_occupied = FALSE;
- pthread_mutex_unlock (&workers_lock);
-#endif
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_tg_surface_flush (void *abstract_surface,
- unsigned flags)
-{
- cairo_tg_surface_t *surface = abstract_surface;
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-
- if (flags)
- return CAIRO_STATUS_SUCCESS;
-
- _cairo_tg_journal_lock (&surface->journal);
-
- if (surface->journal.num_entries)
- {
- status = _cairo_tg_surface_flush_parallel (surface);
-
- if (status)
- {
- status = _cairo_tg_journal_replay (&surface->journal,
- (void *) surface->image_surface,
- NULL, &replay_funcs_image_fallback);
- }
-
- _cairo_tg_journal_clear (&surface->journal);
- }
-
- _cairo_tg_journal_unlock (&surface->journal);
-
- return status;
-}
-
-static cairo_image_surface_t *
-_cairo_tg_surface_map_to_image (void *abstract_surface,
- const cairo_rectangle_int_t *extents)
-{
- cairo_tg_surface_t *other = abstract_surface;
- cairo_surface_t *surface;
- uint8_t *buffer;
-
- _cairo_tg_surface_flush (other, 0);
-
- buffer = other->data;
- buffer += extents->y * other->stride;
- buffer += extents->x * other->bpp / 8;
-
- surface =
- _cairo_image_surface_create_with_pixman_format (buffer,
- other->pixman_format,
- extents->width,
- extents->height,
- other->stride);
-
- if (unlikely (surface == NULL))
- return NULL;
-
- cairo_surface_set_device_offset (surface, -extents->x, extents->y);
-
- return (cairo_image_surface_t *) surface;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_unmap_image (void *abstract_surface,
- cairo_image_surface_t *image)
-{
- cairo_surface_finish (&image->base);
- cairo_surface_destroy (&image->base);
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-static cairo_bool_t
-_cairo_tg_surface_get_extents (void *abstract_surface,
- cairo_rectangle_int_t *extents)
-{
- cairo_tg_surface_t *surface = abstract_surface;
-
- extents->x = 0;
- extents->y = 0;
- extents->width = surface->width;
- extents->height = surface->height;
-
- return TRUE;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_paint (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_clip_t *clip)
-{
- cairo_tg_surface_t *surface = abstract_surface;
- cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
- ! _cairo_pattern_is_recording (source))
- status = _cairo_tg_journal_log_paint (&surface->journal, op, source, clip);
-
- if (status)
- {
- status = _cairo_tg_surface_flush (surface, 0);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_tg_image_surface_paint (surface->image_surface, op, source, clip);
- }
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_mask (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- const cairo_pattern_t *mask,
- const cairo_clip_t *clip)
-{
- cairo_tg_surface_t *surface = abstract_surface;
- cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
- ! _cairo_pattern_is_self_copy (&surface->base, mask) &&
- ! _cairo_pattern_is_recording (source))
- status = _cairo_tg_journal_log_mask (&surface->journal, op, source, mask, clip);
-
- if (status)
- {
- status = _cairo_tg_surface_flush (surface, 0);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_tg_image_surface_mask (surface->image_surface, op, source,
- mask, clip);
- }
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_tg_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_tg_surface_t *surface = abstract_surface;
- cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
- ! _cairo_pattern_is_recording (source))
- {
- status = _cairo_tg_journal_log_stroke (&surface->journal, op, source,
- path, style, ctm, ctm_inverse,
- tolerance, antialias, clip);
- }
-
- if (status)
- {
- status = _cairo_tg_surface_flush (surface, 0);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_tg_image_surface_stroke (surface->image_surface, op, source,
- path, style, ctm, ctm_inverse,
- tolerance, antialias, clip);
- }
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_fill (void *abstract_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_tg_surface_t *surface = abstract_surface;
- cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
- ! _cairo_pattern_is_recording (source))
- {
- status = _cairo_tg_journal_log_fill (&surface->journal, op, source,
- path, fill_rule, tolerance, antialias, clip);
- }
-
- if (status)
- {
- status = _cairo_tg_surface_flush (surface, 0);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_tg_image_surface_fill (surface->image_surface, op, source,
- path, fill_rule, tolerance, antialias, clip);
- }
-
- return status;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_glyphs (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_glyph_t *glyphs,
- int num_glyphs,
- cairo_scaled_font_t *scaled_font,
- const cairo_clip_t *clip)
-{
- cairo_tg_surface_t *surface = abstract_surface;
- cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
- ! _cairo_pattern_is_recording (source))
- {
- status = _cairo_tg_journal_log_glyphs (&surface->journal, op, source,
- glyphs, num_glyphs, scaled_font, clip);
- }
-
- if (status)
- {
- status = _cairo_tg_surface_flush (surface, 0);
-
- if (unlikely (status))
- return status;
-
- status = _cairo_tg_image_surface_glyphs (surface->image_surface, op, source,
- glyphs, num_glyphs, scaled_font, clip);
- }
-
- return status;
-}
-
-static cairo_surface_t *
-_cairo_tg_surface_create_similar (void *abstract_other,
- cairo_content_t content,
- int width,
- int height)
-{
- cairo_tg_surface_t *other = abstract_other;
-
- if (! _cairo_tg_surface_is_size_valid (width, height))
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
-
- if (content == other->base.content)
- return cairo_tg_surface_create (other->format, width, height);
-
- return cairo_tg_surface_create (_cairo_format_from_content (content), width, height);
-}
-
-static cairo_surface_t *
-_cairo_tg_surface_source (void *abstract_surface,
- cairo_rectangle_int_t *extents)
-{
- cairo_tg_surface_t *surface = abstract_surface;
-
- if (extents)
- {
- extents->x = extents->y = 0;
- extents->width = surface->width;
- extents->height = surface->height;
- }
-
- return &surface->base;
-}
-
-static cairo_status_t
-_cairo_tg_surface_acquire_source_image (void *abstract_surface,
- cairo_image_surface_t **image_out,
- void **image_extra)
-{
- cairo_tg_surface_t *surface = abstract_surface;
-
- _cairo_tg_surface_flush (surface, 0);
-
- *image_out = (cairo_image_surface_t *) surface->image_surface;
- *image_extra = NULL;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_tg_surface_release_source_image (void *abstract_surface,
- cairo_image_surface_t *image,
- void *image_extra)
-{
- /* Do nothing */
-}
-
-static cairo_surface_t *
-_cairo_tg_surface_snapshot (void *abstract_surface)
-{
- cairo_tg_surface_t *surface = abstract_surface;
- cairo_tg_surface_t *clone;
-
- _cairo_tg_surface_flush (surface, 0);
-
- if (_cairo_tg_surface_owns_data (surface) && surface->base._finishing)
- {
- return cairo_tg_surface_create_for_data (surface->data, surface->format,
- surface->width, surface->height,
- surface->stride);
- }
-
- clone = (cairo_tg_surface_t *)
- cairo_tg_surface_create (surface->format, surface->width, surface->height);
-
- if (unlikely (clone->base.status))
- return &clone->base;
-
- if (surface->stride == clone->stride)
- {
- memcpy (clone->data, surface->data, clone->stride * clone->height);
- }
- else
- {
- unsigned char *dst = clone->data;
- unsigned char *src = surface->data;
- int i;
- int stride = clone->stride < surface->stride ? clone->stride : surface->stride;
-
- for (i = 0; i < clone->height; i++)
- {
- memcpy (dst, src, stride);
- dst += clone->stride;
- src += surface->stride;
- }
- }
-
- clone->base.is_clear = FALSE;
-
- return &clone->base;
-}
-
-static cairo_int_status_t
-_cairo_tg_surface_init_tile_surfaces (cairo_tg_surface_t *surface)
-{
- int i;
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-
- memset (&surface->tile_surfaces[0], 0x00,
- sizeof (cairo_surface_t *) * CAIRO_TG_NUM_MAX_TILES);
-
- for (i = 0; i < CAIRO_TG_NUM_MAX_TILES; i++)
- {
- surface->tile_surfaces[i] = cairo_image_surface_create_for_data (surface->data,
- surface->format,
- surface->width,
- surface->height,
- surface->stride);
-
- if (surface->tile_surfaces[i] == NULL)
- {
- status = CAIRO_INT_STATUS_NO_MEMORY;
- break;
- }
- }
-
- if (unlikely (status))
- {
- for (i = 0; i < CAIRO_TG_NUM_MAX_TILES; i++)
- {
- if (surface->tile_surfaces[i])
- cairo_surface_destroy (surface->tile_surfaces[i]);
- else
- break;
- }
- }
-
- return status;
-}
-
-static void
-_cairo_tg_surface_fini_tile_surfaces (cairo_tg_surface_t *surface)
-{
- int i;
-
- for (i = 0; i < CAIRO_TG_NUM_MAX_TILES; i++)
- {
- if (surface->tile_surfaces[i])
- cairo_surface_destroy (surface->tile_surfaces[i]);
- else
- break;
- }
-}
-
-static cairo_status_t
-_cairo_tg_surface_finish (void *abstract_surface)
-{
- cairo_tg_surface_t *surface = abstract_surface;
-
- _cairo_tg_surface_flush (surface, 0);
- _cairo_tg_journal_fini (&surface->journal);
- _cairo_tg_surface_fini_tile_surfaces (surface);
- cairo_surface_destroy (surface->image_surface);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static const cairo_surface_backend_t _cairo_tg_surface_backend =
-{
- CAIRO_SURFACE_TYPE_TG,
- _cairo_tg_surface_finish,
-
- _cairo_default_context_create,
-
- _cairo_tg_surface_create_similar,
- NULL, /* create_similar image */
- _cairo_tg_surface_map_to_image,
- _cairo_tg_surface_unmap_image,
-
- _cairo_tg_surface_source,
- _cairo_tg_surface_acquire_source_image,
- _cairo_tg_surface_release_source_image,
- _cairo_tg_surface_snapshot,
-
- NULL, /* copy_page */
- NULL, /* show_page */
-
- _cairo_tg_surface_get_extents,
- NULL, /* get_font_options */
-
- _cairo_tg_surface_flush,
- NULL, /* mark_dirty_rectangle */
-
- _cairo_tg_surface_paint,
- _cairo_tg_surface_mask,
- _cairo_tg_surface_stroke,
- _cairo_tg_surface_fill,
- NULL, /* fill_stroke */
- _cairo_tg_surface_glyphs,
-};
-
-cairo_surface_t *
-cairo_tg_surface_create (cairo_format_t format,
- int width,
- int height)
-{
- cairo_tg_surface_t *surface;
- cairo_surface_t *image_surface;
-
- image_surface = cairo_image_surface_create (format, width, height);
-
- if (unlikely (image_surface == NULL))
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
- surface = malloc (sizeof (cairo_tg_surface_t));
-
- if (unlikely (surface == NULL))
- {
- cairo_surface_destroy (image_surface);
-
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
-
- _cairo_surface_init (&surface->base,
- &_cairo_tg_surface_backend,
- NULL, image_surface->content);
-
- surface->format = format;
- surface->pixman_format = ((cairo_image_surface_t *) image_surface)->pixman_format;
- surface->data = (unsigned char *) cairo_image_surface_get_data (image_surface);
- surface->width = width;
- surface->height = height;
- surface->stride = cairo_image_surface_get_stride (image_surface);
- surface->bpp = get_bpp_for_format (format);
- surface->image_surface = image_surface;
- surface->base.is_clear = image_surface->is_clear;
-
- _cairo_tg_journal_init (&surface->journal);
-
- if (_cairo_tg_surface_init_tile_surfaces (surface))
- {
- cairo_surface_destroy (image_surface);
- _cairo_tg_journal_fini (&surface->journal);
-
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
-
- return &surface->base;
-}
-
-cairo_surface_t *
-cairo_tg_surface_create_for_data (unsigned char *data,
- cairo_format_t format,
- int width,
- int height,
- int stride)
-{
- cairo_tg_surface_t *surface;
- cairo_surface_t *image_surface;
-
- image_surface = cairo_image_surface_create_for_data (data, format, width, height, stride);
-
- if (unlikely (image_surface == NULL))
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
- surface = malloc (sizeof (cairo_tg_surface_t));
-
- if (unlikely (surface == NULL))
- {
- cairo_surface_destroy (image_surface);
-
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
-
- _cairo_surface_init (&surface->base,
- &_cairo_tg_surface_backend,
- NULL, image_surface->content);
-
- surface->format = format;
- surface->pixman_format = ((cairo_image_surface_t *) image_surface)->pixman_format;
- surface->data = (unsigned char *) cairo_image_surface_get_data (image_surface);
- surface->width = width;
- surface->height = height;
- surface->stride = cairo_image_surface_get_stride (image_surface);
- surface->bpp = get_bpp_for_format (format);
- surface->image_surface = image_surface;
- surface->base.is_clear = image_surface->is_clear;
-
- _cairo_tg_journal_init (&surface->journal);
-
- if (_cairo_tg_surface_init_tile_surfaces (surface))
- {
- cairo_surface_destroy (image_surface);
- _cairo_tg_journal_fini (&surface->journal);
-
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
- }
-
- return &surface->base;
-}
-
-unsigned char *
-cairo_tg_surface_get_data (cairo_surface_t *surface)
-{
- cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
-
- if (! _cairo_surface_is_tg (surface)) {
- _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
- return NULL;
- }
-
- return tg_surface->data;
-}
-
-cairo_format_t
-cairo_tg_surface_get_format (cairo_surface_t *surface)
-{
- cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
-
- if (! _cairo_surface_is_tg (surface)) {
- _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
- return CAIRO_FORMAT_INVALID;
- }
-
- return tg_surface->format;
-}
-
-int
-cairo_tg_surface_get_width (cairo_surface_t *surface)
-{
- cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
-
- if (! _cairo_surface_is_tg (surface)) {
- _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
- return 0;
- }
-
- return tg_surface->width;
-}
-
-int
-cairo_tg_surface_get_height (cairo_surface_t *surface)
-{
- cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
-
- if (! _cairo_surface_is_tg (surface)) {
- _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
- return 0;
- }
-
- return tg_surface->height;
-}
-
-int
-cairo_tg_surface_get_stride (cairo_surface_t *surface)
-{
- cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
-
- if (! _cairo_surface_is_tg (surface)) {
- _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
- return 0;
- }
-
- return tg_surface->stride;
-}
diff --git a/src/cairo-thread-local-private.h b/src/cairo-thread-local-private.h
deleted file mode 100755
index 994c049c7..000000000
--- a/src/cairo-thread-local-private.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright © 2012 SCore Corporation
- *
- * 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.
- *
- * Author: Taekyun Kim (podain77@gmail.com)
- */
-
-#ifndef CAIRO_THREAD_LOCAL_PRIVATE_H
-#define CAIRO_THREAD_LOCAL_PRIVATE_H
-
-#if CAIRO_HAS_TLS || CAIRO_HAS_PTHREAD_SETSPECIFIC
-#define CAIRO_HAS_THREAD_LOCAL 1
-#endif
-
-#if CAIRO_HAS_THREAD_LOCAL
-#if defined(TLS)
-
-# define CAIRO_DEFINE_THREAD_LOCAL(type, name) \
- static TLS type name
-
-# define CAIRO_GET_THREAD_LOCAL(name) \
- (&name)
-
-#elif defined(__MINGW32__)
-
-# define _NO_W32_PSEUDO_MODIFIERS
-# include <windows.h>
-
-# define CAIRO_DEFINE_THREAD_LOCAL(type, name) \
- static volatile int tls_ ## name ## _initialized = 0; \
- static void *tls_ ## name ## _mutex = NULL; \
- static unsigned tls_ ## name ## _index; \
- \
- static type * \
- tls_ ## name ## _alloc (void) \
- { \
- type *value = calloc (1, sizeof (type)); \
- if (value) \
- TlsSetValue (tls_ ## name ## _index, value); \
- return value; \
- } \
- \
- static inline type * \
- tls_ ## name ## _get (void) \
- { \
- type *value; \
- if (!tls_ ## name ## _initialized) \
- { \
- if (!tls_ ## name ## _mutex) \
- { \
- void *mutex = CreateMutexA (NULL, 0, NULL); \
- if (InterlockedCompareExchangePointer ( \
- &tls_ ## name ## _mutex, mutex, NULL) != NULL) \
- { \
- CloseHandle (mutex); \
- } \
- } \
- WaitForSingleObject (tls_ ## name ## _mutex, 0xFFFFFFFF); \
- if (!tls_ ## name ## _initialized) \
- { \
- tls_ ## name ## _index = TlsAlloc (); \
- tls_ ## name ## _initialized = 1; \
- } \
- ReleaseMutex (tls_ ## name ## _mutex); \
- } \
- if (tls_ ## name ## _index == 0xFFFFFFFF) \
- return NULL; \
- value = TlsGetValue (tls_ ## name ## _index); \
- if (!value) \
- value = tls_ ## name ## _alloc (); \
- return value; \
- }
-
-# define CAIRO_GET_THREAD_LOCAL(name) \
- tls_ ## name ## _get ()
-
-#elif defined(_MSC_VER)
-
-# define CAIRO_DEFINE_THREAD_LOCAL(type, name) \
- static __declspec(thread) type name
-
-# define CAIRO_GET_THREAD_LOCAL(name) \
- (&name)
-
-#elif defined(CAIRO_HAS_PTHREAD_SETSPECIFIC)
-
-#include <pthread.h>
-
-# define CAIRO_DEFINE_THREAD_LOCAL(type, name) \
- static pthread_once_t tls_ ## name ## _once_control = PTHREAD_ONCE_INIT; \
- static pthread_key_t tls_ ## name ## _key; \
- \
- static void \
- tls_ ## name ## _destroy_value (void *value) \
- { \
- free (value); \
- } \
- \
- static void \
- tls_ ## name ## _make_key (void) \
- { \
- pthread_key_create (&tls_ ## name ## _key, \
- tls_ ## name ## _destroy_value); \
- } \
- \
- static type * \
- tls_ ## name ## _alloc (void) \
- { \
- type *value = calloc (1, sizeof (type)); \
- if (value) \
- pthread_setspecific (tls_ ## name ## _key, value); \
- return value; \
- } \
- \
- static inline type * \
- tls_ ## name ## _get (void) \
- { \
- type *value = NULL; \
- if (pthread_once (&tls_ ## name ## _once_control, \
- tls_ ## name ## _make_key) == 0) \
- { \
- value = pthread_getspecific (tls_ ## name ## _key); \
- if (!value) \
- value = tls_ ## name ## _alloc (); \
- } \
- return value; \
- }
-
-# define CAIRO_GET_THREAD_LOCAL(name) \
- tls_ ## name ## _get ()
-
-#else
-
-# error "Unknown thread local support for this system."
-
-#endif
-#endif /* CAIRO_HAS_THREAD_LOCAL */
-
-#endif /* CAIRO_THREAD_LOCAL_PRIVATE_H */
diff --git a/src/cairo-time-private.h b/src/cairo-time-private.h
index 06dc912b4..06dc912b4 100755..100644
--- a/src/cairo-time-private.h
+++ b/src/cairo-time-private.h
diff --git a/src/cairo-time.c b/src/cairo-time.c
index a0003fbfc..a0003fbfc 100755..100644
--- a/src/cairo-time.c
+++ b/src/cairo-time.c
diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c
index 89ef20f09..b1b51872b 100755..100644
--- a/src/cairo-tor-scan-converter.c
+++ b/src/cairo-tor-scan-converter.c
@@ -262,7 +262,7 @@ typedef int grid_scaled_y_t;
struct quorem {
int32_t quo;
- int32_t rem;
+ int64_t rem;
};
/* Header for a chunk of memory in a memory pool. */
@@ -277,9 +277,14 @@ struct _pool_chunk {
* chunk in the pool header. */
struct _pool_chunk *prev_chunk;
- /* Actual data starts here. Well aligned for pointers. */
+ /* Actual data starts here. Well aligned even for 64 bit types. */
+ int64_t data;
};
+/* The int64_t data member of _pool_chunk just exists to enforce alignment,
+ * it shouldn't be included in the allocated size for the struct. */
+#define SIZEOF_POOL_CHUNK (sizeof(struct _pool_chunk) - sizeof(int64_t))
+
/* A memory pool. This is supposed to be embedded on the stack or
* within some other structure. It may optionally be followed by an
* embedded array from which requests are fulfilled until
@@ -299,8 +304,11 @@ struct pool {
/* Header for the sentinel chunk. Directly following the pool
* struct should be some space for embedded elements from which
- * the sentinel chunk allocates from. */
- struct _pool_chunk sentinel[1];
+ * the sentinel chunk allocates from. This is expressed as a char
+ * array so that the 'int64_t data' member of _pool_chunk isn't
+ * included. This way embedding struct pool in other structs works
+ * without wasting space. */
+ char sentinel[SIZEOF_POOL_CHUNK];
};
/* A polygon edge. */
@@ -308,6 +316,9 @@ struct edge {
/* Next in y-bucket or active list. */
struct edge *next, *prev;
+ /* The clipped y of the top of the edge. */
+ grid_scaled_y_t ytop;
+
/* Number of subsample rows remaining to scan convert of this
* edge. */
grid_scaled_y_t height_left;
@@ -315,7 +326,7 @@ struct edge {
/* Original sign of the edge: +1 for downwards, -1 for upwards
* edges. */
int dir;
- int vertical;
+ int cell;
/* Current x coordinate while the edge is on the active
* list. Initialised to the x coordinate of the top of the
@@ -332,11 +343,8 @@ struct edge {
* full row's worth of subsample rows at a time. */
struct quorem dxdy_full;
- /* The clipped y of the top of the edge. */
- grid_scaled_y_t ytop;
-
/* y2-y1 after orienting the edge downwards. */
- grid_scaled_y_t dy;
+ int64_t dy;
};
#define EDGE_Y_BUCKET_INDEX(y, ymin) (((y) - (ymin))/GRID_Y)
@@ -458,37 +466,6 @@ struct glitter_scan_converter {
grid_scaled_y_t ymin, ymax;
};
-/* Compute the floored division a/b. Assumes / and % perform symmetric
- * division. */
-inline static struct quorem
-floored_divrem(int a, int b)
-{
- struct quorem qr;
- qr.quo = a/b;
- qr.rem = a%b;
- if ((a^b)<0 && qr.rem) {
- qr.quo -= 1;
- qr.rem += b;
- }
- return qr;
-}
-
-/* Compute the floored division (x*a)/b. Assumes / and % perform symmetric
- * division. */
-static struct quorem
-floored_muldivrem(int x, int a, int b)
-{
- struct quorem qr;
- long long xa = (long long)x*a;
- qr.quo = xa/b;
- qr.rem = xa%b;
- if ((xa>=0) != (b>=0) && qr.rem) {
- qr.quo -= 1;
- qr.rem += b;
- }
- return qr;
-}
-
static struct _pool_chunk *
_pool_chunk_init(
struct _pool_chunk *p,
@@ -506,7 +483,7 @@ _pool_chunk_create(struct pool *pool, size_t size)
{
struct _pool_chunk *p;
- p = malloc(size + sizeof(struct _pool_chunk));
+ p = malloc(SIZEOF_POOL_CHUNK + size);
if (unlikely (NULL == p))
longjmp (*pool->jmp, _cairo_error (CAIRO_STATUS_NO_MEMORY));
@@ -520,10 +497,10 @@ pool_init(struct pool *pool,
size_t embedded_capacity)
{
pool->jmp = jmp;
- pool->current = pool->sentinel;
+ pool->current = (void*) pool->sentinel;
pool->first_free = NULL;
pool->default_capacity = default_capacity;
- _pool_chunk_init(pool->sentinel, NULL, embedded_capacity);
+ _pool_chunk_init(pool->current, NULL, embedded_capacity);
}
static void
@@ -533,7 +510,7 @@ pool_fini(struct pool *pool)
do {
while (NULL != p) {
struct _pool_chunk *prev = p->prev_chunk;
- if (p != pool->sentinel)
+ if (p != (void *) pool->sentinel)
free(p);
p = prev;
}
@@ -573,14 +550,14 @@ _pool_alloc_from_new_chunk(
chunk = _pool_chunk_create (pool, capacity);
pool->current = chunk;
- obj = ((unsigned char*)chunk + sizeof(*chunk) + chunk->size);
+ obj = ((unsigned char*)&chunk->data + chunk->size);
chunk->size += size;
return obj;
}
/* Allocate size bytes from the pool. The first allocated address
- * returned from a pool is aligned to sizeof(void*). Subsequent
- * addresses will maintain alignment as long as multiples of void* are
+ * returned from a pool is aligned to 8 bytes. Subsequent
+ * addresses will maintain alignment as long as multiples of 8 are
* allocated. Returns the address of a new memory area or %NULL on
* allocation failures. The pool retains ownership of the returned
* memory. */
@@ -590,7 +567,7 @@ pool_alloc (struct pool *pool, size_t size)
struct _pool_chunk *chunk = pool->current;
if (size <= chunk->capacity - chunk->size) {
- void *obj = ((unsigned char*)chunk + sizeof(*chunk) + chunk->size);
+ void *obj = ((unsigned char*)&chunk->data + chunk->size);
chunk->size += size;
return obj;
} else {
@@ -604,16 +581,16 @@ pool_reset (struct pool *pool)
{
/* Transfer all used chunks to the chunk free list. */
struct _pool_chunk *chunk = pool->current;
- if (chunk != pool->sentinel) {
- while (chunk->prev_chunk != pool->sentinel) {
+ if (chunk != (void *) pool->sentinel) {
+ while (chunk->prev_chunk != (void *) pool->sentinel) {
chunk = chunk->prev_chunk;
}
chunk->prev_chunk = pool->first_free;
pool->first_free = pool->current;
}
/* Reset the sentinel as the current chunk. */
- pool->current = pool->sentinel;
- pool->sentinel->size = 0;
+ pool->current = (void *) pool->sentinel;
+ pool->current->size = 0;
}
/* Rewinds the cell list's cursor to the beginning. After rewinding
@@ -778,6 +755,25 @@ cell_list_add_subspan(struct cell_list *cells,
}
}
+inline static void full_step (struct edge *e)
+{
+ if (e->dy == 0)
+ return;
+
+ e->x.quo += e->dxdy_full.quo;
+ e->x.rem += e->dxdy_full.rem;
+ if (e->x.rem < 0) {
+ e->x.quo--;
+ e->x.rem += e->dy;
+ } else if (e->x.rem >= e->dy) {
+ ++e->x.quo;
+ e->x.rem -= e->dy;
+ }
+
+ e->cell = e->x.quo + (e->x.rem >= e->dy/2);
+}
+
+
/* Adds the analytical coverage of an edge crossing the current pixel
* row to the coverage cells and advances the edge's x position to the
* following row.
@@ -800,28 +796,42 @@ cell_list_render_edge(struct cell_list *cells,
struct edge *edge,
int sign)
{
- grid_scaled_y_t y1, y2, dy;
- grid_scaled_x_t dx;
- int ix1, ix2;
+ struct quorem x1, x2;
grid_scaled_x_t fx1, fx2;
+ int ix1, ix2;
- struct quorem x1 = edge->x;
- struct quorem x2 = x1;
+ x1 = edge->x;
+ full_step (edge);
+ x2 = edge->x;
+
+ /* Step back from the sample location (half-subrow) to the pixel origin */
+ if (edge->dy) {
+ x1.quo -= edge->dxdy.quo / 2;
+ x1.rem -= edge->dxdy.rem / 2;
+ if (x1.rem < 0) {
+ --x1.quo;
+ x1.rem += edge->dy;
+ } else if (x1.rem >= edge->dy) {
+ ++x1.quo;
+ x1.rem -= edge->dy;
+ }
- if (! edge->vertical) {
- x2.quo += edge->dxdy_full.quo;
- x2.rem += edge->dxdy_full.rem;
- if (x2.rem >= 0) {
+ x2.quo -= edge->dxdy.quo / 2;
+ x2.rem -= edge->dxdy.rem / 2;
+ if (x2.rem < 0) {
+ --x2.quo;
+ x2.rem += edge->dy;
+ } else if (x2.rem >= edge->dy) {
++x2.quo;
x2.rem -= edge->dy;
}
-
- edge->x = x2;
}
GRID_X_TO_INT_FRAC(x1.quo, ix1, fx1);
GRID_X_TO_INT_FRAC(x2.quo, ix2, fx2);
+ cell_list_maybe_rewind(cells, MIN(ix1, ix2));
+
/* Edge is entirely within a column? */
if (ix1 == ix2) {
/* We always know that ix1 is >= the cell list cursor in this
@@ -833,26 +843,39 @@ cell_list_render_edge(struct cell_list *cells,
}
/* Orient the edge left-to-right. */
- dx = x2.quo - x1.quo;
- if (dx >= 0) {
- y1 = 0;
- y2 = GRID_Y;
- } else {
- int tmp;
- tmp = ix1; ix1 = ix2; ix2 = tmp;
- tmp = fx1; fx1 = fx2; fx2 = tmp;
- dx = -dx;
- sign = -sign;
- y1 = GRID_Y;
- y2 = 0;
+ if (ix2 < ix1) {
+ struct quorem tx;
+ int t;
+
+ t = ix1;
+ ix1 = ix2;
+ ix2 = t;
+
+ t = fx1;
+ fx1 = fx2;
+ fx2 = t;
+
+ tx = x1;
+ x1 = x2;
+ x2 = tx;
}
- dy = y2 - y1;
/* Add coverage for all pixels [ix1,ix2] on this row crossed
* by the edge. */
{
struct cell_pair pair;
- struct quorem y = floored_divrem((GRID_X - fx1)*dy, dx);
+ struct quorem y;
+ int64_t tmp, dx;
+ int y_last;
+
+ dx = (x2.quo - x1.quo) * edge->dy + (x2.rem - x1.rem);
+
+ tmp = (ix1 + 1) * GRID_X * edge->dy;
+ tmp -= x1.quo * edge->dy + x1.rem;
+ tmp *= GRID_Y;
+
+ y.quo = tmp / dx;
+ y.rem = tmp % dx;
/* When rendering a previous edge on the active list we may
* advance the cell list cursor past the leftmost pixel of the
@@ -868,35 +891,32 @@ cell_list_render_edge(struct cell_list *cells,
*
* The left edge touches cells past the starting cell of the
* right edge. Fortunately such cases are rare.
- *
- * The rewinding is never necessary if the current edge stays
- * within a single column because we've checked before calling
- * this function that the active list order won't change. */
- cell_list_maybe_rewind(cells, ix1);
+ */
pair = cell_list_find_pair(cells, ix1, ix1+1);
pair.cell1->uncovered_area += sign*y.quo*(GRID_X + fx1);
pair.cell1->covered_height += sign*y.quo;
- y.quo += y1;
+ y_last = y.quo;
if (ix1+1 < ix2) {
- struct quorem dydx_full = floored_divrem(GRID_X*dy, dx);
struct cell *cell = pair.cell2;
+ struct quorem dydx_full;
+
+ dydx_full.quo = GRID_Y * GRID_X * edge->dy / dx;
+ dydx_full.rem = GRID_Y * GRID_X * edge->dy % dx;
++ix1;
do {
- grid_scaled_y_t y_skip = dydx_full.quo;
+ y.quo += dydx_full.quo;
y.rem += dydx_full.rem;
if (y.rem >= dx) {
- ++y_skip;
+ y.quo++;
y.rem -= dx;
}
- y.quo += y_skip;
-
- y_skip *= sign;
- cell->uncovered_area += y_skip*GRID_X;
- cell->covered_height += y_skip;
+ cell->uncovered_area += sign*(y.quo - y_last)*GRID_X;
+ cell->covered_height += sign*(y.quo - y_last);
+ y_last = y.quo;
++ix1;
cell = cell_list_find(cells, ix1);
@@ -904,8 +924,8 @@ cell_list_render_edge(struct cell_list *cells,
pair.cell2 = cell;
}
- pair.cell2->uncovered_area += sign*(y2 - y.quo)*fx2;
- pair.cell2->covered_height += sign*(y2 - y.quo);
+ pair.cell2->uncovered_area += sign*(GRID_Y - y_last)*fx2;
+ pair.cell2->covered_height += sign*(GRID_Y - y_last);
}
}
@@ -976,78 +996,19 @@ _polygon_insert_edge_into_its_y_bucket(struct polygon *polygon,
*ptail = e;
}
-inline static void
-polygon_add_edge (struct polygon *polygon,
- const cairo_edge_t *edge)
-{
- struct edge *e;
- grid_scaled_x_t dx;
- grid_scaled_y_t dy;
- grid_scaled_y_t ytop, ybot;
- grid_scaled_y_t ymin = polygon->ymin;
- grid_scaled_y_t ymax = polygon->ymax;
-
- if (unlikely (edge->top >= ymax || edge->bottom <= ymin))
- return;
-
- e = pool_alloc (polygon->edge_pool.base, sizeof (struct edge));
-
- dx = edge->line.p2.x - edge->line.p1.x;
- dy = edge->line.p2.y - edge->line.p1.y;
- e->dy = dy;
- e->dir = edge->dir;
-
- ytop = edge->top >= ymin ? edge->top : ymin;
- ybot = edge->bottom <= ymax ? edge->bottom : ymax;
- e->ytop = ytop;
- e->height_left = ybot - ytop;
-
- if (dx == 0) {
- e->vertical = TRUE;
- e->x.quo = edge->line.p1.x;
- e->x.rem = 0;
- e->dxdy.quo = 0;
- e->dxdy.rem = 0;
- e->dxdy_full.quo = 0;
- e->dxdy_full.rem = 0;
- } else {
- e->vertical = FALSE;
- e->dxdy = floored_divrem (dx, dy);
- if (ytop == edge->line.p1.y) {
- e->x.quo = edge->line.p1.x;
- e->x.rem = 0;
- } else {
- e->x = floored_muldivrem (ytop - edge->line.p1.y, dx, dy);
- e->x.quo += edge->line.p1.x;
- }
-
- if (e->height_left >= GRID_Y) {
- e->dxdy_full = floored_muldivrem (GRID_Y, dx, dy);
- } else {
- e->dxdy_full.quo = 0;
- e->dxdy_full.rem = 0;
- }
- }
-
- _polygon_insert_edge_into_its_y_bucket (polygon, e);
-
- e->x.rem -= dy; /* Bias the remainder for faster
- * edge advancement. */
-}
-
static void
active_list_reset (struct active_list *active)
{
- active->head.vertical = 1;
active->head.height_left = INT_MAX;
- active->head.x.quo = INT_MIN;
+ active->head.dy = 0;
+ active->head.cell = INT_MIN;
active->head.prev = NULL;
active->head.next = &active->tail;
active->tail.prev = &active->head;
active->tail.next = NULL;
- active->tail.x.quo = INT_MAX;
+ active->tail.cell = INT_MAX;
active->tail.height_left = INT_MAX;
- active->tail.vertical = 1;
+ active->tail.dy = 0;
active->min_height = 0;
active->is_vertical = 1;
}
@@ -1084,7 +1045,7 @@ merge_sorted_edges (struct edge *head_a, struct edge *head_b)
prev = head_a->prev;
next = &head;
- if (head_a->x.quo <= head_b->x.quo) {
+ if (head_a->cell <= head_b->cell) {
head = head_a;
} else {
head = head_b;
@@ -1093,8 +1054,8 @@ merge_sorted_edges (struct edge *head_a, struct edge *head_b)
}
do {
- x = head_b->x.quo;
- while (head_a != NULL && head_a->x.quo <= x) {
+ x = head_b->cell;
+ while (head_a != NULL && head_a->cell <= x) {
prev = head_a;
next = &head_a->next;
head_a = head_a->next;
@@ -1106,8 +1067,8 @@ merge_sorted_edges (struct edge *head_a, struct edge *head_b)
return head;
start_with_b:
- x = head_a->x.quo;
- while (head_b != NULL && head_b->x.quo <= x) {
+ x = head_a->cell;
+ while (head_b != NULL && head_b->cell <= x) {
prev = head_b;
next = &head_b->next;
head_b = head_b->next;
@@ -1153,7 +1114,7 @@ sort_edges (struct edge *list,
}
remaining = head_other->next;
- if (list->x.quo <= head_other->x.quo) {
+ if (list->cell <= head_other->cell) {
*head_out = list;
head_other->next = NULL;
} else {
@@ -1197,7 +1158,7 @@ can_do_full_row (struct active_list *active)
while (NULL != e) {
if (e->height_left < min_height)
min_height = e->height_left;
- is_vertical &= e->vertical;
+ is_vertical &= e->dy == 0;
e = e->next;
}
@@ -1210,19 +1171,27 @@ can_do_full_row (struct active_list *active)
/* Check for intersections as no edges end during the next row. */
for (e = active->head.next; e != &active->tail; e = e->next) {
- struct quorem x = e->x;
+ int cell;
- if (! e->vertical) {
+ if (e->dy) {
+ struct quorem x = e->x;
x.quo += e->dxdy_full.quo;
x.rem += e->dxdy_full.rem;
- if (x.rem >= 0)
- ++x.quo;
- }
+ if (x.rem < 0) {
+ x.quo--;
+ x.rem += e->dy;
+ } else if (x.rem >= e->dy) {
+ x.quo++;
+ x.rem -= e->dy;
+ }
+ cell = x.quo + (x.rem >= e->dy/2);
+ } else
+ cell = e->cell;
- if (x.quo < prev_x)
+ if (cell < prev_x)
return 0;
- prev_x = x.quo;
+ prev_x = cell;
}
return 1;
@@ -1237,7 +1206,7 @@ active_list_merge_edges_from_bucket(struct active_list *active,
active->head.next = merge_unsorted_edges (active->head.next, edges);
}
-inline static void
+inline static int
polygon_fill_buckets (struct active_list *active,
struct edge *edge,
int y,
@@ -1245,6 +1214,7 @@ polygon_fill_buckets (struct active_list *active,
{
grid_scaled_y_t min_height = active->min_height;
int is_vertical = active->is_vertical;
+ int max_suby = 0;
while (edge) {
struct edge *next = edge->next;
@@ -1256,12 +1226,34 @@ polygon_fill_buckets (struct active_list *active,
buckets[suby] = edge;
if (edge->height_left < min_height)
min_height = edge->height_left;
- is_vertical &= edge->vertical;
+ is_vertical &= edge->dy == 0;
edge = next;
+ if (suby > max_suby)
+ max_suby = suby;
}
active->is_vertical = is_vertical;
active->min_height = min_height;
+
+ return max_suby;
+}
+
+static void step (struct edge *edge)
+{
+ if (edge->dy == 0)
+ return;
+
+ edge->x.quo += edge->dxdy.quo;
+ edge->x.rem += edge->dxdy.rem;
+ if (edge->x.rem < 0) {
+ --edge->x.quo;
+ edge->x.rem += edge->dy;
+ } else if (edge->x.rem >= edge->dy) {
+ ++edge->x.quo;
+ edge->x.rem -= edge->dy;
+ }
+
+ edge->cell = edge->x.quo + (edge->x.rem >= edge->dy/2);
}
inline static void
@@ -1277,29 +1269,24 @@ sub_row (struct active_list *active,
while (&active->tail != edge) {
struct edge *next = edge->next;
- int xend = edge->x.quo;
+ int xend = edge->cell;
if (--edge->height_left) {
- edge->x.quo += edge->dxdy.quo;
- edge->x.rem += edge->dxdy.rem;
- if (edge->x.rem >= 0) {
- ++edge->x.quo;
- edge->x.rem -= edge->dy;
- }
+ step (edge);
- if (edge->x.quo < prev_x) {
+ if (edge->cell < prev_x) {
struct edge *pos = edge->prev;
pos->next = next;
next->prev = pos;
do {
pos = pos->prev;
- } while (edge->x.quo < pos->x.quo);
+ } while (edge->cell < pos->cell);
pos->next->prev = edge;
edge->next = pos->next;
edge->prev = pos;
pos->next = edge;
} else
- prev_x = edge->x.quo;
+ prev_x = edge->cell;
active->min_height = -1;
} else {
edge->prev->next = next;
@@ -1308,7 +1295,7 @@ sub_row (struct active_list *active,
winding += edge->dir;
if ((winding & mask) == 0) {
- if (next->x.quo != xend) {
+ if (next->cell != xend) {
cell_list_add_subspan (coverages, xstart, xend);
xstart = INT_MIN;
}
@@ -1329,18 +1316,6 @@ inline static void dec (struct active_list *a, struct edge *e, int h)
}
}
-inline static void full_step (struct edge *e)
-{
- if (! e->vertical) {
- e->x.quo += e->dxdy_full.quo;
- e->x.rem += e->dxdy_full.rem;
- if (e->x.rem >= 0) {
- ++e->x.quo;
- e->x.rem -= e->dy;
- }
- }
-}
-
static void
full_row (struct active_list *active,
struct cell_list *coverages,
@@ -1360,7 +1335,7 @@ full_row (struct active_list *active,
dec (active, right, GRID_Y);
winding += right->dir;
- if ((winding & mask) == 0 && right->next->x.quo != right->x.quo)
+ if ((winding & mask) == 0 && right->next->cell != right->cell)
break;
full_step (right);
@@ -1482,10 +1457,96 @@ glitter_scan_converter_reset(
#define INPUT_TO_GRID_general(in, out, grid_scale) do { \
long long tmp__ = (long long)(grid_scale) * (in); \
+ tmp__ += 1 << (GLITTER_INPUT_BITS-1); \
tmp__ >>= GLITTER_INPUT_BITS; \
(out) = tmp__; \
} while (0)
+inline static void
+polygon_add_edge (struct polygon *polygon,
+ const cairo_edge_t *edge)
+{
+ struct edge *e;
+ grid_scaled_y_t ytop, ybot;
+ const cairo_point_t *p1, *p2;
+
+ INPUT_TO_GRID_Y (edge->top, ytop);
+ if (ytop < polygon->ymin)
+ ytop = polygon->ymin;
+
+ INPUT_TO_GRID_Y (edge->bottom, ybot);
+ if (ybot > polygon->ymax)
+ ybot = polygon->ymax;
+
+ if (ybot <= ytop)
+ return;
+
+ e = pool_alloc (polygon->edge_pool.base, sizeof (struct edge));
+
+ e->ytop = ytop;
+ e->height_left = ybot - ytop;
+ if (edge->line.p2.y > edge->line.p1.y) {
+ e->dir = edge->dir;
+ p1 = &edge->line.p1;
+ p2 = &edge->line.p2;
+ } else {
+ e->dir = -edge->dir;
+ p1 = &edge->line.p2;
+ p2 = &edge->line.p1;
+ }
+
+ if (p2->x == p1->x) {
+ e->cell = p1->x;
+ e->x.quo = p1->x;
+ e->x.rem = 0;
+ e->dxdy.quo = e->dxdy.rem = 0;
+ e->dxdy_full.quo = e->dxdy_full.rem = 0;
+ e->dy = 0;
+ } else {
+ int64_t Ex, Ey, tmp;
+
+ Ex = (int64_t)(p2->x - p1->x) * GRID_X;
+ Ey = (int64_t)(p2->y - p1->y) * GRID_Y * (2 << GLITTER_INPUT_BITS);
+
+ e->dxdy.quo = Ex * (2 << GLITTER_INPUT_BITS) / Ey;
+ e->dxdy.rem = Ex * (2 << GLITTER_INPUT_BITS) % Ey;
+
+ tmp = (int64_t)(2*ytop + 1) << GLITTER_INPUT_BITS;
+ tmp -= (int64_t)p1->y * GRID_Y * 2;
+ tmp *= Ex;
+ e->x.quo = tmp / Ey;
+ e->x.rem = tmp % Ey;
+
+#if GRID_X_BITS == GLITTER_INPUT_BITS
+ e->x.quo += p1->x;
+#else
+ tmp = (int64_t)p1->x * GRID_X;
+ e->x.quo += tmp >> GLITTER_INPUT_BITS;
+ e->x.rem += ((tmp & ((1 << GLITTER_INPUT_BITS) - 1)) * Ey) / (1 << GLITTER_INPUT_BITS);
+#endif
+
+ if (e->x.rem < 0) {
+ e->x.quo--;
+ e->x.rem += Ey;
+ } else if (e->x.rem >= Ey) {
+ e->x.quo++;
+ e->x.rem -= Ey;
+ }
+
+ if (e->height_left >= GRID_Y) {
+ tmp = Ex * (2 * GRID_Y << GLITTER_INPUT_BITS);
+ e->dxdy_full.quo = tmp / Ey;
+ e->dxdy_full.rem = tmp % Ey;
+ } else
+ e->dxdy_full.quo = e->dxdy_full.rem = 0;
+
+ e->cell = e->x.quo + (e->x.rem >= Ey/2);
+ e->dy = Ey;
+ }
+
+ _polygon_insert_edge_into_its_y_bucket (polygon, e);
+}
+
/* Add a new polygon edge from pixel (x1,y1) to (x2,y2) to the scan
* converter. The coordinates represent pixel positions scaled by
* 2**GLITTER_PIXEL_BITS. If this function fails then the scan
@@ -1495,25 +1556,7 @@ I void
glitter_scan_converter_add_edge (glitter_scan_converter_t *converter,
const cairo_edge_t *edge)
{
- cairo_edge_t e;
-
- INPUT_TO_GRID_Y (edge->top, e.top);
- INPUT_TO_GRID_Y (edge->bottom, e.bottom);
- if (e.top >= e.bottom)
- return;
-
- /* XXX: possible overflows if GRID_X/Y > 2**GLITTER_INPUT_BITS */
- INPUT_TO_GRID_Y (edge->line.p1.y, e.line.p1.y);
- INPUT_TO_GRID_Y (edge->line.p2.y, e.line.p2.y);
- if (e.line.p1.y == e.line.p2.y)
- e.line.p2.y++; /* little fudge to prevent a div-by-zero */
-
- INPUT_TO_GRID_X (edge->line.p1.x, e.line.p1.x);
- INPUT_TO_GRID_X (edge->line.p2.x, e.line.p2.x);
-
- e.dir = edge->dir;
-
- polygon_add_edge (converter->polygon, &e);
+ polygon_add_edge (converter->polygon, edge);
}
static void
@@ -1699,7 +1742,15 @@ glitter_scan_converter_render(glitter_scan_converter_t *converter,
/* Determine if we can ignore this row or use the full pixel
* stepper. */
- if (! polygon->y_buckets[i]) {
+ if (polygon_fill_buckets (active,
+ polygon->y_buckets[i],
+ (i+ymin_i)*GRID_Y,
+ buckets) == 0) {
+ if (buckets[0]) {
+ active_list_merge_edges_from_bucket (active, buckets[0]);
+ buckets[0] = NULL;
+ }
+
if (active->head.next == &active->tail) {
active->min_height = INT_MAX;
active->is_vertical = 1;
@@ -1729,18 +1780,12 @@ glitter_scan_converter_render(glitter_scan_converter_t *converter,
} else {
int sub;
- polygon_fill_buckets (active,
- polygon->y_buckets[i],
- (i+ymin_i)*GRID_Y,
- buckets);
-
/* Subsample this row. */
for (sub = 0; sub < GRID_Y; sub++) {
if (buckets[sub]) {
active_list_merge_edges_from_bucket (active, buckets[sub]);
buckets[sub] = NULL;
}
-
sub_row (active, coverages, winding_mask);
}
}
diff --git a/src/cairo-tor22-scan-converter.c b/src/cairo-tor22-scan-converter.c
index 4cec5ee4f..4cec5ee4f 100755..100644
--- a/src/cairo-tor22-scan-converter.c
+++ b/src/cairo-tor22-scan-converter.c
diff --git a/src/cairo-toy-font-face.c b/src/cairo-toy-font-face.c
index 363b9a284..4fe94ab09 100755..100644
--- a/src/cairo-toy-font-face.c
+++ b/src/cairo-toy-font-face.c
@@ -342,7 +342,7 @@ cairo_toy_font_face_create (const char *family,
}
slim_hidden_def (cairo_toy_font_face_create);
-static void
+static cairo_bool_t
_cairo_toy_font_face_destroy (void *abstract_face)
{
cairo_toy_font_face_t *font_face = abstract_face;
@@ -352,10 +352,10 @@ _cairo_toy_font_face_destroy (void *abstract_face)
/* All created objects must have been mapped in the hash table. */
assert (hash_table != NULL);
- if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->base.ref_count)) {
+ if (! _cairo_reference_count_dec_and_test (&font_face->base.ref_count)) {
/* somebody recreated the font whilst we waited for the lock */
_cairo_toy_font_face_hash_table_unlock ();
- return;
+ return FALSE;
}
/* Font faces in SUCCESS status are guaranteed to be in the
@@ -369,6 +369,7 @@ _cairo_toy_font_face_destroy (void *abstract_face)
_cairo_toy_font_face_hash_table_unlock ();
_cairo_toy_font_face_fini (font_face);
+ return TRUE;
}
static cairo_status_t
diff --git a/src/cairo-traps-compositor.c b/src/cairo-traps-compositor.c
index 5d561f2be..c26a5df6f 100755..100644
--- a/src/cairo-traps-compositor.c
+++ b/src/cairo-traps-compositor.c
@@ -209,18 +209,18 @@ combine_clip_as_traps (const cairo_traps_compositor_t *compositor,
return src->status;
}
- if (draw_color_glyph)
- status = compositor->composite_traps (mask, CAIRO_OPERATOR_IN, mask,
- 0, 0,
- extents->x, extents->y,
- extents,
- antialias, &traps);
- else
+ if (draw_color_glyph)
+ status = compositor->composite_traps (mask, CAIRO_OPERATOR_IN, mask,
+ 0, 0,
+ extents->x, extents->y,
+ extents,
+ antialias, &traps);
+ else
status = compositor->composite_traps (mask, CAIRO_OPERATOR_IN, src,
- src_x, src_y,
- extents->x, extents->y,
- extents,
- antialias, &traps);
+ src_x, src_y,
+ extents->x, extents->y,
+ extents,
+ antialias, &traps);
_cairo_traps_extents (&traps, &box);
_cairo_box_round_to_rectangle (&box, &fixup);
@@ -315,10 +315,11 @@ __clip_to_surface (const cairo_traps_compositor_t *compositor,
if (unlikely (status))
return status;
- mask = _cairo_surface_create_similar_scratch (composite->surface,
- CAIRO_CONTENT_ALPHA,
- extents->width,
- extents->height);
+ mask = _cairo_surface_create_scratch (composite->surface,
+ CAIRO_CONTENT_ALPHA,
+ extents->width,
+ extents->height,
+ NULL);
if (unlikely (mask->status)) {
_cairo_traps_fini (&traps);
return status;
@@ -379,11 +380,11 @@ traps_get_clip_surface (const cairo_traps_compositor_t *compositor,
status = __clip_to_surface (compositor, composite, extents, &surface);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
- surface = _cairo_surface_create_similar_solid (composite->surface,
- CAIRO_CONTENT_ALPHA,
- extents->width,
- extents->height,
- CAIRO_COLOR_WHITE);
+ surface = _cairo_surface_create_scratch (composite->surface,
+ CAIRO_CONTENT_ALPHA,
+ extents->width,
+ extents->height,
+ CAIRO_COLOR_WHITE);
if (unlikely (surface->status))
return surface;
@@ -435,21 +436,22 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
cairo_surface_t *surface, *src;
cairo_int_status_t status;
int src_x, src_y;
- cairo_bool_t draw_color_glyph = FALSE;
+ cairo_bool_t draw_color_glyph = FALSE;
TRACE ((stderr, "%s\n", __FUNCTION__));
- surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_ALPHA,
- extents->bounded.width,
- extents->bounded.height);
+ surface = _cairo_surface_create_scratch (dst, CAIRO_CONTENT_ALPHA,
+ extents->bounded.width,
+ extents->bounded.height,
+ NULL);
if (unlikely (surface->status))
return surface;
- /* FIXME: This is more like an ugly hack and wasteful. Reason
- for this code is that we don't know whether the mask surface
- should alpha-only or argb32 before we render a glyph.
- */
- redo:
+ /* FIXME: This is more like an ugly hack and wasteful. Reason
+ for this code is that we don't know whether the mask surface
+ should alpha-only or argb32 before we render a glyph.
+ */
+redo:
src = compositor->pattern_to_surface (surface,
&_cairo_pattern_white.base,
FALSE,
@@ -503,22 +505,22 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
CAIRO_OPERATOR_ADD, src, src_x, src_y,
extents->bounded.x, extents->bounded.y,
&extents->bounded, NULL);
- if (unlikely (status)){
- if (cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA)
- goto error;
- else {
- compositor->release (surface);
- cairo_surface_destroy (surface);
- cairo_surface_destroy (src);
- surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_COLOR_ALPHA,
- extents->bounded.width,
- extents->bounded.height);
- if (unlikely (surface->status))
- return surface;
- /* we are drawing color glyph */
- draw_color_glyph = TRUE;
- goto redo;
- }
+ if (unlikely (status)) {
+ if (cairo_surface_get_content (surface) == CAIRO_CONTENT_COLOR_ALPHA)
+ goto error;
+ else {
+ compositor->release (surface);
+ cairo_surface_destroy (surface);
+ cairo_surface_destroy (src);
+ surface = _cairo_surface_create_similar_scratch (dst, CAIRO_CONTENT_COLOR_ALPHA,
+ extents->bounded.width,
+ extents->bounded.height);
+ if (unlikely (surface->status))
+ return surface;
+ /* we are drawing color glyph */
+ draw_color_glyph = TRUE;
+ goto redo;
+ }
}
surface->is_clear = FALSE;
@@ -582,30 +584,31 @@ clip_and_composite_with_mask (const cairo_traps_compositor_t *compositor,
if (mask->is_clear)
goto skip;
- if (mask->content == CAIRO_CONTENT_ALPHA) {
- /* This is real mask */
- if (src != NULL || dst->content != CAIRO_CONTENT_ALPHA) {
- compositor->composite (dst, op, src, mask,
- extents->bounded.x + src_x,
- extents->bounded.y + src_y,
- 0, 0,
- extents->bounded.x, extents->bounded.y,
- extents->bounded.width, extents->bounded.height);
- } else {
- compositor->composite (dst, op, mask, NULL,
- 0, 0,
- 0, 0,
- extents->bounded.x, extents->bounded.y,
- extents->bounded.width, extents->bounded.height);
- }
+ if (mask->content == CAIRO_CONTENT_ALPHA) {
+ /* This is real mask */
+ if (src != NULL || dst->content != CAIRO_CONTENT_ALPHA) {
+ compositor->composite (dst, op, src, mask,
+ extents->bounded.x + src_x,
+ extents->bounded.y + src_y,
+ 0, 0,
+ extents->bounded.x, extents->bounded.y,
+ extents->bounded.width, extents->bounded.height);
} else {
- compositor->composite (dst, op, mask, NULL,
- 0, 0,
- extents->bounded.x + src_x,
- extents->bounded.y + src_y,
- extents->bounded.x, extents->bounded.y,
- extents->bounded.width, extents->bounded.height);
+ compositor->composite (dst, op, mask, NULL,
+ 0, 0,
+ 0, 0,
+ extents->bounded.x, extents->bounded.y,
+ extents->bounded.width, extents->bounded.height);
}
+ }
+ else {
+ compositor->composite (dst, op, mask, NULL,
+ 0, 0,
+ extents->bounded.x + src_x,
+ extents->bounded.y + src_y,
+ extents->bounded.x, extents->bounded.y,
+ extents->bounded.width, extents->bounded.height);
+ }
skip:
cairo_surface_destroy (mask);
return CAIRO_STATUS_SUCCESS;
@@ -629,9 +632,10 @@ clip_and_composite_combine (const cairo_traps_compositor_t *compositor,
TRACE ((stderr, "%s\n", __FUNCTION__));
- tmp = _cairo_surface_create_similar_scratch (dst, dst->content,
- extents->bounded.width,
- extents->bounded.height);
+ tmp = _cairo_surface_create_scratch (dst, dst->content,
+ extents->bounded.width,
+ extents->bounded.height,
+ NULL);
if (unlikely (tmp->status)) {
status = tmp->status;
cairo_surface_destroy (tmp);
@@ -701,15 +705,15 @@ clip_and_composite_source (const cairo_traps_compositor_t *compositor,
const cairo_composite_rectangles_t *extents)
{
cairo_surface_t *mask = NULL;
- /* create a white color pattern */
- cairo_pattern_t *white_pattern = _cairo_pattern_create_solid (CAIRO_COLOR_WHITE);
- cairo_surface_t *white_mask =
- compositor->pattern_to_surface (dst, white_pattern, TRUE,
- &extents->bounded,
- &extents->source_sample_area,
- &src_x, &src_y);
- if (unlikely (white_mask->status))
- goto skip;
+ /* create a white color pattern */
+ cairo_pattern_t *white_pattern = _cairo_pattern_create_solid (CAIRO_COLOR_WHITE);
+ cairo_surface_t *white_mask =
+ compositor->pattern_to_surface (dst, white_pattern, TRUE,
+ &extents->bounded,
+ &extents->source_sample_area,
+ &src_x, &src_y);
+ if (unlikely (white_mask->status))
+ goto skip;
TRACE ((stderr, "%s\n", __FUNCTION__));
@@ -731,22 +735,22 @@ clip_and_composite_source (const cairo_traps_compositor_t *compositor,
extents->bounded.width, extents->bounded.height);
} else {
if (mask->content == CAIRO_CONTENT_ALPHA)
- compositor->lerp (dst, src, mask,
- extents->bounded.x + src_x, extents->bounded.y + src_y,
+ compositor->lerp (dst, src, mask,
+ extents->bounded.x + src_x, extents->bounded.y + src_y,
+ 0, 0,
+ extents->bounded.x, extents->bounded.y,
+ extents->bounded.width, extents->bounded.height);
+ else
+ compositor->lerp_color_glyph (dst, mask, white_mask,
0, 0,
+ extents->bounded.x + src_x, extents->bounded.y + src_y,
extents->bounded.x, extents->bounded.y,
extents->bounded.width, extents->bounded.height);
- else
- compositor->lerp_color_glyph (dst, mask, white_mask,
- 0, 0,
- extents->bounded.x + src_x, extents->bounded.y + src_y,
- extents->bounded.x, extents->bounded.y,
- extents->bounded.width, extents->bounded.height);
- }
+ }
skip:
cairo_surface_destroy (mask);
- cairo_surface_destroy (white_mask);
+ cairo_surface_destroy (white_mask);
cairo_pattern_destroy (white_pattern);
return CAIRO_STATUS_SUCCESS;
@@ -988,12 +992,20 @@ need_bounded_clip (cairo_composite_rectangles_t *extents)
{
unsigned int flags = 0;
- if (extents->unbounded.width < extents->destination.width ||
- extents->unbounded.height < extents->destination.height)
+ if (extents->clip->num_boxes > 1 ||
+ extents->mask.width > extents->unbounded.width ||
+ extents->mask.height > extents->unbounded.height)
{
flags |= NEED_CLIP_REGION;
}
+ if (extents->clip->num_boxes > 1 ||
+ extents->mask.width > extents->bounded.width ||
+ extents->mask.height > extents->bounded.height)
+ {
+ flags |= FORCE_CLIP_REGION;
+ }
+
if (! _cairo_clip_is_region (extents->clip))
flags |= NEED_CLIP_SURFACE;
@@ -1258,7 +1270,9 @@ composite_aligned_boxes (const cairo_traps_compositor_t *compositor,
&extents->source_sample_area))
{
cairo_clip_t *recording_clip;
- cairo_pattern_t *source = &extents->source_pattern.base;
+ const cairo_pattern_t *source = &extents->source_pattern.base;
+ const cairo_matrix_t *m;
+ cairo_matrix_t matrix;
/* XXX could also do tiling repeat modes... */
@@ -1277,10 +1291,17 @@ composite_aligned_boxes (const cairo_traps_compositor_t *compositor,
return status;
}
+ m = &source->matrix;
+ if (_cairo_surface_has_device_transform (dst)) {
+ cairo_matrix_multiply (&matrix,
+ &source->matrix,
+ &dst->device_transform);
+ m = &matrix;
+ }
+
recording_clip = _cairo_clip_from_boxes (boxes);
status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (source),
- &source->matrix,
- dst, recording_clip);
+ m, dst, recording_clip);
_cairo_clip_destroy (recording_clip);
return status;
@@ -1433,7 +1454,7 @@ boxes_for_traps (cairo_boxes_t *boxes,
cairo_traps_t *traps,
cairo_antialias_t antialias)
{
- int i;
+ int i, j;
/* first check that the traps are rectilinear */
if (antialias == CAIRO_ANTIALIAS_NONE) {
@@ -1457,23 +1478,25 @@ boxes_for_traps (cairo_boxes_t *boxes,
_cairo_boxes_init (boxes);
- boxes->num_boxes = traps->num_traps;
boxes->chunks.base = (cairo_box_t *) traps->traps;
- boxes->chunks.count = traps->num_traps;
boxes->chunks.size = traps->num_traps;
if (antialias != CAIRO_ANTIALIAS_NONE) {
- for (i = 0; i < traps->num_traps; i++) {
+ for (i = j = 0; i < traps->num_traps; i++) {
/* Note the traps and boxes alias so we need to take the local copies first. */
cairo_fixed_t x1 = traps->traps[i].left.p1.x;
cairo_fixed_t x2 = traps->traps[i].right.p1.x;
cairo_fixed_t y1 = traps->traps[i].top;
cairo_fixed_t y2 = traps->traps[i].bottom;
- boxes->chunks.base[i].p1.x = x1;
- boxes->chunks.base[i].p1.y = y1;
- boxes->chunks.base[i].p2.x = x2;
- boxes->chunks.base[i].p2.y = y2;
+ if (x1 == x2 || y1 == y2)
+ continue;
+
+ boxes->chunks.base[j].p1.x = x1;
+ boxes->chunks.base[j].p1.y = y1;
+ boxes->chunks.base[j].p2.x = x2;
+ boxes->chunks.base[j].p2.y = y2;
+ j++;
if (boxes->is_pixel_aligned) {
boxes->is_pixel_aligned =
@@ -1484,7 +1507,7 @@ boxes_for_traps (cairo_boxes_t *boxes,
} else {
boxes->is_pixel_aligned = TRUE;
- for (i = 0; i < traps->num_traps; i++) {
+ for (i = j = 0; i < traps->num_traps; i++) {
/* Note the traps and boxes alias so we need to take the local copies first. */
cairo_fixed_t x1 = traps->traps[i].left.p1.x;
cairo_fixed_t x2 = traps->traps[i].right.p1.x;
@@ -1492,12 +1515,16 @@ boxes_for_traps (cairo_boxes_t *boxes,
cairo_fixed_t y2 = traps->traps[i].bottom;
/* round down here to match Pixman's behavior when using traps. */
- boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
- boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
- boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
- boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
+ boxes->chunks.base[j].p1.x = _cairo_fixed_round_down (x1);
+ boxes->chunks.base[j].p1.y = _cairo_fixed_round_down (y1);
+ boxes->chunks.base[j].p2.x = _cairo_fixed_round_down (x2);
+ boxes->chunks.base[j].p2.y = _cairo_fixed_round_down (y2);
+ j += (boxes->chunks.base[j].p1.x != boxes->chunks.base[j].p2.x &&
+ boxes->chunks.base[j].p1.y != boxes->chunks.base[j].p2.y);
}
}
+ boxes->chunks.count = j;
+ boxes->num_boxes = j;
return CAIRO_INT_STATUS_SUCCESS;
}
@@ -2220,18 +2247,14 @@ _cairo_traps_compositor_stroke (const cairo_compositor_t *_compositor,
double tolerance,
cairo_traps_t *traps);
composite_traps_info_t info;
- unsigned flags = 0;
+ unsigned flags;
if (antialias == CAIRO_ANTIALIAS_BEST || antialias == CAIRO_ANTIALIAS_GOOD) {
func = _cairo_path_fixed_stroke_polygon_to_traps;
+ flags = 0;
} else {
func = _cairo_path_fixed_stroke_to_traps;
- if (extents->clip->num_boxes > 1 ||
- extents->mask.width > extents->unbounded.width ||
- extents->mask.height > extents->unbounded.height)
- {
- flags = NEED_CLIP_REGION | FORCE_CLIP_REGION;
- }
+ flags = need_bounded_clip (extents) & ~NEED_CLIP_SURFACE;
}
info.antialias = antialias;
@@ -2353,16 +2376,12 @@ _cairo_traps_compositor_glyphs (const cairo_compositor_t *_compositor,
if (unlikely (status))
return status;
-#if ! CAIRO_HAS_TG_SURFACE
_cairo_scaled_font_freeze_cache (scaled_font);
-#endif
-
status = compositor->check_composite_glyphs (extents,
scaled_font, glyphs,
&num_glyphs);
if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
cairo_composite_glyphs_info_t info;
- unsigned flags = 0;
info.font = scaled_font;
info.glyphs = glyphs;
@@ -2370,21 +2389,11 @@ _cairo_traps_compositor_glyphs (const cairo_compositor_t *_compositor,
info.use_mask = overlap || ! extents->is_bounded;
info.extents = extents->bounded;
- if (extents->mask.width > extents->bounded.width ||
- extents->mask.height > extents->bounded.height)
- {
- flags |= FORCE_CLIP_REGION;
- }
-
status = clip_and_composite (compositor, extents,
composite_glyphs, NULL, &info,
- need_bounded_clip (extents) |
- flags);
+ need_bounded_clip (extents) | FORCE_CLIP_REGION);
}
-
-#if ! CAIRO_HAS_TG_SURFACE
_cairo_scaled_font_thaw_cache (scaled_font);
-#endif
return status;
}
diff --git a/src/cairo-traps-private.h b/src/cairo-traps-private.h
index 7fef062a4..dcaf40d18 100755..100644
--- a/src/cairo-traps-private.h
+++ b/src/cairo-traps-private.h
@@ -91,8 +91,9 @@ cairo_private void
_cairo_traps_translate (cairo_traps_t *traps, int x, int y);
cairo_private void
-_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
- const cairo_point_t t[3]);
+_cairo_traps_tessellate_triangle_with_edges (cairo_traps_t *traps,
+ const cairo_point_t t[3],
+ const cairo_point_t edges[4]);
cairo_private void
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
@@ -106,7 +107,8 @@ _cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
cairo_private void
_cairo_traps_add_trap (cairo_traps_t *traps,
cairo_fixed_t top, cairo_fixed_t bottom,
- cairo_line_t *left, cairo_line_t *right);
+ const cairo_line_t *left,
+ const cairo_line_t *right);
cairo_private int
_cairo_traps_contain (const cairo_traps_t *traps,
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 8bdac45ab..92abe4496 100755..100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -42,6 +42,7 @@
#include "cairo-box-inline.h"
#include "cairo-boxes-private.h"
#include "cairo-error-private.h"
+#include "cairo-line-private.h"
#include "cairo-region-private.h"
#include "cairo-slope-private.h"
#include "cairo-traps-private.h"
@@ -150,10 +151,20 @@ _cairo_traps_grow (cairo_traps_t *traps)
void
_cairo_traps_add_trap (cairo_traps_t *traps,
cairo_fixed_t top, cairo_fixed_t bottom,
- cairo_line_t *left, cairo_line_t *right)
+ const cairo_line_t *left,
+ const cairo_line_t *right)
{
cairo_trapezoid_t *trap;
+ /* These asserts cause reporting of unreal crashes
+ in the case of gl/msaa.
+ Temporarily removed */
+ /*
+ assert (left->p1.y != left->p2.y);
+ assert (right->p1.y != right->p2.y);
+ assert (bottom > top);
+ */
+
if (unlikely (traps->num_traps == traps->traps_size)) {
if (unlikely (! _cairo_traps_grow (traps)))
return;
@@ -169,7 +180,8 @@ _cairo_traps_add_trap (cairo_traps_t *traps,
static void
_cairo_traps_add_clipped_trap (cairo_traps_t *traps,
cairo_fixed_t _top, cairo_fixed_t _bottom,
- cairo_line_t *_left, cairo_line_t *_right)
+ const cairo_line_t *_left,
+ const cairo_line_t *_right)
{
/* Note: With the goofy trapezoid specification, (where an
* arbitrary two points on the lines can specified for the left
@@ -387,23 +399,73 @@ _cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
}
}
-/* A triangle is simply a degenerate case of a convex
- * quadrilateral. We would not benefit from having any distinct
- * implementation of triangle vs. quadrilateral tessellation here. */
-void
-_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
- const cairo_point_t t[3])
+static void add_tri (cairo_traps_t *traps,
+ int y1, int y2,
+ const cairo_line_t *left,
+ const cairo_line_t *right)
{
- cairo_point_t quad[4];
+ if (y2 < y1) {
+ int tmp = y1;
+ y1 = y2;
+ y2 = tmp;
+ }
- quad[0] = t[0];
- quad[1] = t[0];
- quad[2] = t[1];
- quad[3] = t[2];
+ if (cairo_lines_compare_at_y (left, right, y1) > 0) {
+ const cairo_line_t *tmp = left;
+ left = right;
+ right = tmp;
+ }
- _cairo_traps_tessellate_convex_quad (traps, quad);
+ _cairo_traps_add_clipped_trap (traps, y1, y2, left, right);
}
+void
+_cairo_traps_tessellate_triangle_with_edges (cairo_traps_t *traps,
+ const cairo_point_t t[3],
+ const cairo_point_t edges[4])
+{
+ cairo_line_t lines[3];
+
+ if (edges[0].y <= edges[1].y) {
+ lines[0].p1 = edges[0];
+ lines[0].p2 = edges[1];
+ } else {
+ lines[0].p1 = edges[1];
+ lines[0].p2 = edges[0];
+ }
+
+ if (edges[2].y <= edges[3].y) {
+ lines[1].p1 = edges[2];
+ lines[1].p2 = edges[3];
+ } else {
+ lines[1].p1 = edges[3];
+ lines[1].p2 = edges[2];
+ }
+
+ if (t[1].y == t[2].y) {
+ add_tri (traps, t[0].y, t[1].y, &lines[0], &lines[1]);
+ return;
+ }
+
+ if (t[1].y <= t[2].y) {
+ lines[2].p1 = t[1];
+ lines[2].p2 = t[2];
+ } else {
+ lines[2].p1 = t[2];
+ lines[2].p2 = t[1];
+ }
+
+ if (((t[1].y - t[0].y) < 0) ^ ((t[2].y - t[0].y) < 0)) {
+ add_tri (traps, t[0].y, t[1].y, &lines[0], &lines[2]);
+ add_tri (traps, t[0].y, t[2].y, &lines[1], &lines[2]);
+ } else if (abs(t[1].y - t[0].y) < abs(t[2].y - t[0].y)) {
+ add_tri (traps, t[0].y, t[1].y, &lines[0], &lines[1]);
+ add_tri (traps, t[1].y, t[2].y, &lines[2], &lines[1]);
+ } else {
+ add_tri (traps, t[0].y, t[2].y, &lines[1], &lines[0]);
+ add_tri (traps, t[1].y, t[2].y, &lines[2], &lines[0]);
+ }
+}
/**
* _cairo_traps_init_boxes:
diff --git a/src/cairo-tristrip-private.h b/src/cairo-tristrip-private.h
index ccd28799e..ccd28799e 100755..100644
--- a/src/cairo-tristrip-private.h
+++ b/src/cairo-tristrip-private.h
diff --git a/src/cairo-tristrip.c b/src/cairo-tristrip.c
index bb4972f50..bb4972f50 100755..100644
--- a/src/cairo-tristrip.c
+++ b/src/cairo-tristrip.c
diff --git a/src/cairo-truetype-subset-private.h b/src/cairo-truetype-subset-private.h
index dc9573216..dc9573216 100755..100644
--- a/src/cairo-truetype-subset-private.h
+++ b/src/cairo-truetype-subset-private.h
diff --git a/src/cairo-truetype-subset.c b/src/cairo-truetype-subset.c
index 44d7f60f5..fa33d63e4 100755..100644
--- a/src/cairo-truetype-subset.c
+++ b/src/cairo-truetype-subset.c
@@ -1572,40 +1572,11 @@ _cairo_truetype_read_font_name (cairo_scaled_font_t *scaled_font,
goto fail;
}
- free (name);
+ status = _cairo_escape_ps_name (&ps_name);
+ if (unlikely(status))
+ goto fail;
- /* Ensure PS name is a valid PDF/PS name object. In PDF names are
- * treated as UTF8 and non ASCII bytes, ' ', and '#' are encoded
- * as '#' followed by 2 hex digits that encode the byte. By also
- * encoding the characters in the reserved string we ensure the
- * name is also PS compatible. */
- if (ps_name) {
- static const char *reserved = "()<>[]{}/%#\\";
- char buf[128]; /* max name length is 127 bytes */
- char *src = ps_name;
- char *dst = buf;
-
- while (*src && dst < buf + 127) {
- unsigned char c = *src;
- if (c < 0x21 || c > 0x7e || strchr (reserved, c)) {
- if (dst + 4 > buf + 127)
- break;
-
- snprintf (dst, 4, "#%02X", c);
- src++;
- dst += 3;
- } else {
- *dst++ = *src++;
- }
- }
- *dst = 0;
- free (ps_name);
- ps_name = strdup (buf);
- if (ps_name == NULL) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto fail;
- }
- }
+ free (name);
*ps_name_out = ps_name;
*font_name_out = family_name;
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index d7d6eae12..d7d6eae12 100755..100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
diff --git a/src/cairo-type1-glyph-names.c b/src/cairo-type1-glyph-names.c
index 80ccb9626..80ccb9626 100755..100644
--- a/src/cairo-type1-glyph-names.c
+++ b/src/cairo-type1-glyph-names.c
diff --git a/src/cairo-type1-private.h b/src/cairo-type1-private.h
index 1630397bc..1630397bc 100755..100644
--- a/src/cairo-type1-private.h
+++ b/src/cairo-type1-private.h
diff --git a/src/cairo-type1-subset.c b/src/cairo-type1-subset.c
index 8453cbd7d..81a1bdbc1 100755..100644
--- a/src/cairo-type1-subset.c
+++ b/src/cairo-type1-subset.c
@@ -53,7 +53,6 @@
#include "cairo-output-stream-private.h"
#include <ctype.h>
-#include <locale.h>
#define TYPE1_STACKSIZE 24 /* Defined in Type 1 Font Format */
@@ -309,12 +308,10 @@ cairo_type1_font_subset_get_matrix (cairo_type1_font_subset_t *font,
const char *start, *end, *segment_end;
int ret, s_max, i, j;
char *s;
- struct lconv *locale_data;
const char *decimal_point;
int decimal_point_len;
- locale_data = localeconv ();
- decimal_point = locale_data->decimal_point;
+ decimal_point = cairo_get_locale_decimal_point ();
decimal_point_len = strlen (decimal_point);
assert (decimal_point_len != 0);
@@ -407,6 +404,7 @@ cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font)
const char *start, *end, *segment_end;
char *s;
int i;
+ cairo_status_t status;
segment_end = font->header_segment + font->header_segment_size;
start = find_token (font->header_segment, segment_end, "/FontName");
@@ -419,6 +417,9 @@ cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font)
if (end == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
+ while (end > start && _cairo_isspace(end[-1]))
+ end--;
+
s = malloc (end - start + 1);
if (unlikely (s == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -447,13 +448,9 @@ cairo_type1_font_subset_get_fontname (cairo_type1_font_subset_t *font)
if (unlikely (font->base.base_font == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- s = font->base.base_font;
- while (*s && !is_ps_delimiter(*s))
- s++;
-
- *s = 0;
+ status = _cairo_escape_ps_name (&font->base.base_font);
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
static cairo_status_t
@@ -1133,8 +1130,9 @@ write_used_glyphs (cairo_type1_font_subset_t *font,
cairo_status_t status;
char buffer[256];
int length;
- int subset_id;
+ unsigned int subset_id;
int ch;
+ const char *wa_name;
if (font->glyphs[glyph_number].subset_index < 0)
return CAIRO_STATUS_SUCCESS;
@@ -1146,12 +1144,18 @@ write_used_glyphs (cairo_type1_font_subset_t *font,
* font with the standard name.
**/
subset_id = font->glyphs[glyph_number].subset_index;
- if (subset_id > 0) {
+ /* Any additional glyph included for use by the seac operator
+ * will either have subset_id >= font->scaled_font_subset->num_glyphs
+ * or will not map to a winansi name (wa_name = NULL). In this
+ * case the original name is used.
+ */
+ if (subset_id > 0 && subset_id < font->scaled_font_subset->num_glyphs) {
ch = font->scaled_font_subset->to_latin_char[subset_id];
- name = _cairo_winansi_to_glyphname (ch);
- if (name == NULL)
- return CAIRO_STATUS_NULL_POINTER;
- name_length = strlen(name);
+ wa_name = _cairo_winansi_to_glyphname (ch);
+ if (wa_name) {
+ name = wa_name;
+ name_length = strlen(name);
+ }
}
}
@@ -1263,21 +1267,21 @@ cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
* the actual glyph definitions (charstrings).
*
* What we do here is scan directly to the /Subrs token, which
- * marks the beginning of the subroutines. We then read in all the
- * subroutines then move on to the /CharString token, which marks
- * the beginning of the glyph definitions, and read in the chastrings.
+ * marks the beginning of the subroutines. We read in all the
+ * subroutines, then move on to the /CharString token, which marks
+ * the beginning of the glyph definitions, and read in the charstrings.
*
- * The charstrings are parsed to extracts glyph widths, work out
- * which subroutines are called, and too see if any extra glyphs
+ * The charstrings are parsed to extract glyph widths, work out
+ * which subroutines are called, and to see if any extra glyphs
* need to be included due to the use of the seac glyph combining
* operator.
*
- * Finally the private dict is copied to the subset font minus the
+ * Finally, the private dict is copied to the subset font minus the
* subroutines and charstrings not required.
*/
/* Determine lenIV, the number of random characters at the start of
- each encrypted charstring. The defaults is 4, but this can be
+ each encrypted charstring. The default is 4, but this can be
overridden in the private dict. */
font->lenIV = 4;
if ((lenIV_start = find_token (font->cleartext, font->cleartext_end, "/lenIV")) != NULL) {
@@ -1313,6 +1317,7 @@ cairo_type1_font_subset_write_private_dict (cairo_type1_font_subset_t *font,
if (subrs == NULL) {
font->subset_subrs = FALSE;
p = font->cleartext;
+ array_start = NULL;
goto skip_subrs;
}
diff --git a/src/cairo-type3-glyph-surface-private.h b/src/cairo-type3-glyph-surface-private.h
index b4abcf604..6f40f1c25 100755..100644
--- a/src/cairo-type3-glyph-surface-private.h
+++ b/src/cairo-type3-glyph-surface-private.h
@@ -45,8 +45,9 @@
#include "cairo-surface-clipper-private.h"
#include "cairo-pdf-operators-private.h"
-typedef cairo_status_t (*cairo_type3_glyph_surface_emit_image_t) (cairo_image_surface_t *image,
- cairo_output_stream_t *stream);
+typedef cairo_int_status_t
+(*cairo_type3_glyph_surface_emit_image_t) (cairo_image_surface_t *image,
+ cairo_output_stream_t *stream);
typedef struct cairo_type3_glyph_surface {
cairo_surface_t base;
@@ -64,7 +65,8 @@ cairo_private cairo_surface_t *
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream,
cairo_type3_glyph_surface_emit_image_t emit_image,
- cairo_scaled_font_subsets_t *font_subsets);
+ cairo_scaled_font_subsets_t *font_subsets,
+ cairo_bool_t ps_output);
cairo_private void
_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface,
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index dc5dbdf61..63d2bd74c 100755..100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -74,7 +74,8 @@ cairo_surface_t *
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
cairo_output_stream_t *stream,
cairo_type3_glyph_surface_emit_image_t emit_image,
- cairo_scaled_font_subsets_t *font_subsets)
+ cairo_scaled_font_subsets_t *font_subsets,
+ cairo_bool_t ps)
{
cairo_type3_glyph_surface_t *surface;
cairo_matrix_t invert_y_axis;
@@ -106,7 +107,8 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
_cairo_pdf_operators_init (&surface->pdf_operators,
surface->stream,
&surface->cairo_to_pdf,
- font_subsets);
+ font_subsets,
+ ps);
_cairo_surface_clipper_init (&surface->clipper,
_cairo_type3_glyph_surface_clipper_intersect_clip_path);
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 5050fd552..9e2fd37e0 100755..100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -113,7 +113,7 @@ struct _cairo_observer {
};
/**
- * cairo_hash_entry_t:
+ * _cairo_hash_entry:
*
* A #cairo_hash_entry_t contains both a key and a value for
* #cairo_hash_table_t. User-derived types for #cairo_hash_entry_t must
@@ -158,7 +158,7 @@ struct _cairo_array {
};
/**
- * cairo_lcd_filter_t:
+ * _cairo_lcd_filter:
* @CAIRO_LCD_FILTER_DEFAULT: Use the default LCD filter for
* font backend and target device
* @CAIRO_LCD_FILTER_NONE: Do not perform LCD filtering
@@ -194,7 +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;
- cairo_font_color_t color;
+ cairo_font_color_t color;
};
struct _cairo_glyph_text_info {
@@ -447,7 +447,7 @@ typedef struct _cairo_shadow_cache {
double scale;
cairo_list_t link;
} cairo_shadow_cache_t;
-
+
CAIRO_END_DECLS
#endif /* CAIRO_TYPES_PRIVATE_H */
diff --git a/src/cairo-unicode.c b/src/cairo-unicode.c
index 88de39516..88de39516 100755..100644
--- a/src/cairo-unicode.c
+++ b/src/cairo-unicode.c
diff --git a/src/cairo-uninstalled.pc.in b/src/cairo-uninstalled.pc.in
index 9dc3231ae..9dc3231ae 100755..100644
--- a/src/cairo-uninstalled.pc.in
+++ b/src/cairo-uninstalled.pc.in
diff --git a/src/cairo-user-font-private.h b/src/cairo-user-font-private.h
index d54ef78b4..d54ef78b4 100755..100644
--- a/src/cairo-user-font-private.h
+++ b/src/cairo-user-font-private.h
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 297f21c91..6d2de2097 100755..100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -507,7 +507,7 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
const cairo_font_face_backend_t _cairo_user_font_face_backend = {
CAIRO_FONT_TYPE_USER,
_cairo_user_font_face_create_for_toy,
- NULL, /* destroy */
+ _cairo_font_face_destroy,
_cairo_user_font_face_scaled_font_create
};
diff --git a/src/cairo-version.c b/src/cairo-version.c
index d9ad240bf..a94cef681 100755..100644
--- a/src/cairo-version.c
+++ b/src/cairo-version.c
@@ -79,10 +79,10 @@
* 1.0.1 - Development on a maintenance branch (toward 1.0.2 release)
* 1.1.1 - Development on head (toward 1.1.2 snapshot and 1.2.0 release)
* </screen></informalexample>
- * </para>
+ *
* <refsect2>
* <title>Compatibility</title>
- * <para>
+ *
* The API/ABI compatibility guarantees for various versions are as
* follows. First, let's assume some cairo-using application code that is
* successfully using the API/ABI "from" one version of cairo. Then let's
@@ -102,11 +102,11 @@
* with the same in-development version number. This is because these
* numbers don't correspond to any fixed state of the software, but
* rather the many states between snapshots and releases.
- * </para>
+ *
* </refsect2>
* <refsect2>
* <title>Examining the version</title>
- * <para>
+ *
* Cairo provides the ability to examine the version at either
* compile-time or run-time and in both a human-readable form as well as
* an encoded form suitable for direct comparison. Cairo also provides the
@@ -135,8 +135,9 @@
* if (cairo_version() >= CAIRO_VERSION_ENCODE(1, 0, 0))
* printf ("Running with suitable cairo version: %s\n", cairo_version_string ());
* </programlisting></informalexample>
- * </para>
+ *
* </refsect2>
+ *
**/
/**
diff --git a/src/cairo-version.h b/src/cairo-version.h
index 51008003f..51008003f 100755..100644
--- a/src/cairo-version.h
+++ b/src/cairo-version.h
diff --git a/src/cairo-vg-surface.c b/src/cairo-vg-surface.c
index 6e0d9a0ed..6e0d9a0ed 100755..100644
--- a/src/cairo-vg-surface.c
+++ b/src/cairo-vg-surface.c
diff --git a/src/cairo-vg.h b/src/cairo-vg.h
index f9a62e51c..f9a62e51c 100755..100644
--- a/src/cairo-vg.h
+++ b/src/cairo-vg.h
diff --git a/src/cairo-wgl-context.c b/src/cairo-wgl-context.c
index 31cbcfe07..31cbcfe07 100755..100644
--- a/src/cairo-wgl-context.c
+++ b/src/cairo-wgl-context.c
diff --git a/src/cairo-wideint-private.h b/src/cairo-wideint-private.h
index 3f5491bb1..3f5491bb1 100755..100644
--- a/src/cairo-wideint-private.h
+++ b/src/cairo-wideint-private.h
diff --git a/src/cairo-wideint-type-private.h b/src/cairo-wideint-type-private.h
index 84a3cbab0..84a3cbab0 100755..100644
--- a/src/cairo-wideint-type-private.h
+++ b/src/cairo-wideint-type-private.h
diff --git a/src/cairo-wideint.c b/src/cairo-wideint.c
index bba266b24..2e056fa36 100755..100644
--- a/src/cairo-wideint.c
+++ b/src/cairo-wideint.c
@@ -654,16 +654,16 @@ _cairo_uint128_divrem (cairo_uint128_t num, cairo_uint128_t den)
return qr;
}
-cairo_int128_t
-_cairo_int128_negate (cairo_int128_t a)
+cairo_uint128_t
+_cairo_uint128_negate (cairo_uint128_t a)
{
a.lo = _cairo_uint64_not (a.lo);
a.hi = _cairo_uint64_not (a.hi);
return _cairo_uint128_add (a, _cairo_uint32_to_uint128 (1));
}
-cairo_int128_t
-_cairo_int128_not (cairo_int128_t a)
+cairo_uint128_t
+_cairo_uint128_not (cairo_uint128_t a)
{
a.lo = _cairo_uint64_not (a.lo);
a.hi = _cairo_uint64_not (a.hi);
diff --git a/src/cairo-win32.h b/src/cairo-win32.h
index 3d2e1c601..3d2e1c601 100755..100644
--- a/src/cairo-win32.h
+++ b/src/cairo-win32.h
diff --git a/src/cairo-xcb-connection-core.c b/src/cairo-xcb-connection-core.c
index ae7c023e1..e01dc1a83 100755..100644
--- a/src/cairo-xcb-connection-core.c
+++ b/src/cairo-xcb-connection-core.c
@@ -268,8 +268,6 @@ _cairo_xcb_connection_put_subimage (cairo_xcb_connection_t *connection,
if (rows > height)
rows = height;
- length = rows * cpp * width;
-
_cairo_xcb_connection_do_put_subimage (connection, dst, gc, src_x, src_y,
width, rows, cpp, stride, dst_x, dst_y, depth, _data);
@@ -283,32 +281,20 @@ _cairo_xcb_connection_put_subimage (cairo_xcb_connection_t *connection,
}
}
-cairo_status_t
+xcb_get_image_reply_t *
_cairo_xcb_connection_get_image (cairo_xcb_connection_t *connection,
xcb_drawable_t src,
int16_t src_x,
int16_t src_y,
uint16_t width,
- uint16_t height,
- xcb_get_image_reply_t **reply)
+ uint16_t height)
{
- xcb_generic_error_t *error;
-
- *reply = xcb_get_image_reply (connection->xcb_connection,
- xcb_get_image (connection->xcb_connection,
- XCB_IMAGE_FORMAT_Z_PIXMAP,
- src,
- src_x, src_y,
- width, height,
- (uint32_t) -1),
-
- &error);
- if (error) {
- free (error);
-
- free (*reply);
- *reply = NULL;
- }
-
- return CAIRO_STATUS_SUCCESS;
+ return xcb_get_image_reply (connection->xcb_connection,
+ xcb_get_image (connection->xcb_connection,
+ XCB_IMAGE_FORMAT_Z_PIXMAP,
+ src,
+ src_x, src_y,
+ width, height,
+ (uint32_t) -1),
+ NULL);
}
diff --git a/src/cairo-xcb-connection-render.c b/src/cairo-xcb-connection-render.c
index 83f1d482e..83f1d482e 100755..100644
--- a/src/cairo-xcb-connection-render.c
+++ b/src/cairo-xcb-connection-render.c
diff --git a/src/cairo-xcb-connection-shm.c b/src/cairo-xcb-connection-shm.c
index 8c1d50698..7720bbbd2 100755..100644
--- a/src/cairo-xcb-connection-shm.c
+++ b/src/cairo-xcb-connection-shm.c
@@ -82,7 +82,6 @@ _cairo_xcb_connection_shm_get_image (cairo_xcb_connection_t *connection,
uint32_t offset)
{
xcb_shm_get_image_reply_t *reply;
- xcb_generic_error_t *error;
assert (connection->flags & CAIRO_XCB_HAS_SHM);
reply = xcb_shm_get_image_reply (connection->xcb_connection,
@@ -93,12 +92,11 @@ _cairo_xcb_connection_shm_get_image (cairo_xcb_connection_t *connection,
(uint32_t) -1,
XCB_IMAGE_FORMAT_Z_PIXMAP,
shmseg, offset),
- &error);
+ NULL);
free (reply);
- if (error) {
+ if (!reply) {
/* an error here should be impossible */
- free (error);
return _cairo_error (CAIRO_STATUS_READ_ERROR);
}
diff --git a/src/cairo-xcb-connection.c b/src/cairo-xcb-connection.c
index 78bc9a101..a070720fd 100755..100644
--- a/src/cairo-xcb-connection.c
+++ b/src/cairo-xcb-connection.c
@@ -77,6 +77,9 @@ typedef struct _cairo_xcb_xid {
#define XCB_RENDER_HAS_PICTURE_TRANSFORM(surface) XCB_RENDER_AT_LEAST((surface), 0, 6)
#define XCB_RENDER_HAS_FILTERS(surface) XCB_RENDER_AT_LEAST((surface), 0, 6)
+#define XCB_RENDER_HAS_FILTER_GOOD(surface) FALSE
+#define XCB_RENDER_HAS_FILTER_BEST(surface) FALSE
+#define XCB_RENDER_HAS_SUBPIXEL_ORDER(surface) XCB_RENDER_AT_LEAST((surface), 0, 6)
#define XCB_RENDER_HAS_EXTENDED_REPEAT(surface) XCB_RENDER_AT_LEAST((surface), 0, 10)
#define XCB_RENDER_HAS_GRADIENTS(surface) XCB_RENDER_AT_LEAST((surface), 0, 10)
@@ -390,6 +393,12 @@ _cairo_xcb_connection_query_render (cairo_xcb_connection_t *connection)
if (XCB_RENDER_HAS_FILTERS (version))
connection->flags |= CAIRO_XCB_RENDER_HAS_FILTERS;
+ if (XCB_RENDER_HAS_FILTER_GOOD (version))
+ connection->flags |= CAIRO_XCB_RENDER_HAS_FILTER_GOOD;
+
+ if (XCB_RENDER_HAS_FILTER_BEST (version))
+ connection->flags |= CAIRO_XCB_RENDER_HAS_FILTER_BEST;
+
if (XCB_RENDER_HAS_PDF_OPERATORS (version))
connection->flags |= CAIRO_XCB_RENDER_HAS_PDF_OPERATORS;
@@ -399,6 +408,15 @@ _cairo_xcb_connection_query_render (cairo_xcb_connection_t *connection)
if (XCB_RENDER_HAS_GRADIENTS (version))
connection->flags |= CAIRO_XCB_RENDER_HAS_GRADIENTS;
+ if (XCB_RENDER_HAS_SUBPIXEL_ORDER (version)) {
+ uint32_t screen;
+ uint32_t *subpixel = xcb_render_query_pict_formats_subpixels(formats);
+
+ /* The spec explicitly allows to have too few entries in the reply... */
+ for (screen = 0; screen < formats->num_subpixel && screen < connection->root->roots_len; screen++)
+ connection->subpixel_orders[screen] = subpixel[screen];
+ }
+
free (version);
status = _cairo_xcb_connection_parse_xrender_formats (connection, formats);
@@ -573,6 +591,7 @@ _device_destroy (void *device)
CAIRO_MUTEX_FINI (connection->shm_mutex);
CAIRO_MUTEX_FINI (connection->screens_mutex);
+ free (connection->subpixel_orders);
free (connection);
}
@@ -684,6 +703,14 @@ _cairo_xcb_connection_get (xcb_connection_t *xcb_connection)
}
connection->render = NULL;
+ connection->subpixel_orders = calloc (connection->root->roots_len, sizeof(*connection->subpixel_orders));
+ if (unlikely (connection->subpixel_orders == NULL)) {
+ CAIRO_MUTEX_UNLOCK (connection->device.mutex);
+ _cairo_xcb_connection_destroy (connection);
+ connection = NULL;
+ goto unlock;
+ }
+
ext = xcb_get_extension_data (xcb_connection, &xcb_render_id);
if (ext != NULL && ext->present) {
status = _cairo_xcb_connection_query_render (connection);
@@ -890,6 +917,8 @@ cairo_xcb_device_debug_cap_xrender_version (cairo_device_t *device,
CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS |
CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM |
CAIRO_XCB_RENDER_HAS_FILTERS |
+ CAIRO_XCB_RENDER_HAS_FILTER_GOOD |
+ CAIRO_XCB_RENDER_HAS_FILTER_BEST |
CAIRO_XCB_RENDER_HAS_PDF_OPERATORS |
CAIRO_XCB_RENDER_HAS_EXTENDED_REPEAT |
CAIRO_XCB_RENDER_HAS_GRADIENTS);
diff --git a/src/cairo-xcb-private.h b/src/cairo-xcb-private.h
index d162d73d4..1ede8c716 100755..100644
--- a/src/cairo-xcb-private.h
+++ b/src/cairo-xcb-private.h
@@ -37,10 +37,10 @@
#ifndef CAIRO_XCB_PRIVATE_H
#define CAIRO_XCB_PRIVATE_H
-#include "cairo-xcb.h"
-
#include "cairoint.h"
+#include "cairo-xcb.h"
+
#include "cairo-cache-private.h"
#include "cairo-compiler-private.h"
#include "cairo-device-private.h"
@@ -75,6 +75,7 @@ typedef struct _cairo_xcb_surface cairo_xcb_surface_t;
typedef struct _cairo_xcb_picture cairo_xcb_picture_t;
typedef struct _cairo_xcb_shm_mem_pool cairo_xcb_shm_mem_pool_t;
typedef struct _cairo_xcb_shm_info cairo_xcb_shm_info_t;
+typedef struct _cairo_xcb_resources cairo_xcb_resources_t;
struct _cairo_xcb_shm_info {
cairo_xcb_connection_t *connection;
@@ -180,7 +181,8 @@ struct _cairo_xcb_font {
struct _cairo_xcb_screen {
cairo_xcb_connection_t *connection;
- xcb_screen_t *xcb_screen;
+ xcb_screen_t *xcb_screen;
+ xcb_render_sub_pixel_t subpixel_order;
xcb_gcontext_t gc[GC_CACHE_SIZE];
uint8_t gc_depths[GC_CACHE_SIZE];
@@ -199,6 +201,9 @@ struct _cairo_xcb_screen {
cairo_list_t link;
cairo_list_t surfaces;
cairo_list_t pictures;
+
+ cairo_bool_t has_font_options;
+ cairo_font_options_t font_options;
};
struct _cairo_xcb_connection {
@@ -219,6 +224,7 @@ struct _cairo_xcb_connection {
const xcb_setup_t *root;
const xcb_query_extension_reply_t *render;
const xcb_query_extension_reply_t *shm;
+ xcb_render_sub_pixel_t *subpixel_orders;
cairo_list_t free_xids;
cairo_freepool_t xid_pool;
@@ -236,6 +242,14 @@ struct _cairo_xcb_connection {
cairo_list_t link;
};
+struct _cairo_xcb_resources {
+ cairo_bool_t xft_antialias;
+ int xft_lcdfilter;
+ cairo_bool_t xft_hinting;
+ int xft_hintstyle;
+ int xft_rgba;
+};
+
enum {
CAIRO_XCB_HAS_RENDER = 0x0001,
CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES = 0x0002,
@@ -247,6 +261,8 @@ enum {
CAIRO_XCB_RENDER_HAS_PDF_OPERATORS = 0x0080,
CAIRO_XCB_RENDER_HAS_EXTENDED_REPEAT = 0x0100,
CAIRO_XCB_RENDER_HAS_GRADIENTS = 0x0200,
+ CAIRO_XCB_RENDER_HAS_FILTER_GOOD = 0x0400,
+ CAIRO_XCB_RENDER_HAS_FILTER_BEST = 0x0800,
CAIRO_XCB_HAS_SHM = 0x80000000,
@@ -259,7 +275,9 @@ enum {
CAIRO_XCB_RENDER_HAS_FILTERS |
CAIRO_XCB_RENDER_HAS_PDF_OPERATORS |
CAIRO_XCB_RENDER_HAS_EXTENDED_REPEAT |
- CAIRO_XCB_RENDER_HAS_GRADIENTS,
+ CAIRO_XCB_RENDER_HAS_GRADIENTS |
+ CAIRO_XCB_RENDER_HAS_FILTER_GOOD |
+ CAIRO_XCB_RENDER_HAS_FILTER_BEST,
CAIRO_XCB_SHM_MASK = CAIRO_XCB_HAS_SHM
};
@@ -267,6 +285,21 @@ enum {
cairo_private extern const cairo_surface_backend_t _cairo_xcb_surface_backend;
+/**
+ * _cairo_surface_is_xcb:
+ * @surface: a #cairo_surface_t
+ *
+ * Checks if a surface is an #cairo_xcb_surface_t
+ *
+ * Return value: %TRUE if the surface is an xcb surface
+ **/
+static inline cairo_bool_t
+_cairo_surface_is_xcb (const cairo_surface_t *surface)
+{
+ /* _cairo_surface_nil sets a NULL backend so be safe */
+ return surface->backend && surface->backend->type == CAIRO_SURFACE_TYPE_XCB;
+}
+
cairo_private cairo_xcb_connection_t *
_cairo_xcb_connection_get (xcb_connection_t *connection);
@@ -342,6 +375,9 @@ _cairo_xcb_screen_get_gc (cairo_xcb_screen_t *screen,
cairo_private void
_cairo_xcb_screen_put_gc (cairo_xcb_screen_t *screen, int depth, xcb_gcontext_t gc);
+cairo_private cairo_font_options_t *
+_cairo_xcb_screen_get_font_options (cairo_xcb_screen_t *screen);
+
cairo_private cairo_status_t
_cairo_xcb_screen_store_linear_picture (cairo_xcb_screen_t *screen,
const cairo_linear_pattern_t *linear,
@@ -505,14 +541,13 @@ _cairo_xcb_connection_put_subimage (cairo_xcb_connection_t *connection,
uint8_t depth,
void *data);
-cairo_private cairo_status_t
+cairo_private xcb_get_image_reply_t *
_cairo_xcb_connection_get_image (cairo_xcb_connection_t *connection,
xcb_drawable_t src,
int16_t src_x,
int16_t src_y,
uint16_t width,
- uint16_t height,
- xcb_get_image_reply_t **reply);
+ uint16_t height);
cairo_private void
_cairo_xcb_connection_poly_fill_rectangle (cairo_xcb_connection_t *connection,
@@ -767,4 +802,8 @@ slim_hidden_proto_no_warn (cairo_xcb_device_debug_set_precision);
slim_hidden_proto_no_warn (cairo_xcb_device_debug_cap_xrender_version);
#endif
+cairo_private void
+_cairo_xcb_resources_get (cairo_xcb_screen_t *screen,
+ cairo_xcb_resources_t *resources);
+
#endif /* CAIRO_XCB_PRIVATE_H */
diff --git a/src/cairo-xcb-resources.c b/src/cairo-xcb-resources.c
new file mode 100644
index 000000000..1877758c2
--- /dev/null
+++ b/src/cairo-xcb-resources.c
@@ -0,0 +1,281 @@
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2014 Lukas Lalinsky
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Authors:
+ * Lukas Lalinsky <lukas@oxygene.sk>
+ *
+ * Partially on code from xftdpy.c
+ *
+ * Copyright © 2000 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "cairoint.h"
+
+#include "cairo-xcb-private.h"
+
+#include "cairo-fontconfig-private.h"
+
+static void
+parse_boolean (const char *v, cairo_bool_t *out)
+{
+ char c0, c1;
+
+ c0 = *v;
+ if (c0 == 't' || c0 == 'T' || c0 == 'y' || c0 == 'Y' || c0 == '1')
+ *out = TRUE;
+ if (c0 == 'f' || c0 == 'F' || c0 == 'n' || c0 == 'N' || c0 == '0')
+ *out = FALSE;
+ if (c0 == 'o') {
+ c1 = v[1];
+ if (c1 == 'n' || c1 == 'N')
+ *out = TRUE;
+ if (c1 == 'f' || c1 == 'F')
+ *out = FALSE;
+ }
+}
+
+static void
+parse_integer (const char *v, int *out)
+{
+ char *e;
+ int value;
+
+#if CAIRO_HAS_FC_FONT
+ if (FcNameConstant ((FcChar8 *) v, out))
+ return;
+#endif
+
+ value = strtol (v, &e, 0);
+ if (e != v)
+ *out = value;
+}
+
+static char *
+skip_spaces(char *str)
+{
+ while (*str == ' ' || *str == '\t' || *str == '\n')
+ str++;
+ return str;
+}
+
+struct resource_parser {
+ int buffer_size;
+ int bytes_in_buffer;
+ char* buffer;
+ cairo_xcb_resources_t *resources;
+};
+
+static cairo_bool_t
+resource_parse_line (char *name, cairo_xcb_resources_t *resources)
+{
+ char *value;
+
+ value = strchr (name, ':');
+ if (value == NULL)
+ return FALSE;
+
+ *value++ = 0;
+
+ name = skip_spaces (name);
+ value = skip_spaces (value);
+
+ if (strcmp (name, "Xft.antialias") == 0)
+ parse_boolean (value, &(resources->xft_antialias));
+ else if (strcmp (name, "Xft.lcdfilter") == 0)
+ parse_integer (value, &(resources->xft_lcdfilter));
+ else if (strcmp (name, "Xft.rgba") == 0)
+ parse_integer (value, &(resources->xft_rgba));
+ else if (strcmp (name, "Xft.hinting") == 0)
+ parse_boolean (value, &(resources->xft_hinting));
+ else if (strcmp (name, "Xft.hintstyle") == 0)
+ parse_integer (value, &(resources->xft_hintstyle));
+
+ return TRUE;
+}
+
+static int
+resource_parse_lines (struct resource_parser *parser)
+{
+ char *line, *newline;
+
+ line = parser->buffer;
+ while (1) {
+ newline = strchr (line, '\n');
+ if (newline == NULL)
+ break;
+
+ *newline++ = 0;
+
+ if (! resource_parse_line (line, parser->resources))
+ break;
+
+ line = newline;
+ }
+
+ return line - parser->buffer;
+}
+
+static void
+resource_parser_init (struct resource_parser *parser, cairo_xcb_resources_t *resources)
+{
+ parser->buffer_size = 0;
+ parser->bytes_in_buffer = 0;
+ parser->buffer = NULL;
+ parser->resources = resources;
+}
+
+static cairo_bool_t
+resource_parser_update (struct resource_parser *parser, const char *data, int length)
+{
+ int bytes_parsed;
+
+ if (parser->bytes_in_buffer + length + 1 > parser->buffer_size) {
+ parser->buffer_size = parser->bytes_in_buffer + length + 1;
+ parser->buffer = realloc(parser->buffer, parser->buffer_size);
+ if (! parser->buffer) {
+ parser->buffer_size = 0;
+ parser->bytes_in_buffer = 0;
+ return FALSE;
+ }
+ }
+
+ memmove (parser->buffer + parser->bytes_in_buffer, data, length);
+ parser->bytes_in_buffer += length;
+ parser->buffer[parser->bytes_in_buffer] = 0;
+
+ bytes_parsed = resource_parse_lines (parser);
+
+ if (parser->bytes_in_buffer > bytes_parsed) {
+ memmove (parser->buffer, parser->buffer + bytes_parsed, parser->bytes_in_buffer - bytes_parsed);
+ parser->bytes_in_buffer -= bytes_parsed;
+ } else {
+ parser->bytes_in_buffer = 0;
+ }
+
+ return TRUE;
+}
+
+static void
+resource_parser_done (struct resource_parser *parser)
+{
+ if (parser->bytes_in_buffer > 0) {
+ parser->buffer[parser->bytes_in_buffer] = 0;
+ resource_parse_line (parser->buffer, parser->resources);
+ }
+
+ free (parser->buffer);
+}
+
+static void
+get_resources(xcb_connection_t *connection, xcb_screen_t *screen, cairo_xcb_resources_t *resources)
+{
+ xcb_get_property_cookie_t cookie;
+ xcb_get_property_reply_t *reply;
+ struct resource_parser parser;
+ int offset;
+ cairo_bool_t has_more_data;
+
+ resources->xft_antialias = TRUE;
+ resources->xft_lcdfilter = -1;
+ resources->xft_hinting = TRUE;
+ resources->xft_hintstyle = FC_HINT_FULL;
+ resources->xft_rgba = FC_RGBA_UNKNOWN;
+
+ resource_parser_init (&parser, resources);
+
+ offset = 0;
+ has_more_data = FALSE;
+ do {
+ cookie = xcb_get_property (connection, 0, screen->root, XCB_ATOM_RESOURCE_MANAGER, XCB_ATOM_STRING, offset, 1024);
+ reply = xcb_get_property_reply (connection, cookie, NULL);
+
+ if (reply) {
+ if (reply->format == 8 && reply->type == XCB_ATOM_STRING) {
+ char *value = (char *) xcb_get_property_value (reply);
+ int length = xcb_get_property_value_length (reply);
+
+ offset += length / 4; /* X needs the offset in 'long' units */
+ has_more_data = reply->bytes_after > 0;
+
+ if (! resource_parser_update (&parser, value, length))
+ has_more_data = FALSE; /* early exit on error */
+ }
+
+ free (reply);
+ }
+ } while (has_more_data);
+
+ resource_parser_done (&parser);
+}
+
+void
+_cairo_xcb_resources_get (cairo_xcb_screen_t *screen, cairo_xcb_resources_t *resources)
+{
+ get_resources (screen->connection->xcb_connection, screen->xcb_screen, resources);
+
+ if (resources->xft_rgba == FC_RGBA_UNKNOWN) {
+ switch (screen->subpixel_order) {
+ case XCB_RENDER_SUB_PIXEL_UNKNOWN:
+ resources->xft_rgba = FC_RGBA_UNKNOWN;
+ break;
+ case XCB_RENDER_SUB_PIXEL_HORIZONTAL_RGB:
+ resources->xft_rgba = FC_RGBA_RGB;
+ break;
+ case XCB_RENDER_SUB_PIXEL_HORIZONTAL_BGR:
+ resources->xft_rgba = FC_RGBA_BGR;
+ break;
+ case XCB_RENDER_SUB_PIXEL_VERTICAL_RGB:
+ resources->xft_rgba = FC_RGBA_VRGB;
+ break;
+ case XCB_RENDER_SUB_PIXEL_VERTICAL_BGR:
+ resources->xft_rgba = FC_RGBA_VBGR;
+ break;
+ case XCB_RENDER_SUB_PIXEL_NONE:
+ resources->xft_rgba = FC_RGBA_NONE;
+ break;
+ }
+ }
+}
diff --git a/src/cairo-xcb-screen.c b/src/cairo-xcb-screen.c
index 2858d23fb..d0019f9cd 100755..100644
--- a/src/cairo-xcb-screen.c
+++ b/src/cairo-xcb-screen.c
@@ -35,6 +35,96 @@
#include "cairo-xcb-private.h"
#include "cairo-list-inline.h"
+#include "cairo-fontconfig-private.h"
+
+static void
+_cairo_xcb_init_screen_font_options (cairo_xcb_screen_t *screen)
+{
+ cairo_xcb_resources_t res;
+ cairo_antialias_t antialias;
+ cairo_subpixel_order_t subpixel_order;
+ cairo_lcd_filter_t lcd_filter;
+ cairo_hint_style_t hint_style;
+
+ _cairo_xcb_resources_get (screen, &res);
+
+ /* the rest of the code in this function is copied from
+ _cairo_xlib_init_screen_font_options in cairo-xlib-screen.c */
+
+ if (res.xft_hinting) {
+ switch (res.xft_hintstyle) {
+ case FC_HINT_NONE:
+ hint_style = CAIRO_HINT_STYLE_NONE;
+ break;
+ case FC_HINT_SLIGHT:
+ hint_style = CAIRO_HINT_STYLE_SLIGHT;
+ break;
+ case FC_HINT_MEDIUM:
+ hint_style = CAIRO_HINT_STYLE_MEDIUM;
+ break;
+ case FC_HINT_FULL:
+ hint_style = CAIRO_HINT_STYLE_FULL;
+ break;
+ default:
+ hint_style = CAIRO_HINT_STYLE_DEFAULT;
+ }
+ } else {
+ hint_style = CAIRO_HINT_STYLE_NONE;
+ }
+
+ switch (res.xft_rgba) {
+ case FC_RGBA_RGB:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
+ break;
+ case FC_RGBA_BGR:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
+ break;
+ case FC_RGBA_VRGB:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
+ break;
+ case FC_RGBA_VBGR:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
+ break;
+ case FC_RGBA_UNKNOWN:
+ case FC_RGBA_NONE:
+ default:
+ subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+ }
+
+ switch (res.xft_lcdfilter) {
+ case FC_LCD_NONE:
+ lcd_filter = CAIRO_LCD_FILTER_NONE;
+ break;
+ case FC_LCD_DEFAULT:
+ lcd_filter = CAIRO_LCD_FILTER_FIR5;
+ break;
+ case FC_LCD_LIGHT:
+ lcd_filter = CAIRO_LCD_FILTER_FIR3;
+ break;
+ case FC_LCD_LEGACY:
+ lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
+ break;
+ default:
+ lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
+ break;
+ }
+
+ if (res.xft_antialias) {
+ if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
+ antialias = CAIRO_ANTIALIAS_GRAY;
+ else
+ antialias = CAIRO_ANTIALIAS_SUBPIXEL;
+ } else {
+ antialias = CAIRO_ANTIALIAS_NONE;
+ }
+
+ cairo_font_options_set_hint_style (&screen->font_options, hint_style);
+ cairo_font_options_set_antialias (&screen->font_options, antialias);
+ cairo_font_options_set_subpixel_order (&screen->font_options, subpixel_order);
+ _cairo_font_options_set_lcd_filter (&screen->font_options, lcd_filter);
+ cairo_font_options_set_hint_metrics (&screen->font_options, CAIRO_HINT_METRICS_ON);
+}
+
struct pattern_cache_entry {
cairo_cache_entry_t key;
cairo_xcb_screen_t *screen;
@@ -117,6 +207,18 @@ _pattern_cache_entry_destroy (void *closure)
_cairo_freelist_free (&entry->screen->pattern_cache_entry_freelist, entry);
}
+static int _get_screen_index(cairo_xcb_connection_t *xcb_connection,
+ xcb_screen_t *xcb_screen)
+{
+ int idx = 0;
+ xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_connection->root);
+ for (; iter.rem; xcb_screen_next(&iter), idx++)
+ if (iter.data->root == xcb_screen->root)
+ return idx;
+
+ ASSERT_NOT_REACHED;
+}
+
cairo_xcb_screen_t *
_cairo_xcb_screen_get (xcb_connection_t *xcb_connection,
xcb_screen_t *xcb_screen)
@@ -124,6 +226,7 @@ _cairo_xcb_screen_get (xcb_connection_t *xcb_connection,
cairo_xcb_connection_t *connection;
cairo_xcb_screen_t *screen;
cairo_status_t status;
+ int screen_idx;
int i;
connection = _cairo_xcb_connection_get (xcb_connection);
@@ -150,8 +253,12 @@ _cairo_xcb_screen_get (xcb_connection_t *xcb_connection,
if (unlikely (screen == NULL))
goto unlock;
+ screen_idx = _get_screen_index(connection, xcb_screen);
+
screen->connection = connection;
screen->xcb_screen = xcb_screen;
+ screen->has_font_options = FALSE;
+ screen->subpixel_order = connection->subpixel_orders[screen_idx];
_cairo_freelist_init (&screen->pattern_cache_entry_freelist,
sizeof (struct pattern_cache_entry));
@@ -362,3 +469,26 @@ _cairo_xcb_screen_lookup_radial_picture (cairo_xcb_screen_t *screen,
return picture;
}
+
+cairo_font_options_t *
+_cairo_xcb_screen_get_font_options (cairo_xcb_screen_t *screen)
+{
+ if (! screen->has_font_options) {
+ _cairo_font_options_init_default (&screen->font_options);
+ _cairo_font_options_set_round_glyph_positions (&screen->font_options, CAIRO_ROUND_GLYPH_POS_ON);
+
+ /* XXX: This is disabled because something seems to be merging
+ font options incorrectly for xcb. This effectively reverts
+ the changes brought in git e691d242, and restores ~150 tests
+ to resume passing. See mailing list archives for Sep 17,
+ 2014 for more discussion. */
+ if (0 && ! _cairo_xcb_connection_acquire (screen->connection)) {
+ _cairo_xcb_init_screen_font_options (screen);
+ _cairo_xcb_connection_release (screen->connection);
+ }
+
+ screen->has_font_options = TRUE;
+ }
+
+ return &screen->font_options;
+}
diff --git a/src/cairo-xcb-shm.c b/src/cairo-xcb-shm.c
index 2be2dac5b..2be2dac5b 100755..100644
--- a/src/cairo-xcb-shm.c
+++ b/src/cairo-xcb-shm.c
diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c
index db775cd17..e78cd80c2 100755..100644
--- a/src/cairo-xcb-surface-core.c
+++ b/src/cairo-xcb-surface-core.c
@@ -409,7 +409,7 @@ _cairo_xcb_surface_pixmap (cairo_xcb_surface_t *target,
if (pixmap != NULL && pixmap->screen == target->screen)
return (cairo_xcb_pixmap_t *) cairo_surface_reference (&pixmap->base);
- if (source->type == CAIRO_SURFACE_TYPE_XCB &&
+ if (_cairo_surface_is_xcb(source) &&
((cairo_xcb_surface_t *) source)->screen == target->screen)
{
cairo_xcb_surface_t *xcb_source = (cairo_xcb_surface_t *) source;
@@ -576,7 +576,7 @@ _cairo_xcb_surface_core_copy_boxes (cairo_xcb_surface_t *dst,
src->x0 + x1,
src->y0 + y1,
x1, y1,
- x2 - x2, y2 - x2);
+ x2 - x1, y2 - y1);
}
}
}
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index c6393a809..eec45c7f3 100755..100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -39,6 +39,7 @@
#include "cairo-clip-inline.h"
#include "cairo-clip-private.h"
#include "cairo-composite-rectangles-private.h"
+#include "cairo-image-surface-inline.h"
#include "cairo-image-surface-private.h"
#include "cairo-list-inline.h"
#include "cairo-region-private.h"
@@ -396,11 +397,6 @@ _pattern_is_supported (uint32_t flags,
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
return TRUE;
- if (! _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL)) {
- if ((flags & CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM) == 0)
- return FALSE;
- }
-
switch (pattern->extend) {
default:
ASSERT_NOT_REACHED;
@@ -414,19 +410,22 @@ _pattern_is_supported (uint32_t flags,
}
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
- cairo_filter_t filter;
-
- filter = pattern->filter;
- if (_cairo_matrix_has_unity_scale (&pattern->matrix) &&
- _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL))
- {
- filter = CAIRO_FILTER_NEAREST;
- }
-
- if (! (filter == CAIRO_FILTER_NEAREST || filter == CAIRO_FILTER_FAST)) {
- if ((flags & CAIRO_XCB_RENDER_HAS_FILTERS) == 0)
- return FALSE;
+ switch (pattern->filter) {
+ case CAIRO_FILTER_FAST:
+ case CAIRO_FILTER_NEAREST:
+ return (flags & CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM) ||
+ _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL);
+ case CAIRO_FILTER_GOOD:
+ return flags & CAIRO_XCB_RENDER_HAS_FILTER_GOOD;
+ case CAIRO_FILTER_BEST:
+ return flags & CAIRO_XCB_RENDER_HAS_FILTER_BEST;
+ case CAIRO_FILTER_BILINEAR:
+ case CAIRO_FILTER_GAUSSIAN:
+ default:
+ return flags & CAIRO_XCB_RENDER_HAS_FILTERS;
}
+ } else if (pattern->type == CAIRO_PATTERN_TYPE_MESH) {
+ return FALSE;
} else { /* gradient */
if ((flags & CAIRO_XCB_RENDER_HAS_GRADIENTS) == 0)
return FALSE;
@@ -438,9 +437,8 @@ _pattern_is_supported (uint32_t flags,
{
return FALSE;
}
+ return TRUE;
}
-
- return pattern->type != CAIRO_PATTERN_TYPE_MESH;
}
static void
@@ -519,7 +517,7 @@ _cairo_xcb_picture_set_filter (cairo_xcb_picture_t *picture,
render_filter = "best";
len = strlen ("best");
}
- else {
+ else {
render_filter = "convolution";
len = strlen ("convolution");
}
@@ -1045,9 +1043,7 @@ _cairo_xcb_surface_setup_surface_picture(cairo_xcb_picture_t *picture,
filter = pattern->base.filter;
if (filter != CAIRO_FILTER_NEAREST &&
- _cairo_matrix_has_unity_scale (&pattern->base.matrix) &&
- _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.x0)) &&
- _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.y0)))
+ _cairo_matrix_is_pixel_exact (&pattern->base.matrix))
{
filter = CAIRO_FILTER_NEAREST;
}
@@ -1113,10 +1109,11 @@ record_to_picture (cairo_surface_t *target,
return _cairo_xcb_transparent_picture ((cairo_xcb_surface_t *) target);
/* Now draw the recording surface to an xcb surface */
- tmp = _cairo_surface_create_similar_scratch (target,
- source->content,
- limit.width,
- limit.height);
+ tmp = _cairo_surface_create_scratch (target,
+ source->content,
+ limit.width,
+ limit.height,
+ CAIRO_COLOR_TRANSPARENT);
if (tmp->status != CAIRO_STATUS_SUCCESS) {
return (cairo_xcb_picture_t *) tmp;
}
@@ -1176,13 +1173,13 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
/* restore transform */
if (filtered_picture != picture) {
- _cairo_xcb_picture_set_matrix (filtered_picture,
+ _cairo_xcb_picture_set_matrix (filtered_picture,
&pattern->base.matrix,
pattern->base.filter,
extents->x + extents->width/2.,
extents->y + extents->height/2.);
- _cairo_xcb_picture_set_matrix (picture,
+ _cairo_xcb_picture_set_matrix (picture,
&pattern->base.matrix,
pattern->base.filter,
extents->x + extents->width/2.,
@@ -1199,7 +1196,7 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
if (source->type == CAIRO_SURFACE_TYPE_XCB)
{
- if (source->backend->type == CAIRO_SURFACE_TYPE_XCB) {
+ if (_cairo_surface_is_xcb(source)) {
cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) source;
if (xcb->screen == target->screen && xcb->fallback == NULL) {
picture = _copy_to_picture ((cairo_xcb_surface_t *) source);
@@ -1360,13 +1357,13 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
/* restore transform */
if (filtered_picture != picture) {
- _cairo_xcb_picture_set_matrix (filtered_picture,
+ _cairo_xcb_picture_set_matrix (filtered_picture,
&pattern->base.matrix,
pattern->base.filter,
extents->x + extents->width/2.,
extents->y + extents->height/2.);
- _cairo_xcb_picture_set_matrix (picture,
+ _cairo_xcb_picture_set_matrix (picture,
&pattern->base.matrix,
pattern->base.filter,
extents->x + extents->width/2.,
@@ -1425,7 +1422,7 @@ _render_fill_boxes (void *abstract_dst,
cairo_boxes_t *boxes)
{
cairo_xcb_surface_t *dst = abstract_dst;
- xcb_rectangle_t stack_xrects[CAIRO_STACK_ARRAY_LENGTH (sizeof (xcb_rectangle_t))];
+ xcb_rectangle_t stack_xrects[CAIRO_STACK_ARRAY_LENGTH (xcb_rectangle_t)];
xcb_rectangle_t *xrects = stack_xrects;
xcb_render_color_t render_color;
int render_op = _render_operator (op);
@@ -1581,7 +1578,7 @@ _render_composite_boxes (cairo_xcb_surface_t *dst,
src->x + extents->x, src->y + extents->y,
0, 0,
extents->x, extents->y,
- extents->width, extents->height);
+ extents->width, extents->height);
}
@@ -1770,11 +1767,11 @@ get_clip_surface (const cairo_clip_t *clip,
cairo_surface_t *surface;
cairo_status_t status;
- surface = _cairo_surface_create_similar_solid (&target->base,
- CAIRO_CONTENT_ALPHA,
- clip->extents.width,
- clip->extents.height,
- CAIRO_COLOR_WHITE);
+ surface = _cairo_surface_create_scratch (&target->base,
+ CAIRO_CONTENT_ALPHA,
+ clip->extents.width,
+ clip->extents.height,
+ CAIRO_COLOR_WHITE);
if (unlikely (surface->status))
return (cairo_xcb_surface_t *) surface;
@@ -2033,7 +2030,7 @@ _clip_and_composite_combine (cairo_clip_t *clip,
{
cairo_xcb_surface_t *tmp;
cairo_xcb_surface_t *clip_surface;
- int clip_x, clip_y;
+ int clip_x = 0, clip_y = 0;
xcb_render_picture_t clip_picture;
cairo_status_t status;
@@ -2336,7 +2333,7 @@ _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst,
cairo_clip_t *clip)
{
cairo_xcb_surface_t *mask;
- int mask_x, mask_y;
+ int mask_x = 0, mask_y = 0;
mask = get_clip_surface (clip, dst, &mask_x, &mask_y);
if (unlikely (mask->base.status))
@@ -2739,7 +2736,7 @@ _composite_boxes (cairo_xcb_surface_t *dst,
if (need_clip_mask) {
cairo_xcb_surface_t *clip_surface;
- int clip_x, clip_y;
+ int clip_x = 0, clip_y = 0;
clip_surface = get_clip_surface (extents->clip, dst,
&clip_x, &clip_y);
@@ -2877,7 +2874,7 @@ _upload_image_inplace (cairo_xcb_surface_t *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
pattern = (const cairo_surface_pattern_t *) source;
- if (pattern->surface->type != CAIRO_SURFACE_TYPE_IMAGE)
+ if (! _cairo_surface_is_image (pattern->surface))
return CAIRO_INT_STATUS_UNSUPPORTED;
/* Have we already upload this image to a pixmap? */
@@ -2992,27 +2989,29 @@ _boxes_for_traps (cairo_boxes_t *boxes,
cairo_traps_t *traps,
cairo_antialias_t antialias)
{
- int i;
+ int i, j;
_cairo_boxes_init (boxes);
- boxes->num_boxes = traps->num_traps;
boxes->chunks.base = (cairo_box_t *) traps->traps;
- boxes->chunks.count = traps->num_traps;
boxes->chunks.size = traps->num_traps;
if (antialias != CAIRO_ANTIALIAS_NONE) {
- for (i = 0; i < traps->num_traps; i++) {
+ for (i = j = 0; i < traps->num_traps; i++) {
/* Note the traps and boxes alias so we need to take the local copies first. */
cairo_fixed_t x1 = traps->traps[i].left.p1.x;
cairo_fixed_t x2 = traps->traps[i].right.p1.x;
cairo_fixed_t y1 = traps->traps[i].top;
cairo_fixed_t y2 = traps->traps[i].bottom;
- boxes->chunks.base[i].p1.x = x1;
- boxes->chunks.base[i].p1.y = y1;
- boxes->chunks.base[i].p2.x = x2;
- boxes->chunks.base[i].p2.y = y2;
+ if (x1 == x2 || y1 == y2)
+ continue;
+
+ boxes->chunks.base[j].p1.x = x1;
+ boxes->chunks.base[j].p1.y = y1;
+ boxes->chunks.base[j].p2.x = x2;
+ boxes->chunks.base[j].p2.y = y2;
+ j++;
if (boxes->is_pixel_aligned) {
boxes->is_pixel_aligned =
@@ -3023,7 +3022,7 @@ _boxes_for_traps (cairo_boxes_t *boxes,
} else {
boxes->is_pixel_aligned = TRUE;
- for (i = 0; i < traps->num_traps; i++) {
+ for (i = j = 0; i < traps->num_traps; i++) {
/* Note the traps and boxes alias so we need to take the local copies first. */
cairo_fixed_t x1 = traps->traps[i].left.p1.x;
cairo_fixed_t x2 = traps->traps[i].right.p1.x;
@@ -3031,12 +3030,18 @@ _boxes_for_traps (cairo_boxes_t *boxes,
cairo_fixed_t y2 = traps->traps[i].bottom;
/* round down here to match Pixman's behavior when using traps. */
- boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
- boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
- boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
- boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
+ boxes->chunks.base[j].p1.x = _cairo_fixed_round_down (x1);
+ boxes->chunks.base[j].p1.y = _cairo_fixed_round_down (y1);
+ boxes->chunks.base[j].p2.x = _cairo_fixed_round_down (x2);
+ boxes->chunks.base[j].p2.y = _cairo_fixed_round_down (y2);
+
+ j += (boxes->chunks.base[j].p1.x != boxes->chunks.base[j].p2.x &&
+ boxes->chunks.base[j].p1.y != boxes->chunks.base[j].p2.y);
}
}
+
+ boxes->num_boxes = j;
+ boxes->chunks.count = j;
}
static cairo_status_t
@@ -3209,6 +3214,9 @@ _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
clip = _cairo_clip_copy (extents->clip);
clip = _cairo_clip_intersect_boxes (clip, boxes);
+ if (_cairo_clip_is_all_clipped (clip))
+ return CAIRO_INT_STATUS_NOTHING_TO_DO;
+
status = _cairo_clip_get_polygon (clip, &polygon,
&fill_rule, &antialias);
_cairo_clip_path_destroy (clip->path);
@@ -4561,6 +4569,9 @@ _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection,
const uint8_t *d;
uint8_t *new, *n;
+ if (c == 0)
+ break;
+
new = malloc (c);
if (unlikely (new == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -4589,6 +4600,9 @@ _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection,
const uint32_t *d;
uint32_t *new, *n;
+ if (c == 0)
+ break;
+
new = malloc (4 * c);
if (unlikely (new == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -4979,36 +4993,36 @@ _create_convolution_coef (double *convolution_matrix,
return NULL;
if (is_x_pass) {
- length = col;
+ length = col;
values = _cairo_malloc_ab (length + 2, sizeof (xcb_render_fixed_t));
if (values == NULL)
return NULL;
- v = col;
- values[0] = _cairo_fixed_16_16_from_double (v);
- values[1] = _cairo_fixed_16_16_from_double (1.0);
+ v = col;
+ values[0] = _cairo_fixed_16_16_from_double (v);
+ values[1] = _cairo_fixed_16_16_from_double (1.0);
coef = _cairo_malloc_ab (length, sizeof (double));
if (coef == NULL) {
free (values);
return NULL;
}
memset (coef, 0, sizeof (double) * length);
- compute_x_coef_to_double (convolution_matrix, row, col, coef);
+ compute_x_coef_to_double (convolution_matrix, row, col, coef);
}
else {
- length = row;
+ length = row;
values = _cairo_malloc_ab (length + 2, sizeof (xcb_render_fixed_t));
if (values == NULL)
return NULL;
- values[0] = _cairo_fixed_16_16_from_double (1.0);
- v = row;
- values[1] = _cairo_fixed_16_16_from_double (v);
+ values[0] = _cairo_fixed_16_16_from_double (1.0);
+ v = row;
+ values[1] = _cairo_fixed_16_16_from_double (v);
coef = _cairo_malloc_ab (length, sizeof (double));
if (coef == NULL) {
free (values);
return NULL;
}
memset (coef, 0, sizeof (double) * length);
- compute_y_coef_to_double (convolution_matrix, row, col, coef);
+ compute_y_coef_to_double (convolution_matrix, row, col, coef);
}
for (i = 0; i < length; i++)
@@ -5102,7 +5116,7 @@ _cairo_xcb_gaussian_filter (cairo_xcb_surface_t *source,
pixmap,
xrender_format,
0, 0);
- _cairo_xcb_connection_free_pixmap (source->connection, pixmap);
+ _cairo_xcb_connection_free_pixmap (source->connection, pixmap);
}
if (width != src_width || height != src_height) {
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 7b74027d1..41e16f0db 100755..100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -383,13 +383,10 @@ _get_image (cairo_xcb_surface_t *surface,
}
}
- status = _cairo_xcb_connection_get_image (connection,
- surface->drawable,
- x, y,
- width, height,
- &reply);
- if (unlikely (status))
- goto FAIL;
+ reply =_cairo_xcb_connection_get_image (connection,
+ surface->drawable,
+ x, y,
+ width, height);
if (reply == NULL && ! surface->owns_pixmap) {
/* xcb_get_image_t from a window is dangerous because it can
@@ -423,15 +420,11 @@ _get_image (cairo_xcb_surface_t *surface,
_cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
- status = _cairo_xcb_connection_get_image (connection,
- pixmap,
- 0, 0,
- width, height,
- &reply);
+ reply = _cairo_xcb_connection_get_image (connection,
+ pixmap,
+ 0, 0,
+ width, height);
_cairo_xcb_connection_free_pixmap (connection, pixmap);
-
- if (unlikely (status))
- goto FAIL;
}
if (unlikely (reply == NULL)) {
@@ -543,9 +536,9 @@ static void
_cairo_xcb_surface_get_font_options (void *abstract_surface,
cairo_font_options_t *options)
{
- /* XXX copy from xlib */
- _cairo_font_options_init_default (options);
- _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
+ cairo_xcb_surface_t *surface = abstract_surface;
+
+ *options = *_cairo_xcb_screen_get_font_options (surface->screen);
}
static cairo_status_t
@@ -1163,8 +1156,8 @@ _cairo_xcb_surface_glyphs (void *abstract_surface,
if (shadow_type != CAIRO_SHADOW_INSET)
status = _cairo_surface_shadow_glyphs (surface, op, source,
- scaled_font,
- glyphs, num_glyphs,
+ scaled_font,
+ glyphs, num_glyphs,
clip,
&source->shadow);
if (unlikely (status)) {
@@ -1190,8 +1183,8 @@ _cairo_xcb_surface_glyphs (void *abstract_surface,
if (shadow_type == CAIRO_SHADOW_INSET)
status = _cairo_surface_shadow_glyphs (surface, op, source,
- scaled_font,
- glyphs, num_glyphs,
+ scaled_font,
+ glyphs, num_glyphs,
clip,
&source->shadow);
cairo_device_release (surface->device);
@@ -1604,7 +1597,7 @@ cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface,
}
- if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
+ if ( !_cairo_surface_is_xcb(abstract_surface)) {
_cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
return;
@@ -1658,7 +1651,7 @@ cairo_xcb_surface_set_drawable (cairo_surface_t *abstract_surface,
}
- if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
+ if ( !_cairo_surface_is_xcb(abstract_surface)) {
_cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
return;
diff --git a/src/cairo-xcb.h b/src/cairo-xcb.h
index e321d8482..e321d8482 100755..100644
--- a/src/cairo-xcb.h
+++ b/src/cairo-xcb.h
diff --git a/src/cairo-xlib-core-compositor.c b/src/cairo-xlib-core-compositor.c
index 9398079b4..5babcc81b 100755..100644
--- a/src/cairo-xlib-core-compositor.c
+++ b/src/cairo-xlib-core-compositor.c
@@ -292,9 +292,7 @@ render_boxes (cairo_xlib_surface_t *dst,
const cairo_pattern_t *pattern,
cairo_boxes_t *boxes)
{
- double pad;
-
- if (_cairo_pattern_analyze_filter (pattern, &pad) != CAIRO_FILTER_NEAREST)
+ if (pattern->filter != CAIRO_FILTER_NEAREST)
return fallback_boxes (dst, pattern, boxes);
switch (pattern->extend) {
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index cc82b3a99..88efe9c0e 100755..100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -292,7 +292,7 @@ _cairo_xlib_device_create (Display *dpy)
*
* 1. The original bug that led to the buggy_repeat
* workaround. This was a bug that Owen Taylor investigated,
- * understood well, and characterized against carious X
+ * understood well, and characterized against various X
* servers. Confirmed X servers with this bug include:
*
* "XFree86" <= 40500000
@@ -484,7 +484,7 @@ _cairo_xlib_display_get_xrender_format_for_pixman(cairo_xlib_display_t *display,
#undef MASK
/* XXX caching? */
- return XRenderFindFormat(dpy, mask, &tmpl, 1);
+ return XRenderFindFormat(dpy, mask, &tmpl, 0);
}
XRenderPictFormat *
@@ -493,12 +493,6 @@ _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display,
{
XRenderPictFormat *xrender_format;
-#if ! ATOMIC_OP_NEEDS_MEMORY_BARRIER
- xrender_format = display->cached_xrender_formats[format];
- if (likely (xrender_format != NULL))
- return xrender_format;
-#endif
-
xrender_format = display->cached_xrender_formats[format];
if (xrender_format == NULL) {
int pict_format = PictStandardNUM;
@@ -576,7 +570,7 @@ _cairo_xlib_display_has_gradients (cairo_device_t *device)
*
* Restricts all future Xlib surfaces for this devices to the specified version
* of the RENDER extension. This function exists solely for debugging purpose.
- * It let's you find out how cairo would behave with an older version of
+ * It lets you find out how cairo would behave with an older version of
* the RENDER extension.
*
* Use the special values -1 and -1 for disabling the RENDER extension.
diff --git a/src/cairo-xlib-fallback-compositor.c b/src/cairo-xlib-fallback-compositor.c
index ed2845db5..ed2845db5 100755..100644
--- a/src/cairo-xlib-fallback-compositor.c
+++ b/src/cairo-xlib-fallback-compositor.c
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index 4fd725f93..0f2f2e1fa 100755..100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -37,8 +37,8 @@
#ifndef CAIRO_XLIB_PRIVATE_H
#define CAIRO_XLIB_PRIVATE_H
-#include "cairo-xlib.h"
#include "cairo-xlib-xrender-private.h"
+#include "cairo-xlib.h"
#include "cairo-compiler-private.h"
#include "cairo-device-private.h"
@@ -81,7 +81,7 @@ struct _cairo_xlib_display {
int render_major;
int render_minor;
- XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_RGB16_565 + 1];
+ XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_RGB30 + 1];
int force_precision;
@@ -373,6 +373,8 @@ _cairo_xlib_font_close (cairo_xlib_font_t *font);
#define CAIRO_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_RENDER_AT_LEAST((surface), 0, 6)
#define CAIRO_RENDER_HAS_FILTERS(surface) CAIRO_RENDER_AT_LEAST((surface), 0, 6)
+#define CAIRO_RENDER_HAS_FILTER_GOOD(surface) FALSE
+#define CAIRO_RENDER_HAS_FILTER_BEST(surface) FALSE
#define CAIRO_RENDER_HAS_EXTENDED_REPEAT(surface) CAIRO_RENDER_AT_LEAST((surface), 0, 10)
#define CAIRO_RENDER_HAS_GRADIENTS(surface) CAIRO_RENDER_AT_LEAST((surface), 0, 10)
diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c
index 05cde708b..82ed26af7 100755..100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -51,6 +51,7 @@
#include "cairo-image-surface-private.h"
#include "cairo-list-inline.h"
#include "cairo-pattern-private.h"
+#include "cairo-pixman-private.h"
#include "cairo-traps-private.h"
#include "cairo-tristrip-private.h"
@@ -99,7 +100,7 @@ set_clip_region (void *_surface,
_cairo_xlib_surface_ensure_picture (surface);
if (region != NULL) {
- XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (sizeof (XRectangle))];
+ XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)];
XRectangle *rects = stack_rects;
int n_rects, i;
@@ -1295,6 +1296,9 @@ _cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display,
unsigned char *d;
unsigned char *new, *n;
+ if (c == 0)
+ break;
+
new = malloc (c);
if (!new) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -1320,6 +1324,9 @@ _cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display,
const uint32_t *d;
uint32_t *new, *n;
+ if (c == 0)
+ break;
+
new = malloc (4 * c);
if (unlikely (new == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -1478,14 +1485,14 @@ _emit_glyphs_chunk (cairo_xlib_display_t *display,
*/
if (_start_new_glyph_elt (j, &glyphs[i])) {
if (j) {
- elts[nelt].nchars = n;
- nelt++;
- n = 0;
+ elts[nelt].nchars = n;
+ nelt++;
+ n = 0;
}
elts[nelt].chars = char8 + size * j;
elts[nelt].glyphset = info->glyphset;
- elts[nelt].xOff = glyphs[i].i.x - dst_x;
- elts[nelt].yOff = glyphs[i].i.y - dst_y;
+ elts[nelt].xOff = glyphs[i].i.x;
+ elts[nelt].yOff = glyphs[i].i.y;
}
switch (width) {
@@ -1588,7 +1595,7 @@ composite_glyphs (void *surface,
cairo_xlib_display_t *display = dst->display;
cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
cairo_scaled_glyph_t *glyph;
- cairo_fixed_t x = 0, y = 0;
+ cairo_fixed_t x = dst_x, y = dst_y;
cairo_xlib_font_glyphset_t *glyphset = NULL, *this_glyphset_info;
unsigned long max_index = 0;
@@ -1606,11 +1613,6 @@ composite_glyphs (void *surface,
op = _render_operator (op),
_cairo_xlib_surface_ensure_picture (dst);
-
-#if CAIRO_HAS_TG_SURFACE
- _cairo_scaled_font_freeze_cache(info->font);
-#endif
-
for (i = 0; i < num_glyphs; i++) {
int this_x, this_y;
int old_width;
@@ -1620,7 +1622,7 @@ composite_glyphs (void *surface,
CAIRO_SCALED_GLYPH_INFO_METRICS,
&glyph);
if (unlikely (status))
- goto done;
+ return status;
this_x = _cairo_lround (glyphs[i].d.x);
this_y = _cairo_lround (glyphs[i].d.y);
@@ -1629,7 +1631,7 @@ composite_glyphs (void *surface,
if (glyph->dev_private_key != display) {
status = _cairo_xlib_surface_add_glyph (display, info->font, &glyph);
if (unlikely (status))
- goto done;
+ return status;
}
this_glyphset_info = glyph->dev_private;
@@ -1681,7 +1683,7 @@ composite_glyphs (void *surface,
op, src, src_x, src_y,
num_elts, old_width, glyphset);
if (unlikely (status))
- goto done;
+ return status;
glyphs += i;
num_glyphs -= i;
@@ -1726,11 +1728,6 @@ composite_glyphs (void *surface,
num_elts, width, glyphset);
}
-done:
-#if CAIRO_HAS_TG_SURFACE
- _cairo_scaled_font_thaw_cache(info->font);
-#endif
-
return status;
}
@@ -2001,7 +1998,7 @@ _cairo_xlib_traps_compositor_get (void)
compositor.check_composite = check_composite;
compositor.composite = composite;
compositor.lerp = lerp;
- //FIXME:
+ // FIXME:
compositor.lerp_color_glyph = lerp;
//compositor.check_composite_boxes = check_composite_boxes;
compositor.composite_boxes = composite_boxes;
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 119603e9a..119603e9a 100755..100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
diff --git a/src/cairo-xlib-source.c b/src/cairo-xlib-source.c
index 4e9babd79..d5752ba99 100755..100644
--- a/src/cairo-xlib-source.c
+++ b/src/cairo-xlib-source.c
@@ -288,13 +288,14 @@ render_pattern (cairo_xlib_surface_t *dst,
cairo_rectangle_int_t map_extents;
src = (cairo_xlib_surface_t *)
- _cairo_surface_create_similar_scratch (&dst->base,
- is_mask ? CAIRO_CONTENT_ALPHA : CAIRO_CONTENT_COLOR_ALPHA,
- extents->width,
- extents->height);
+ _cairo_surface_create_scratch (&dst->base,
+ is_mask ? CAIRO_CONTENT_ALPHA : CAIRO_CONTENT_COLOR_ALPHA,
+ extents->width,
+ extents->height,
+ NULL);
if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
cairo_surface_destroy (&src->base);
- return None;
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
map_extents = *extents;
@@ -750,10 +751,11 @@ subsurface_source (cairo_xlib_surface_t *dst,
source = &src->embedded_source;
} else {
src = (cairo_xlib_surface_t *)
- _cairo_surface_create_similar_scratch (&dst->base,
- sub->base.content,
- sub->extents.width,
- sub->extents.height);
+ _cairo_surface_create_scratch (&dst->base,
+ sub->base.content,
+ sub->extents.width,
+ sub->extents.height,
+ NULL);
if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
cairo_surface_destroy (&src->base);
return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
@@ -867,11 +869,14 @@ recording_pattern_get_surface (const cairo_pattern_t *pattern)
cairo_surface_t *surface;
surface = ((const cairo_surface_pattern_t *) pattern)->surface;
+
if (_cairo_surface_is_paginated (surface))
- surface = _cairo_paginated_surface_get_recording (surface);
+ return cairo_surface_reference (_cairo_paginated_surface_get_recording (surface));
+
if (_cairo_surface_is_snapshot (surface))
- surface = _cairo_surface_snapshot_get_target (surface);
- return surface;
+ return _cairo_surface_snapshot_get_target (surface);
+
+ return cairo_surface_reference (surface);
}
static cairo_surface_t *
@@ -883,6 +888,7 @@ record_source (cairo_xlib_surface_t *dst,
int *src_x, int *src_y)
{
cairo_xlib_surface_t *src;
+ cairo_surface_t *recording;
cairo_matrix_t matrix, m;
cairo_status_t status;
cairo_rectangle_int_t upload, limit;
@@ -898,19 +904,22 @@ record_source (cairo_xlib_surface_t *dst,
}
src = (cairo_xlib_surface_t *)
- _cairo_surface_create_similar_scratch (&dst->base,
- pattern->surface->content,
- upload.width,
- upload.height);
+ _cairo_surface_create_scratch (&dst->base,
+ pattern->surface->content,
+ upload.width,
+ upload.height,
+ NULL);
if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
cairo_surface_destroy (&src->base);
return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
}
cairo_matrix_init_translate (&matrix, upload.x, upload.y);
- status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (&pattern->base),
+ recording = recording_pattern_get_surface (&pattern->base),
+ status = _cairo_recording_surface_replay_with_clip (recording,
&matrix, &src->base,
NULL);
+ cairo_surface_destroy (recording);
if (unlikely (status)) {
cairo_surface_destroy (&src->base);
return _cairo_surface_create_in_error (status);
@@ -993,6 +1002,9 @@ surface_source (cairo_xlib_surface_t *dst,
if (pattern->base.extend == CAIRO_EXTEND_NONE) {
if (! _cairo_rectangle_intersect (&upload, &limit))
return alpha_source (dst, 0);
+ } else if (pattern->base.extend == CAIRO_EXTEND_PAD) {
+ if (! _cairo_rectangle_intersect (&upload, &limit))
+ upload = limit;
} else {
if (upload.x < limit.x ||
upload.x + upload.width > limit.x + limit.width ||
@@ -1005,14 +1017,15 @@ surface_source (cairo_xlib_surface_t *dst,
}
xsrc = (cairo_xlib_surface_t *)
- _cairo_surface_create_similar_scratch (&dst->base,
- src->content,
- upload.width,
- upload.height);
+ _cairo_surface_create_scratch (&dst->base,
+ src->content,
+ upload.width,
+ upload.height,
+ NULL);
if (xsrc->base.type != CAIRO_SURFACE_TYPE_XLIB) {
cairo_surface_destroy (src);
cairo_surface_destroy (&xsrc->base);
- return None;
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
}
if (_cairo_surface_is_image (src)) {
@@ -1093,17 +1106,22 @@ pattern_is_supported (cairo_xlib_display_t *display,
return FALSE;
}
- if (! CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display)) {
- if (!_cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL))
- return FALSE;
- }
-
- if (! CAIRO_RENDER_HAS_FILTERS (display)) {
- /* No filters implies no transforms, so we optimise away BILINEAR */
+ switch (pattern->filter) {
+ case CAIRO_FILTER_FAST:
+ case CAIRO_FILTER_NEAREST:
+ return CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display) ||
+ _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL);
+ case CAIRO_FILTER_GOOD:
+ return CAIRO_RENDER_HAS_FILTER_GOOD (display);
+ case CAIRO_FILTER_BEST:
+ return CAIRO_RENDER_HAS_FILTER_BEST (display);
+ case CAIRO_FILTER_BILINEAR:
+ case CAIRO_FILTER_GAUSSIAN:
+ default:
+ return CAIRO_RENDER_HAS_FILTERS (display);
}
-
- return TRUE;
}
+
cairo_surface_t *
_cairo_xlib_source_create_for_pattern (cairo_surface_t *_dst,
const cairo_pattern_t *pattern,
diff --git a/src/cairo-xlib-surface-private.h b/src/cairo-xlib-surface-private.h
index 87db6962b..83d9b63cc 100755..100644
--- a/src/cairo-xlib-surface-private.h
+++ b/src/cairo-xlib-surface-private.h
@@ -33,9 +33,9 @@
#ifndef CAIRO_XLIB_SURFACE_PRIVATE_H
#define CAIRO_XLIB_SURFACE_PRIVATE_H
+#include "cairo-xlib-xrender-private.h"
#include "cairo-xlib.h"
#include "cairo-xlib-private.h"
-#include "cairo-xlib-xrender-private.h"
#include "cairo-surface-private.h"
#include "cairo-surface-backend-private.h"
diff --git a/src/cairo-xlib-surface-shm.c b/src/cairo-xlib-surface-shm.c
index fa7d3eb9b..9b4dea5e5 100755..100644
--- a/src/cairo-xlib-surface-shm.c
+++ b/src/cairo-xlib-surface-shm.c
@@ -453,7 +453,7 @@ static void send_event(cairo_xlib_display_t *display,
display->shm->last_event = ev.serial;
}
-static void sync (cairo_xlib_display_t *display)
+static void _cairo_xlib_display_sync (cairo_xlib_display_t *display)
{
cairo_xlib_shm_info_t *info;
struct pqueue *pq = &display->shm->info;
@@ -670,6 +670,7 @@ _cairo_xlib_shm_surface_flush (void *abstract_surface, unsigned flags)
cairo_xlib_shm_surface_t *shm = abstract_surface;
cairo_xlib_display_t *display;
Display *dpy;
+ _XQEvent *qev;
cairo_status_t status;
if (shm->active == 0)
@@ -694,6 +695,10 @@ _cairo_xlib_shm_surface_flush (void *abstract_surface, unsigned flags)
while (! seqno_passed (shm->active, LastKnownRequestProcessed (dpy))) {
LockDisplay(dpy);
_XReadEvents(dpy);
+ while (dpy->head) {
+ qev = dpy->head;
+ _XDeq (dpy, NULL, qev);
+ }
UnlockDisplay(dpy);
}
@@ -893,7 +898,7 @@ _cairo_xlib_surface_update_shm (cairo_xlib_surface_t *surface)
}
if (damage->region) {
- XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (sizeof (XRectangle))];
+ XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)];
XRectangle *rects = stack_rects;
cairo_rectangle_int_t r;
int n_rects, i;
@@ -949,7 +954,7 @@ _cairo_xlib_surface_update_shm (cairo_xlib_surface_t *surface)
XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
}
- sync (display);
+ _cairo_xlib_display_sync (display);
shm->active = 0;
shm->idle--;
@@ -1081,7 +1086,7 @@ _cairo_xlib_surface_put_shm (cairo_xlib_surface_t *surface)
TRACE ((stderr, "%s: flushing damage x %d\n", __FUNCTION__,
damage->region ? cairo_region_num_rectangles (damage->region) : 0));
if (damage->status == CAIRO_STATUS_SUCCESS && damage->region) {
- XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (sizeof (XRectangle))];
+ XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)];
XRectangle *rects = stack_rects;
cairo_rectangle_int_t r;
int n_rects, i;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 2fb29e3d4..8128ebc05 100755..100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -60,6 +60,7 @@
#include "cairo-image-surface-private.h"
#include "cairo-list-inline.h"
#include "cairo-pattern-private.h"
+#include "cairo-pixman-private.h"
#include "cairo-region-private.h"
#include "cairo-scaled-font-private.h"
#include "cairo-surface-snapshot-private.h"
@@ -385,14 +386,14 @@ _cairo_xlib_surface_finish (void *abstract_surface)
cairo_status_t status;
cairo_xlib_display_t *display;
- X_DEBUG ((display->display, "finish (drawable=%x)", (unsigned int) surface->drawable));
-
cairo_list_del (&surface->link);
status = _cairo_xlib_display_acquire (surface->base.device, &display);
if (unlikely (status))
return status;
+ X_DEBUG ((display->display, "finish (drawable=%x)", (unsigned int) surface->drawable));
+
if (surface->embedded_source.picture)
XRenderFreePicture (display->display, surface->embedded_source.picture);
if (surface->picture)
diff --git a/src/cairo-xlib-visual.c b/src/cairo-xlib-visual.c
index d9aac44ca..863822eeb 100755..100644
--- a/src/cairo-xlib-visual.c
+++ b/src/cairo-xlib-visual.c
@@ -40,6 +40,7 @@
#include "cairo-xlib-private.h"
#include "cairo-error-private.h"
+#include "cairo-list-inline.h"
/* A perceptual distance metric between two colors. No sqrt needed
* since the square of the distance is still a valid metric. */
@@ -85,6 +86,7 @@ _cairo_xlib_visual_info_create (Display *dpy,
if (unlikely (info == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ cairo_list_init (&info->link);
info->visualid = visualid;
/* Allocate a gray ramp and a color cube.
@@ -185,6 +187,7 @@ void
_cairo_xlib_visual_info_destroy (cairo_xlib_visual_info_t *info)
{
/* No need for XFreeColors() whilst using DefaultColormap */
+ _cairo_list_del (&info->link);
free (info);
}
diff --git a/src/cairo-xlib-xcb-surface.c b/src/cairo-xlib-xcb-surface.c
index 9c0d4b413..af3e15578 100755..100644
--- a/src/cairo-xlib-xcb-surface.c
+++ b/src/cairo-xlib-xcb-surface.c
@@ -519,21 +519,6 @@ cairo_xlib_surface_create (Display *dpy,
width, height));
}
-cairo_surface_t *
-cairo_xlib_surface_create_for_bitmap (Display *dpy,
- Pixmap bitmap,
- Screen *scr,
- int width,
- int height)
-{
- return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, NULL,
- cairo_xcb_surface_create_for_bitmap (XGetXCBConnection (dpy),
- (xcb_screen_t *) scr,
- bitmap,
- width, height));
-}
-
-#if CAIRO_HAS_XLIB_XRENDER_SURFACE
static xcb_screen_t *
_cairo_xcb_screen_from_root (xcb_connection_t *connection,
xcb_window_t id)
@@ -548,6 +533,24 @@ _cairo_xcb_screen_from_root (xcb_connection_t *connection,
return NULL;
}
+
+cairo_surface_t *
+cairo_xlib_surface_create_for_bitmap (Display *dpy,
+ Pixmap bitmap,
+ Screen *scr,
+ int width,
+ int height)
+{
+ xcb_connection_t *connection = XGetXCBConnection (dpy);
+ xcb_screen_t *screen = _cairo_xcb_screen_from_root (connection, (xcb_window_t) scr->root);
+ return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, NULL,
+ cairo_xcb_surface_create_for_bitmap (connection,
+ screen,
+ bitmap,
+ width, height));
+}
+
+#if CAIRO_HAS_XLIB_XRENDER_SURFACE
cairo_surface_t *
cairo_xlib_surface_create_with_xrender_format (Display *dpy,
Drawable drawable,
diff --git a/src/cairo-xlib-xrender-private.h b/src/cairo-xlib-xrender-private.h
index bf3199c4c..90769467b 100755..100644
--- a/src/cairo-xlib-xrender-private.h
+++ b/src/cairo-xlib-xrender-private.h
@@ -96,6 +96,10 @@ __attribute__((__unused__)) static void _void_consume_free (Display *p, XID
#define PictOpBlendMaximum 0x3e
#endif
+#if !HAVE_XRENDERCREATESOLIDFILL
+#define XRenderCreateSolidFill _int_consume
+#endif
+
#if !HAVE_XRENDERCREATELINEARGRADIENT
#define XRenderCreateLinearGradient _int_consume
diff --git a/src/cairo-xlib-xrender.h b/src/cairo-xlib-xrender.h
index b34b057de..b34b057de 100755..100644
--- a/src/cairo-xlib-xrender.h
+++ b/src/cairo-xlib-xrender.h
diff --git a/src/cairo-xlib.h b/src/cairo-xlib.h
index ecf8d6c86..ecf8d6c86 100755..100644
--- a/src/cairo-xlib.h
+++ b/src/cairo-xlib.h
diff --git a/src/cairo-xml-surface.c b/src/cairo-xml-surface.c
index 777d47089..6dbafdba2 100755..100644
--- a/src/cairo-xml-surface.c
+++ b/src/cairo-xml-surface.c
@@ -459,19 +459,79 @@ to_xml (cairo_xml_surface_t *surface)
}
static cairo_status_t
+_cairo_xml_surface_emit_clip_boxes (cairo_xml_surface_t *surface,
+ const cairo_clip_t *clip)
+{
+ cairo_box_t *box;
+ cairo_xml_t *xml;
+ int n;
+
+ if (clip->num_boxes == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ /* skip the trivial clip covering the surface extents */
+ if (surface->width >= 0 && surface->height >= 0 && clip->num_boxes == 1) {
+ box = &clip->boxes[0];
+ if (box->p1.x <= 0 && box->p1.y <= 0 &&
+ box->p2.x - box->p1.x >= _cairo_fixed_from_double (surface->width) &&
+ box->p2.y - box->p1.y >= _cairo_fixed_from_double (surface->height))
+ {
+ return CAIRO_STATUS_SUCCESS;
+ }
+ }
+
+ xml = to_xml (surface);
+
+ _cairo_xml_printf (xml, "<clip>");
+ _cairo_xml_indent (xml, 2);
+
+ _cairo_xml_printf (xml, "<path>");
+ _cairo_xml_indent (xml, 2);
+ for (n = 0; n < clip->num_boxes; n++) {
+ box = &clip->boxes[n];
+
+ _cairo_xml_printf_start (xml, "%f %f m",
+ _cairo_fixed_to_double (box->p1.x),
+ _cairo_fixed_to_double (box->p1.y));
+ _cairo_xml_printf_continue (xml, " %f %f l",
+ _cairo_fixed_to_double (box->p2.x),
+ _cairo_fixed_to_double (box->p1.y));
+ _cairo_xml_printf_continue (xml, " %f %f l",
+ _cairo_fixed_to_double (box->p2.x),
+ _cairo_fixed_to_double (box->p2.y));
+ _cairo_xml_printf_continue (xml, " %f %f l",
+ _cairo_fixed_to_double (box->p1.x),
+ _cairo_fixed_to_double (box->p2.y));
+ _cairo_xml_printf_end (xml, " h");
+ }
+ _cairo_xml_indent (xml, -2);
+ _cairo_xml_printf (xml, "</path>");
+ _cairo_xml_emit_double (xml, "tolerance", 1.0);
+ _cairo_xml_emit_string (xml, "antialias",
+ _antialias_to_string (CAIRO_ANTIALIAS_NONE));
+ _cairo_xml_emit_string (xml, "fill-rule",
+ _fill_rule_to_string (CAIRO_FILL_RULE_WINDING));
+
+ _cairo_xml_indent (xml, -2);
+ _cairo_xml_printf (xml, "</clip>");
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
_cairo_xml_surface_emit_clip_path (cairo_xml_surface_t *surface,
- cairo_clip_path_t *clip_path)
+ const cairo_clip_path_t *clip_path)
{
cairo_box_t box;
cairo_status_t status;
cairo_xml_t *xml;
- if (clip_path->prev != NULL) {
- status = _cairo_xml_surface_emit_clip_path (surface, clip_path->prev);
- if (unlikely (status))
- return status;
- }
+ if (clip_path == NULL)
+ return CAIRO_STATUS_SUCCESS;
+ status = _cairo_xml_surface_emit_clip_path (surface, clip_path->prev);
+ if (unlikely (status))
+ return status;
/* skip the trivial clip covering the surface extents */
if (surface->width >= 0 && surface->height >= 0 &&
@@ -507,9 +567,15 @@ static cairo_status_t
_cairo_xml_surface_emit_clip (cairo_xml_surface_t *surface,
const cairo_clip_t *clip)
{
+ cairo_status_t status;
+
if (clip == NULL)
return CAIRO_STATUS_SUCCESS;
+ status = _cairo_xml_surface_emit_clip_boxes (surface, clip);
+ if (unlikely (status))
+ return status;
+
return _cairo_xml_surface_emit_clip_path (surface, clip->path);
}
diff --git a/src/cairo-xml.h b/src/cairo-xml.h
index 9ae76e90a..9ae76e90a 100755..100644
--- a/src/cairo-xml.h
+++ b/src/cairo-xml.h
diff --git a/src/cairo.c b/src/cairo.c
index 3a6607b1b..983f02cea 100755..100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -152,7 +152,9 @@ static const cairo_t _cairo_nil[] = {
DEFINE_NIL_CONTEXT (CAIRO_STATUS_DEVICE_TYPE_MISMATCH),
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_DEVICE_FINISHED),
+ DEFINE_NIL_CONTEXT (CAIRO_STATUS_JBIG2_GLOBAL_MISSING)
+
};
COMPILE_TIME_ASSERT (ARRAY_LENGTH (_cairo_nil) == CAIRO_STATUS_LAST_STATUS - 1);
@@ -228,6 +230,8 @@ cairo_create (cairo_surface_t *target)
return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
if (unlikely (target->status))
return _cairo_create_in_error (target->status);
+ if (unlikely (target->finished))
+ return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
if (target->backend->create_context == NULL)
return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
@@ -1635,7 +1639,6 @@ cairo_arc (cairo_t *cr,
angle2 += 2 * M_PI;
angle2 += angle1;
}
-
status = cr->backend->arc (cr, xc, yc, radius, angle1, angle2, TRUE);
if (unlikely (status))
_cairo_set_error (cr, status);
@@ -1868,6 +1871,53 @@ cairo_rectangle (cairo_t *cr,
_cairo_set_error (cr, status);
}
+/**
+ * cairo_rounded_rectangle:
+ * @cr: a cairo context
+ * @x: the X coordinate of the top left corner of the rectangle
+ * @y: the Y coordinate to the top left corner of the rectangle
+ * @width: the width of the rectangle
+ * @height: the height of the rectangle
+ * @r_top_left: top left corner radius
+ * @r_top_right: top right corner radius
+ * @r_bottom_left: bottom left corner radius
+ * @r_bottom_left: top left corner radius
+ *
+ * Adds a closed sub-path roundedrectangle of the given size to the current
+ * path at position (@x, @y) in user-space coordinates.
+ *
+ * This function is logically equivalent to:
+ * <informalexample><programlisting>
+ * cairo_move_to (cr, x, y + r_top_left)
+ * cairo_rel_curve_to (cr, ....)
+ * cairo_rel_line_to (cr, ....)
+ * cairo_rel_curve_to (cr, ....)
+ * cairo_line_to (cr, ....)
+ * cairo_rel_curve_to (cr, ....)
+ * cairo_close_path (cr)
+ * </programlisting></informalexample>
+ *
+ * Since: 1.12
+ **/
+void
+cairo_rounded_rectangle (cairo_t *cr,
+ double x, double y,
+ double width, double height,
+ double r_top_left, double r_top_right,
+ double r_bottom_left, double r_bottom_right)
+{
+ cairo_status_t status;
+
+ if (unlikely (cr->status))
+ return;
+
+ status = cr->backend->rounded_rectangle (cr, x, y, width, height,
+ r_top_left, r_top_right,
+ r_bottom_left, r_bottom_right);
+ if (unlikely (status))
+ _cairo_set_error (cr, status);
+}
+
#if 0
/* XXX: NYI */
void
diff --git a/src/cairo.h b/src/cairo.h
index 2b03e77ec..c1649dbe5 100755..100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -290,6 +290,8 @@ typedef struct _cairo_user_data_key {
* cairo_mesh_pattern_begin_patch()/cairo_mesh_pattern_end_patch()
* pair (Since 1.12)
* @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_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
@@ -345,6 +347,7 @@ typedef enum _cairo_status {
CAIRO_STATUS_DEVICE_ERROR,
CAIRO_STATUS_INVALID_MESH_CONSTRUCTION,
CAIRO_STATUS_DEVICE_FINISHED,
+ CAIRO_STATUS_JBIG2_GLOBAL_MISSING,
CAIRO_STATUS_LAST_STATUS
} cairo_status_t;
@@ -892,6 +895,13 @@ cairo_rectangle (cairo_t *cr,
double x, double y,
double width, double height);
+cairo_public void
+cairo_rounded_rectangle (cairo_t *cr,
+ double x, double y,
+ double width, double height,
+ double r_top_left, double r_top_right,
+ double r_bottom_left, double r_bottom_right);
+
/* XXX: NYI
cairo_public void
cairo_stroke_to_path (cairo_t *cr);
@@ -1341,7 +1351,7 @@ typedef enum _cairo_hint_metrics {
/**
* cairo_font_color_t:
* @CAIRO_FONT_COLOR_DEFAULT: default color, if the font has color,
- * use font's color, otherwise, use user specified, since 1.12.14
+ * use font's color, otherwise, use user specified, since 1.12.14
* @CAIRO_FONT_COLOR_USER: always uses user's color, since 1.0
*
* When rendering text, specifies whether to use user's color set
@@ -1349,12 +1359,12 @@ typedef enum _cairo_hint_metrics {
*
* Since: 1.4
**/
- typedef enum _cairo_font_color {
- CAIRO_FONT_COLOR_DEFAULT,
- CAIRO_FONT_COLOR_USER
- } cairo_font_color_t;
+typedef enum _cairo_font_color {
+ CAIRO_FONT_COLOR_DEFAULT,
+ CAIRO_FONT_COLOR_USER
+} cairo_font_color_t;
- /**
+/**
* cairo_font_options_t:
*
* An opaque structure holding all options that are used when
@@ -1426,8 +1436,7 @@ cairo_font_options_get_hint_metrics (const cairo_font_options_t *options);
cairo_public void
cairo_font_options_set_font_color (cairo_font_options_t *options,
-cairo_font_color_t font_color);
-
+ cairo_font_color_t font_color);
cairo_public cairo_font_color_t
cairo_font_options_get_font_color (const cairo_font_options_t *options);
@@ -2095,6 +2104,7 @@ typedef struct cairo_path {
cairo_status_t status;
cairo_path_data_t *data;
int num_data;
+ unsigned int is_convex : 1;
} cairo_path_t;
cairo_public cairo_path_t *
@@ -2231,6 +2241,15 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target,
double width,
double height);
+/**
+ * cairo_surface_observer_mode_t:
+ * @CAIRO_SURFACE_OBSERVER_NORMAL: no recording is done
+ * @CAIRO_SURFACE_OBSERVER_RECORD_OPERATIONS: operations are recorded
+ *
+ * Whether operations should be recorded.
+ *
+ * Since: 1.12
+ **/
typedef enum {
CAIRO_SURFACE_OBSERVER_NORMAL = 0,
CAIRO_SURFACE_OBSERVER_RECORD_OPERATIONS = 0x1
@@ -2405,8 +2424,7 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_XML,
CAIRO_SURFACE_TYPE_SKIA,
CAIRO_SURFACE_TYPE_SUBSURFACE,
- CAIRO_SURFACE_TYPE_COGL,
- CAIRO_SURFACE_TYPE_TG,
+ CAIRO_SURFACE_TYPE_COGL
} cairo_surface_type_t;
cairo_public cairo_surface_type_t
@@ -2443,6 +2461,9 @@ cairo_surface_set_user_data (cairo_surface_t *surface,
#define CAIRO_MIME_TYPE_JP2 "image/jp2"
#define CAIRO_MIME_TYPE_URI "text/x-uri"
#define CAIRO_MIME_TYPE_UNIQUE_ID "application/x-cairo.uuid"
+#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"
cairo_public void
cairo_surface_get_mime_data (cairo_surface_t *surface,
@@ -2480,6 +2501,16 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
int height);
cairo_public void
+cairo_surface_set_device_scale (cairo_surface_t *surface,
+ double x_scale,
+ double y_scale);
+
+cairo_public void
+cairo_surface_get_device_scale (cairo_surface_t *surface,
+ double *x_scale,
+ double *y_scale);
+
+cairo_public void
cairo_surface_set_device_offset (cairo_surface_t *surface,
double x_offset,
double y_offset);
@@ -2961,10 +2992,10 @@ cairo_public void
cairo_set_shadow_rgba (cairo_t *cr, double red, double green,
double blue, double alpha);
-cairo_public void
+cairo_public void
cairo_set_shadow_blur (cairo_t *cr, double x_blur, double y_blur);
-cairo_public void
+cairo_public void
cairo_set_draw_shadow_only (cairo_t *cr, cairo_bool_t draw_shadow_only);
cairo_public void
@@ -3090,6 +3121,17 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix,
**/
typedef struct _cairo_region cairo_region_t;
+/**
+ * cairo_region_overlap_t:
+ * @CAIRO_REGION_OVERLAP_IN: The contents are entirely inside the region. (Since 1.10)
+ * @CAIRO_REGION_OVERLAP_OUT: The contents are entirely outside the region. (Since 1.10)
+ * @CAIRO_REGION_OVERLAP_PART: The contents are partially inside and
+ * partially outside the region. (Since 1.10)
+ *
+ * Used as the return value for cairo_region_contains_rectangle().
+ *
+ * Since: 1.10
+ **/
typedef enum _cairo_region_overlap {
CAIRO_REGION_OVERLAP_IN, /* completely inside region */
CAIRO_REGION_OVERLAP_OUT, /* completely outside region */
diff --git a/src/cairo.pc.in b/src/cairo.pc.in
index b361edf18..b361edf18 100755..100644
--- a/src/cairo.pc.in
+++ b/src/cairo.pc.in
diff --git a/src/cairoint.h b/src/cairoint.h
index e4f483a3a..7c73c3d13 100755..100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -229,7 +229,7 @@ be16_to_cpu(uint16_t v)
static inline uint32_t cairo_const
cpu_to_be32(uint32_t v)
{
- return (cpu_to_be16 (v) << 16) | cpu_to_be16 (v >> 16);
+ return (v >> 24) | ((v >> 8) & 0xff00) | ((v << 8) & 0xff0000) | (v << 24);
}
static inline uint32_t cairo_const
@@ -240,6 +240,32 @@ be32_to_cpu(uint32_t v)
#endif
+/* Unaligned big endian access
+ */
+
+static inline uint16_t get_unaligned_be16 (const unsigned char *p)
+{
+ return p[0] << 8 | p[1];
+}
+
+static inline uint32_t get_unaligned_be32 (const unsigned char *p)
+{
+ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+}
+
+static inline void put_unaligned_be16 (uint16_t v, unsigned char *p)
+{
+ p[0] = (v >> 8) & 0xff;
+ p[1] = v & 0xff;
+}
+
+static inline void put_unaligned_be32 (uint32_t v, unsigned char *p)
+{
+ p[0] = (v >> 24) & 0xff;
+ p[1] = (v >> 16) & 0xff;
+ p[2] = (v >> 8) & 0xff;
+ p[3] = v & 0xff;
+}
/* The glibc versions of ispace() and isdigit() are slow in UTF-8 locales.
*/
@@ -428,7 +454,7 @@ _cairo_cogl_context_reset_static_data (void);
/* the font backend interface */
struct _cairo_unscaled_font_backend {
- void (*destroy) (void *unscaled_font);
+ cairo_bool_t (*destroy) (void *unscaled_font);
};
/* #cairo_toy_font_face_t - simple family/slant/weight font faces used for
@@ -587,7 +613,7 @@ struct _cairo_font_face_backend {
/* The destroy() function is allowed to resurrect the font face
* by re-referencing. This is needed for the FreeType backend.
*/
- void
+ cairo_bool_t
(*destroy) (void *font_face);
cairo_warn cairo_status_t
@@ -797,6 +823,9 @@ cairo_private void
_cairo_font_face_init (cairo_font_face_t *font_face,
const cairo_font_face_backend_t *backend);
+cairo_private cairo_bool_t
+_cairo_font_face_destroy (void *abstract_face);
+
cairo_private cairo_status_t
_cairo_font_face_set_error (cairo_font_face_t *font_face,
cairo_status_t status);
@@ -872,6 +901,9 @@ _cairo_intern_string (const char **str_inout, int len);
cairo_private void
_cairo_intern_string_reset_static_data (void);
+cairo_private const char *
+cairo_get_locale_decimal_point (void);
+
/* cairo-path-fixed.c */
cairo_private cairo_path_fixed_t *
_cairo_path_fixed_create (void);
@@ -1034,6 +1066,9 @@ cairo_private cairo_bool_t
_cairo_path_fixed_is_single_arc (const cairo_path_fixed_t *path);
cairo_private cairo_bool_t
+_cairo_path_fixed_is_empty (const cairo_path_fixed_t *path);
+
+cairo_private cairo_bool_t
_cairo_path_fixed_is_single_line (const cairo_path_fixed_t *path);
cairo_private cairo_bool_t
@@ -1323,20 +1358,21 @@ _cairo_surface_set_resolution (cairo_surface_t *surface,
cairo_private cairo_surface_t *
_cairo_surface_create_similar_scratch (cairo_surface_t *other,
- cairo_content_t content,
- int width,
- int height);
+ cairo_content_t content,
+ int width,
+ int height);
+
cairo_private cairo_surface_t *
_cairo_surface_create_for_rectangle_int (cairo_surface_t *target,
const cairo_rectangle_int_t *extents);
cairo_private cairo_surface_t *
-_cairo_surface_create_similar_solid (cairo_surface_t *other,
- cairo_content_t content,
- int width,
- int height,
- const cairo_color_t *color);
+_cairo_surface_create_scratch (cairo_surface_t *other,
+ cairo_content_t content,
+ int width,
+ int height,
+ const cairo_color_t *color);
cairo_private void
_cairo_surface_init (cairo_surface_t *surface,
@@ -1358,7 +1394,7 @@ cairo_private cairo_image_surface_t *
_cairo_surface_map_to_image (cairo_surface_t *surface,
const cairo_rectangle_int_t *extents);
-cairo_private cairo_int_status_t
+cairo_private_no_warn cairo_int_status_t
_cairo_surface_unmap_image (cairo_surface_t *surface,
cairo_image_surface_t *image);
@@ -1454,11 +1490,6 @@ cairo_private_no_warn cairo_bool_t
_cairo_surface_get_extents (cairo_surface_t *surface,
cairo_rectangle_int_t *extents);
-cairo_private void
-_cairo_surface_set_device_scale (cairo_surface_t *surface,
- double sx,
- double sy);
-
cairo_private cairo_bool_t
_cairo_surface_has_device_transform (cairo_surface_t *surface) cairo_pure;
@@ -1651,18 +1682,18 @@ _cairo_polygon_limit_to_clip (cairo_polygon_t *polygon,
cairo_private void
_cairo_polygon_fini (cairo_polygon_t *polygon);
-cairo_private cairo_status_t
+cairo_private_no_warn cairo_status_t
_cairo_polygon_add_line (cairo_polygon_t *polygon,
const cairo_line_t *line,
int top, int bottom,
int dir);
-cairo_private cairo_status_t
+cairo_private_no_warn cairo_status_t
_cairo_polygon_add_external_edge (void *polygon,
const cairo_point_t *p1,
const cairo_point_t *p2);
-cairo_private cairo_status_t
+cairo_private_no_warn cairo_status_t
_cairo_polygon_add_contour (cairo_polygon_t *polygon,
const cairo_contour_t *contour);
@@ -1990,6 +2021,7 @@ slim_hidden_proto (cairo_surface_destroy);
slim_hidden_proto (cairo_surface_finish);
slim_hidden_proto (cairo_surface_flush);
slim_hidden_proto (cairo_surface_get_device_offset);
+slim_hidden_proto (cairo_surface_get_device_scale);
slim_hidden_proto (cairo_surface_get_font_options);
slim_hidden_proto (cairo_surface_get_mime_data);
slim_hidden_proto (cairo_surface_has_show_text_glyphs);
@@ -1997,6 +2029,7 @@ slim_hidden_proto (cairo_surface_mark_dirty);
slim_hidden_proto (cairo_surface_mark_dirty_rectangle);
slim_hidden_proto_no_warn (cairo_surface_reference);
slim_hidden_proto (cairo_surface_set_device_offset);
+slim_hidden_proto (cairo_surface_set_device_scale);
slim_hidden_proto (cairo_surface_set_fallback_resolution);
slim_hidden_proto (cairo_surface_set_mime_data);
slim_hidden_proto (cairo_surface_show_page);
@@ -2055,10 +2088,6 @@ slim_hidden_proto (cairo_surface_write_to_png_stream);
#endif
-cairo_private_no_warn cairo_filter_t
-_cairo_pattern_analyze_filter (const cairo_pattern_t *pattern,
- double *pad_out);
-
CAIRO_END_DECLS
#include "cairo-mutex-private.h"
diff --git a/src/check-def.sh b/src/check-def.sh
index 9008c5871..beefb46a3 100755
--- a/src/check-def.sh
+++ b/src/check-def.sh
@@ -39,7 +39,7 @@ for def in $defs; do
{
echo EXPORTS
- eval $get_cairo_syms | c++filt --no-params | grep -v '^_cairo_test_\|^_fini\|^_init\|^_save[fg]pr\|^_rest[fg]pr\|^_Z\|^__gnu' | sort -u
+ eval $get_cairo_syms | c++filt --no-params | grep -v '^_cairo_test_\|^_fini\|^_init\|^_save[fg]pr\|^_rest[fg]pr\|^_Z\|^__gnu\|^__bss\|^_edata\|^_end' | sort -u
# cheat: copy the last line from the def file!
tail -n1 "$def"
} | diff "$def" - >&2 || stat=1
diff --git a/src/check-doc-syntax.awk b/src/check-doc-syntax.awk
index 5fdabdac9..1fa8b8d22 100755..100644
--- a/src/check-doc-syntax.awk
+++ b/src/check-doc-syntax.awk
@@ -1,5 +1,3 @@
-#!/usr/bin/awk -f
-
BEGIN {
name_found = 1
SECTION_DOC = 0
diff --git a/src/check-doc-syntax.sh b/src/check-doc-syntax.sh
index c74fb875d..762a48429 100755
--- a/src/check-doc-syntax.sh
+++ b/src/check-doc-syntax.sh
@@ -72,7 +72,7 @@ fi >&2
# Only run the syntax checker on the source files (not doc/)
if test -e ./check-doc-syntax.awk; then
- if echo $FILES | xargs ./check-doc-syntax.awk ; then
+ if echo $FILES | xargs awk -f ./check-doc-syntax.awk ; then
:
else
stat=1
diff --git a/src/check-has-hidden-symbols.c b/src/check-has-hidden-symbols.c
index 120412776..120412776 100755..100644
--- a/src/check-has-hidden-symbols.c
+++ b/src/check-has-hidden-symbols.c
diff --git a/src/check-link.c b/src/check-link.c
index 66ca1b241..66ca1b241 100755..100644
--- a/src/check-link.c
+++ b/src/check-link.c
diff --git a/src/check-preprocessor-syntax.sh b/src/check-preprocessor-syntax.sh
index c4154151d..b718f604e 100755
--- a/src/check-preprocessor-syntax.sh
+++ b/src/check-preprocessor-syntax.sh
@@ -9,10 +9,10 @@ stat=0
HEADERS=$all_cairo_headers
-test "x$HEADERS" = x && HEADERS=`find . -name 'cairo*.h' ! -name 'cairo*-private.h' ! -name 'cairoint.h'`
+test "x$HEADERS" = x && HEADERS=`find . -name 'cairo*.h' ! -name 'cairo*-private.h' ! -name 'cairo*-inline.h' ! -name 'cairoint.h'`
PRIVATE=$all_cairo_private
-test "x$PRIVATE" = x && PRIVATE=`find . -name 'cairo*-private.h' -or -name 'cairoint.h'`
+test "x$PRIVATE" = x && PRIVATE=`find . -name 'cairo*-private.h' -or -name 'cairo*-inline.h' -or -name 'cairoint.h'`
SOURCES=$all_cairo_sources
test "x$SOURCES" = x && SOURCES=`find . -name 'cairo*.c' -or -name 'cairo*.cpp'`
diff --git a/src/drm/cairo-drm-bo.c b/src/drm/cairo-drm-bo.c
index a5b59f2c9..a5b59f2c9 100755..100644
--- a/src/drm/cairo-drm-bo.c
+++ b/src/drm/cairo-drm-bo.c
diff --git a/src/drm/cairo-drm-gallium-surface.c b/src/drm/cairo-drm-gallium-surface.c
index 164ab03ce..164ab03ce 100755..100644
--- a/src/drm/cairo-drm-gallium-surface.c
+++ b/src/drm/cairo-drm-gallium-surface.c
diff --git a/src/drm/cairo-drm-i915-glyphs.c b/src/drm/cairo-drm-i915-glyphs.c
index 9944f15a4..9944f15a4 100755..100644
--- a/src/drm/cairo-drm-i915-glyphs.c
+++ b/src/drm/cairo-drm-i915-glyphs.c
diff --git a/src/drm/cairo-drm-i915-private.h b/src/drm/cairo-drm-i915-private.h
index c750cf4cf..c750cf4cf 100755..100644
--- a/src/drm/cairo-drm-i915-private.h
+++ b/src/drm/cairo-drm-i915-private.h
diff --git a/src/drm/cairo-drm-i915-shader.c b/src/drm/cairo-drm-i915-shader.c
index a1911d0a4..85aa98433 100755..100644
--- a/src/drm/cairo-drm-i915-shader.c
+++ b/src/drm/cairo-drm-i915-shader.c
@@ -1467,42 +1467,6 @@ i915_shader_acquire_solid_surface (i915_shader_t *shader,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_filter_t
-sampled_area (const cairo_surface_pattern_t *pattern,
- const cairo_rectangle_int_t *extents,
- cairo_rectangle_int_t *sample)
-{
- cairo_rectangle_int_t surface_extents;
- cairo_filter_t filter;
- double x1, x2, y1, y2;
- double pad;
-
- x1 = extents->x;
- y1 = extents->y;
- x2 = extents->x + (int) extents->width;
- y2 = extents->y + (int) extents->height;
-
- if (_cairo_matrix_is_translation (&pattern->base.matrix)) {
- x1 += pattern->base.matrix.x0; x2 += pattern->base.matrix.x0;
- y1 += pattern->base.matrix.y0; y2 += pattern->base.matrix.y0;
- } else {
- _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
- &x1, &y1, &x2, &y2,
- NULL);
- }
-
- filter = _cairo_pattern_analyze_filter (&pattern->base, &pad);
- sample->x = floor (x1 - pad);
- sample->y = floor (y1 - pad);
- sample->width = ceil (x2 + pad) - sample->x;
- sample->height = ceil (y2 + pad) - sample->y;
-
- if (_cairo_surface_get_extents (pattern->surface, &surface_extents))
- _cairo_rectangle_intersect (sample, &surface_extents);
-
- return filter;
-}
-
static cairo_status_t
i915_shader_acquire_surface (i915_shader_t *shader,
union i915_shader_channel *src,
@@ -1524,7 +1488,8 @@ i915_shader_acquire_surface (i915_shader_t *shader,
extend = pattern->base.extend;
src->base.matrix = pattern->base.matrix;
- filter = sampled_area (pattern, extents, &sample);
+ filter = pattern->base.filter;
+ _cairo_pattern_sampled_area(&pattern->base, extents, sample);
if (surface->type == CAIRO_SURFACE_TYPE_DRM) {
if (surface->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
diff --git a/src/drm/cairo-drm-i915-spans.c b/src/drm/cairo-drm-i915-spans.c
index b3f4e0afd..b3f4e0afd 100755..100644
--- a/src/drm/cairo-drm-i915-spans.c
+++ b/src/drm/cairo-drm-i915-spans.c
diff --git a/src/drm/cairo-drm-i915-surface.c b/src/drm/cairo-drm-i915-surface.c
index c1a04529f..c1a04529f 100755..100644
--- a/src/drm/cairo-drm-i915-surface.c
+++ b/src/drm/cairo-drm-i915-surface.c
diff --git a/src/drm/cairo-drm-i965-glyphs.c b/src/drm/cairo-drm-i965-glyphs.c
index c66a63d73..c66a63d73 100755..100644
--- a/src/drm/cairo-drm-i965-glyphs.c
+++ b/src/drm/cairo-drm-i965-glyphs.c
diff --git a/src/drm/cairo-drm-i965-private.h b/src/drm/cairo-drm-i965-private.h
index 79568a63d..79568a63d 100755..100644
--- a/src/drm/cairo-drm-i965-private.h
+++ b/src/drm/cairo-drm-i965-private.h
diff --git a/src/drm/cairo-drm-i965-shader.c b/src/drm/cairo-drm-i965-shader.c
index eed5f5f09..eed5f5f09 100755..100644
--- a/src/drm/cairo-drm-i965-shader.c
+++ b/src/drm/cairo-drm-i965-shader.c
diff --git a/src/drm/cairo-drm-i965-spans.c b/src/drm/cairo-drm-i965-spans.c
index 5cba7cec8..5cba7cec8 100755..100644
--- a/src/drm/cairo-drm-i965-spans.c
+++ b/src/drm/cairo-drm-i965-spans.c
diff --git a/src/drm/cairo-drm-i965-surface.c b/src/drm/cairo-drm-i965-surface.c
index ec7b5954c..ec7b5954c 100755..100644
--- a/src/drm/cairo-drm-i965-surface.c
+++ b/src/drm/cairo-drm-i965-surface.c
diff --git a/src/drm/cairo-drm-intel-brw-defines.h b/src/drm/cairo-drm-intel-brw-defines.h
index b2be36f18..b2be36f18 100755..100644
--- a/src/drm/cairo-drm-intel-brw-defines.h
+++ b/src/drm/cairo-drm-intel-brw-defines.h
diff --git a/src/drm/cairo-drm-intel-brw-eu-emit.c b/src/drm/cairo-drm-intel-brw-eu-emit.c
index f27b23804..f27b23804 100755..100644
--- a/src/drm/cairo-drm-intel-brw-eu-emit.c
+++ b/src/drm/cairo-drm-intel-brw-eu-emit.c
diff --git a/src/drm/cairo-drm-intel-brw-eu-util.c b/src/drm/cairo-drm-intel-brw-eu-util.c
index 592235b12..592235b12 100755..100644
--- a/src/drm/cairo-drm-intel-brw-eu-util.c
+++ b/src/drm/cairo-drm-intel-brw-eu-util.c
diff --git a/src/drm/cairo-drm-intel-brw-eu.c b/src/drm/cairo-drm-intel-brw-eu.c
index 2b47d8c37..2b47d8c37 100755..100644
--- a/src/drm/cairo-drm-intel-brw-eu.c
+++ b/src/drm/cairo-drm-intel-brw-eu.c
diff --git a/src/drm/cairo-drm-intel-brw-eu.h b/src/drm/cairo-drm-intel-brw-eu.h
index 2662a2e7f..2662a2e7f 100755..100644
--- a/src/drm/cairo-drm-intel-brw-eu.h
+++ b/src/drm/cairo-drm-intel-brw-eu.h
diff --git a/src/drm/cairo-drm-intel-brw-structs.h b/src/drm/cairo-drm-intel-brw-structs.h
index f42483ed1..f42483ed1 100755..100644
--- a/src/drm/cairo-drm-intel-brw-structs.h
+++ b/src/drm/cairo-drm-intel-brw-structs.h
diff --git a/src/drm/cairo-drm-intel-command-private.h b/src/drm/cairo-drm-intel-command-private.h
index a93ac12ab..a93ac12ab 100755..100644
--- a/src/drm/cairo-drm-intel-command-private.h
+++ b/src/drm/cairo-drm-intel-command-private.h
diff --git a/src/drm/cairo-drm-intel-debug.c b/src/drm/cairo-drm-intel-debug.c
index 7068c933e..7068c933e 100755..100644
--- a/src/drm/cairo-drm-intel-debug.c
+++ b/src/drm/cairo-drm-intel-debug.c
diff --git a/src/drm/cairo-drm-intel-ioctl-private.h b/src/drm/cairo-drm-intel-ioctl-private.h
index 004d3bfd7..004d3bfd7 100755..100644
--- a/src/drm/cairo-drm-intel-ioctl-private.h
+++ b/src/drm/cairo-drm-intel-ioctl-private.h
diff --git a/src/drm/cairo-drm-intel-private.h b/src/drm/cairo-drm-intel-private.h
index 343270a3c..343270a3c 100755..100644
--- a/src/drm/cairo-drm-intel-private.h
+++ b/src/drm/cairo-drm-intel-private.h
diff --git a/src/drm/cairo-drm-intel-surface.c b/src/drm/cairo-drm-intel-surface.c
index 88f5b8f0c..88f5b8f0c 100755..100644
--- a/src/drm/cairo-drm-intel-surface.c
+++ b/src/drm/cairo-drm-intel-surface.c
diff --git a/src/drm/cairo-drm-intel.c b/src/drm/cairo-drm-intel.c
index d45155ebe..d45155ebe 100755..100644
--- a/src/drm/cairo-drm-intel.c
+++ b/src/drm/cairo-drm-intel.c
diff --git a/src/drm/cairo-drm-ioctl-private.h b/src/drm/cairo-drm-ioctl-private.h
index 4294de2d5..4294de2d5 100755..100644
--- a/src/drm/cairo-drm-ioctl-private.h
+++ b/src/drm/cairo-drm-ioctl-private.h
diff --git a/src/drm/cairo-drm-private.h b/src/drm/cairo-drm-private.h
index 2db7f38d6..2db7f38d6 100755..100644
--- a/src/drm/cairo-drm-private.h
+++ b/src/drm/cairo-drm-private.h
diff --git a/src/drm/cairo-drm-radeon-private.h b/src/drm/cairo-drm-radeon-private.h
index 546126c6f..546126c6f 100755..100644
--- a/src/drm/cairo-drm-radeon-private.h
+++ b/src/drm/cairo-drm-radeon-private.h
diff --git a/src/drm/cairo-drm-radeon-surface.c b/src/drm/cairo-drm-radeon-surface.c
index 6dbddaae4..6dbddaae4 100755..100644
--- a/src/drm/cairo-drm-radeon-surface.c
+++ b/src/drm/cairo-drm-radeon-surface.c
diff --git a/src/drm/cairo-drm-radeon.c b/src/drm/cairo-drm-radeon.c
index a6d22089b..a6d22089b 100755..100644
--- a/src/drm/cairo-drm-radeon.c
+++ b/src/drm/cairo-drm-radeon.c
diff --git a/src/drm/cairo-drm-surface.c b/src/drm/cairo-drm-surface.c
index 8c4dd0ee8..8c4dd0ee8 100755..100644
--- a/src/drm/cairo-drm-surface.c
+++ b/src/drm/cairo-drm-surface.c
diff --git a/src/drm/cairo-drm.c b/src/drm/cairo-drm.c
index 051b79e4f..661e181b6 100755..100644
--- a/src/drm/cairo-drm.c
+++ b/src/drm/cairo-drm.c
@@ -202,8 +202,7 @@ cairo_drm_device_get (struct udev_device *device)
parent = udev_device_get_parent (device);
pci_id = get_udev_property (parent, "PCI_ID");
if (pci_id == NULL || sscanf (pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
- dev = (cairo_drm_device_t *)
- _cairo_device_create_in_error (CAIRO_STATUS_DEVICE_ERROR);
+ dev = NULL;
goto DONE;
}
@@ -239,6 +238,7 @@ cairo_drm_device_get (struct udev_device *device)
if (fd == -1) {
/* XXX more likely to be a permissions issue... */
_cairo_error_throw (CAIRO_STATUS_FILE_NOT_FOUND);
+ dev = NULL;
goto DONE;
}
@@ -249,7 +249,10 @@ cairo_drm_device_get (struct udev_device *device)
DONE:
CAIRO_MUTEX_UNLOCK (_cairo_drm_device_mutex);
- return &dev->base;
+ if (dev == NULL)
+ return _cairo_device_create_in_error (CAIRO_STATUS_DEVICE_ERROR);
+ else
+ return &dev->base;
}
slim_hidden_def (cairo_drm_device_get);
diff --git a/src/skia/cairo-skia-context.cpp b/src/skia/cairo-skia-context.cpp
index bbe5507f6..9ffb8f6a2 100755..100644
--- a/src/skia/cairo-skia-context.cpp
+++ b/src/skia/cairo-skia-context.cpp
@@ -53,6 +53,7 @@
#include "cairo-skia-private.h"
#include "cairo-surface-backend-private.h"
+#include <SkPaint.h>
#include <SkShader.h>
#include <SkColorShader.h>
#include <SkGradientShader.h>
@@ -236,16 +237,19 @@ surface_to_sk_bitmap (cairo_surface_t *surface, SkBitmap& bitmap)
{
cairo_image_surface_t *img = (cairo_image_surface_t *) surface;
SkBitmap::Config config;
+ SkColorType colorType;
bool opaque;
if (unlikely (! format_to_sk_config (img->format, config, opaque)))
return false;
bitmap.reset ();
- bitmap.setConfig (config, img->width, img->height, img->stride);
- bitmap.setIsOpaque (opaque);
+ bitmap.setAlphaType (opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+ colorType = SkBitmapConfigToColorType(config);
+ bitmap.setInfo (SkImageInfo::Make(img->width, img->height, colorType, kPremul_SkAlphaType), img->stride);
bitmap.setPixels (img->data);
+
return true;
}
@@ -330,9 +334,18 @@ source_to_sk_shader (cairo_skia_context_t *cr,
if (surface->type == CAIRO_SURFACE_TYPE_SKIA) {
cairo_skia_surface_t *esurf = (cairo_skia_surface_t *) surface;
- shader = SkShader::CreateBitmapShader (*esurf->bitmap,
- extend_to_sk (pattern->extend),
- extend_to_sk (pattern->extend));
+ if (! _cairo_matrix_is_identity (&pattern->matrix))
+ {
+ SkMatrix localMatrix = matrix_inverse_to_sk (pattern->matrix);
+ shader = SkShader::CreateBitmapShader (*esurf->bitmap,
+ extend_to_sk (pattern->extend),
+ extend_to_sk (pattern->extend),
+ &localMatrix);
+ } else {
+ shader = SkShader::CreateBitmapShader (*esurf->bitmap,
+ extend_to_sk (pattern->extend),
+ extend_to_sk (pattern->extend));
+ }
} else {
SkBitmap bitmap;
@@ -351,9 +364,18 @@ source_to_sk_shader (cairo_skia_context_t *cr,
if (unlikely (! surface_to_sk_bitmap (surface, bitmap)))
return NULL;
- shader = SkShader::CreateBitmapShader (bitmap,
- extend_to_sk (pattern->extend),
- extend_to_sk (pattern->extend));
+ if (! _cairo_matrix_is_identity (&pattern->matrix))
+ {
+ SkMatrix localMatrix = matrix_inverse_to_sk (pattern->matrix);
+ shader = SkShader::CreateBitmapShader (bitmap,
+ extend_to_sk (pattern->extend),
+ extend_to_sk (pattern->extend),
+ &localMatrix);
+ } else {
+ shader = SkShader::CreateBitmapShader (bitmap,
+ extend_to_sk (pattern->extend),
+ extend_to_sk (pattern->extend));
+ }
}
} else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR
/* || pattern->type == CAIRO_PATTERN_TYPE_RADIAL */)
@@ -382,8 +404,17 @@ source_to_sk_shader (cairo_skia_context_t *cr,
SkFloatToScalar (linear->pd1.y));
points[1].set (SkFloatToScalar (linear->pd2.x),
SkFloatToScalar (linear->pd2.y));
- shader = SkGradientShader::CreateLinear (points, colors, pos, gradient->n_stops,
- extend_to_sk (pattern->extend));
+
+ if(! _cairo_matrix_is_identity (&pattern->matrix))
+ {
+ SkMatrix localMatrix = matrix_inverse_to_sk (pattern->matrix);
+ shader = SkGradientShader::CreateLinear (points, colors, pos, gradient->n_stops,
+ extend_to_sk (pattern->extend),
+ 0, &localMatrix);
+ } else {
+ shader = SkGradientShader::CreateLinear (points, colors, pos, gradient->n_stops,
+ extend_to_sk (pattern->extend));
+ }
} else {
// XXX todo -- implement real radial shaders in Skia
}
@@ -394,9 +425,6 @@ source_to_sk_shader (cairo_skia_context_t *cr,
}
}
- if (shader && ! _cairo_matrix_is_identity (&pattern->matrix))
- shader->setLocalMatrix (matrix_inverse_to_sk (pattern->matrix));
-
return shader;
}
@@ -446,6 +474,7 @@ _cairo_skia_context_set_source (void *abstract_cr,
cr->paint->setColor (color);
} else {
SkShader *shader = source_to_sk_shader (cr, source);
+ bool fLevel = pattern_filter_to_sk (source);
if (shader == NULL) {
UNSUPPORTED;
return CAIRO_STATUS_SUCCESS;
@@ -454,7 +483,8 @@ _cairo_skia_context_set_source (void *abstract_cr,
cr->paint->setShader (shader);
shader->unref ();
- cr->paint->setFilterBitmap (pattern_filter_to_sk (source));
+ cr->paint->setFilterLevel (fLevel ?
+ (SkPaint::kLow_FilterLevel) : (SkPaint::kNone_FilterLevel));
}
/* XXX change notification */
@@ -496,7 +526,8 @@ _cairo_skia_context_set_source_surface (void *abstract_cr,
cr->paint->setShader (shader);
shader->unref ();
- cr->paint->setFilterBitmap (true);
+ cr->paint->setFilterLevel (true ?
+ (SkPaint::kLow_FilterLevel) : (SkPaint::kNone_FilterLevel));
return CAIRO_STATUS_SUCCESS;
}
@@ -682,7 +713,7 @@ _cairo_skia_context_set_dash (void *abstract_cr,
intervals[i++] = SkFloatToScalar (dashes[j]);
} while (loop--);
- SkDashPathEffect *dash = new SkDashPathEffect (intervals, num_dashes, SkFloatToScalar (offset));
+ SkDashPathEffect *dash = SkDashPathEffect::Create (intervals, num_dashes, SkFloatToScalar (offset));
cr->paint->setPathEffect (dash);
dash->unref ();
@@ -1264,7 +1295,7 @@ _cairo_skia_context_paint_with_alpha (void *abstract_cr,
if (CAIRO_ALPHA_IS_OPAQUE (alpha))
return _cairo_skia_context_paint (cr);
- cr->paint->setAlpha(SkScalarRound(255*alpha));
+ cr->paint->setAlpha(SkScalarRoundToInt(255*alpha));
status = _cairo_skia_context_paint (cr);
cr->paint->setAlpha(255);
diff --git a/src/skia/cairo-skia-private.h b/src/skia/cairo-skia-private.h
index cbd8c888d..f538b486b 100755..100644
--- a/src/skia/cairo-skia-private.h
+++ b/src/skia/cairo-skia-private.h
@@ -44,7 +44,26 @@
#include <SkPaint.h>
#include <SkPath.h>
+/**
+ * cairo_skia_context_t:
+ *
+ * A #cairo_skia_context_t includes handles to Skia's canvas,
+ * paint, and path objects along with the Cairo source surfaces
+ * and matrix, and the original and target #cairo_skia_surface_t
+ * objects.
+ *
+ * Since: 1.10
+ **/
typedef struct _cairo_skia_context cairo_skia_context_t;
+
+/**
+ * cairo_skia_surface_t:
+ *
+ * A #cairo_skia_surface_t is a container for the underlying
+ * #SkBitmap and the corresponding Cairo image surface.
+ *
+ * Since: 1.10
+ **/
typedef struct _cairo_skia_surface cairo_skia_surface_t;
struct _cairo_skia_context {
@@ -92,11 +111,9 @@ format_to_sk_config (cairo_format_t format,
case CAIRO_FORMAT_A8:
config = SkBitmap::kA8_Config;
break;
- case CAIRO_FORMAT_A1:
- config = SkBitmap::kA1_Config;
- break;
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_INVALID:
+ case CAIRO_FORMAT_A1:
default:
return false;
}
diff --git a/src/skia/cairo-skia-surface.cpp b/src/skia/cairo-skia-surface.cpp
index bb785e192..834a2f13b 100755..100644
--- a/src/skia/cairo-skia-surface.cpp
+++ b/src/skia/cairo-skia-surface.cpp
@@ -64,7 +64,7 @@ _cairo_skia_surface_create_similar (void *asurface,
if (content == surface->image.base.content)
{
- config = surface->bitmap->getConfig ();
+ config = surface->bitmap->config ();
opaque = surface->bitmap->isOpaque ();
}
else if (! format_to_sk_config (_cairo_format_from_content (content),
@@ -207,9 +207,6 @@ sk_config_to_pixman_format_code (SkBitmap::Config config,
case SkBitmap::kA8_Config:
return PIXMAN_a8;
-
- case SkBitmap::kA1_Config:
- return PIXMAN_a1;
case SkBitmap::kRGB_565_Config:
return PIXMAN_r5g6b5;
case SkBitmap::kARGB_4444_Config:
@@ -217,8 +214,6 @@ sk_config_to_pixman_format_code (SkBitmap::Config config,
case SkBitmap::kNo_Config:
case SkBitmap::kIndex8_Config:
- case SkBitmap::kRLE_Index8_Config:
- case SkBitmap::kConfigCount:
default:
ASSERT_NOT_REACHED;
return (pixman_format_code_t) -1;
@@ -236,6 +231,7 @@ _cairo_skia_surface_create_internal (SkBitmap::Config config,
cairo_skia_surface_t *surface;
pixman_image_t *pixman_image;
pixman_format_code_t pixman_format;
+ SkColorType colorType;
surface = (cairo_skia_surface_t *) malloc (sizeof (cairo_skia_surface_t));
if (unlikely (surface == NULL))
@@ -245,8 +241,10 @@ _cairo_skia_surface_create_internal (SkBitmap::Config config,
pixman_image = pixman_image_create_bits (pixman_format,
width, height,
(uint32_t *) data, stride);
- if (unlikely (pixman_image == NULL))
+ if (unlikely (pixman_image == NULL)) {
+ free (surface);
return (cairo_skia_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+ }
_cairo_surface_init (&surface->image.base,
&cairo_skia_surface_backend,
@@ -256,8 +254,9 @@ _cairo_skia_surface_create_internal (SkBitmap::Config config,
_cairo_image_surface_init (&surface->image, pixman_image, pixman_format);
surface->bitmap = new SkBitmap;
- surface->bitmap->setConfig (config, width, height, surface->image.stride);
- surface->bitmap->setIsOpaque (opaque);
+ colorType = SkBitmapConfigToColorType(config);
+ surface->bitmap->setAlphaType (opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+ surface->bitmap->setInfo (SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType), surface->image.stride);
surface->bitmap->setPixels (surface->image.data);
surface->image.base.is_clear = data == NULL;
diff --git a/src/test-base-compositor-surface.c b/src/test-base-compositor-surface.c
index ff84b10af..ff84b10af 100755..100644
--- a/src/test-base-compositor-surface.c
+++ b/src/test-base-compositor-surface.c
diff --git a/src/test-compositor-surface-private.h b/src/test-compositor-surface-private.h
index 491f241ba..491f241ba 100755..100644
--- a/src/test-compositor-surface-private.h
+++ b/src/test-compositor-surface-private.h
diff --git a/src/test-compositor-surface.c b/src/test-compositor-surface.c
index ddee06f3e..1cc5f6921 100755..100644
--- a/src/test-compositor-surface.c
+++ b/src/test-compositor-surface.c
@@ -145,6 +145,8 @@ test_compositor_surface_stroke (void *_surface,
const cairo_clip_t *clip)
{
test_compositor_surface_t *surface = _surface;
+ if (antialias == CAIRO_ANTIALIAS_DEFAULT)
+ antialias = CAIRO_ANTIALIAS_BEST;
return _cairo_compositor_stroke (surface->base.compositor,
_surface, op, source,
path, style, ctm, ctm_inverse,
@@ -163,6 +165,8 @@ test_compositor_surface_fill (void *_surface,
const cairo_clip_t *clip)
{
test_compositor_surface_t *surface = _surface;
+ if (antialias == CAIRO_ANTIALIAS_DEFAULT)
+ antialias = CAIRO_ANTIALIAS_BEST;
return _cairo_compositor_fill (surface->base.compositor,
_surface, op, source,
path, fill_rule, tolerance, antialias,
diff --git a/src/test-compositor-surface.h b/src/test-compositor-surface.h
index 8d8af2d54..8d8af2d54 100755..100644
--- a/src/test-compositor-surface.h
+++ b/src/test-compositor-surface.h
diff --git a/src/test-null-compositor-surface.c b/src/test-null-compositor-surface.c
index 4fdaac4a3..395a5f4a6 100755..100644
--- a/src/test-null-compositor-surface.c
+++ b/src/test-null-compositor-surface.c
@@ -419,7 +419,7 @@ no_traps_compositor_get (void)
compositor.check_composite = check_composite;
compositor.composite = composite;
compositor.lerp = lerp;
- //FIXME:
+ // FIXME:
compositor.lerp_color_glyph = lerp;
//compositor.check_composite_boxes = check_composite_boxes;
compositor.composite_boxes = composite_boxes;
diff --git a/src/test-null-compositor-surface.h b/src/test-null-compositor-surface.h
index 52d864b28..52d864b28 100755..100644
--- a/src/test-null-compositor-surface.h
+++ b/src/test-null-compositor-surface.h
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index 0a7c79b37..0a7c79b37 100755..100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
diff --git a/src/test-paginated-surface.h b/src/test-paginated-surface.h
index 2bd98aa5e..2bd98aa5e 100755..100644
--- a/src/test-paginated-surface.h
+++ b/src/test-paginated-surface.h
diff --git a/src/win32/cairo-win32-debug.c b/src/win32/cairo-win32-debug.c
index ff7aeaf1f..ff7aeaf1f 100755..100644
--- a/src/win32/cairo-win32-debug.c
+++ b/src/win32/cairo-win32-debug.c
diff --git a/src/win32/cairo-win32-device.c b/src/win32/cairo-win32-device.c
index 741e49e33..741e49e33 100755..100644
--- a/src/win32/cairo-win32-device.c
+++ b/src/win32/cairo-win32-device.c
diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c
index ccd285d7d..965f2c45d 100755..100644
--- a/src/win32/cairo-win32-display-surface.c
+++ b/src/win32/cairo-win32-display-surface.c
@@ -415,7 +415,8 @@ _cairo_win32_display_surface_finish (void *abstract_surface)
{
cairo_win32_display_surface_t *surface = abstract_surface;
- if (surface->image) {
+ if (surface->image && to_image_surface(surface->image)->parent) {
+ assert (to_image_surface(surface->image)->parent == &surface->win32.base);
/* Unhook ourselves first to avoid the double-unref from the image */
to_image_surface(surface->image)->parent = NULL;
cairo_surface_finish (surface->image);
@@ -429,6 +430,8 @@ _cairo_win32_display_surface_finish (void *abstract_surface)
DeleteDC (surface->win32.dc);
}
+ _cairo_win32_display_surface_discard_fallback (surface);
+
if (surface->initial_clip_rgn)
DeleteObject (surface->initial_clip_rgn);
@@ -452,17 +455,17 @@ _cairo_win32_display_surface_map_to_image (void *abstract_sur
surface->fallback =
_cairo_win32_display_surface_create_for_dc (surface->win32.dc,
surface->win32.format,
- surface->win32.extents.width,
- surface->win32.extents.height);
+ surface->win32.extents.x + surface->win32.extents.width,
+ surface->win32.extents.y + surface->win32.extents.height);
if (unlikely (status = surface->fallback->status))
goto err;
if (!BitBlt (to_win32_surface(surface->fallback)->dc,
- 0, 0,
+ surface->win32.extents.x, surface->win32.extents.y,
surface->win32.extents.width,
surface->win32.extents.height,
surface->win32.dc,
- 0, 0,
+ surface->win32.extents.x, surface->win32.extents.y,
SRCCOPY)) {
status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
goto err;
@@ -758,6 +761,7 @@ _cairo_win32_display_surface_discard_fallback (cairo_win32_display_surface_t *su
TRACE ((stderr, "%s (surface=%d)\n",
__FUNCTION__, surface->win32.base.unique_id));
+ cairo_surface_finish (surface->fallback);
cairo_surface_destroy (surface->fallback);
surface->fallback = NULL;
}
diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c
index a65d81b1a..1599b0751 100755..100644
--- a/src/win32/cairo-win32-font.c
+++ b/src/win32/cairo-win32-font.c
@@ -157,10 +157,6 @@ static cairo_status_t
_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph);
-static void
-_cairo_win32_font_face_destroy (void *abstract_face);
-
-
#define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.))
static HDC
@@ -1847,49 +1843,6 @@ struct _cairo_win32_font_face {
HFONT hfont;
};
-/* implement the platform-specific interface */
-
-static cairo_bool_t
-_is_scale (const cairo_matrix_t *matrix, double scale)
-{
- return matrix->xx == scale && matrix->yy == scale &&
- matrix->xy == 0. && matrix->yx == 0. &&
- matrix->x0 == 0. && matrix->y0 == 0.;
-}
-
-static cairo_status_t
-_cairo_win32_font_face_scaled_font_create (void *abstract_face,
- const cairo_matrix_t *font_matrix,
- const cairo_matrix_t *ctm,
- const cairo_font_options_t *options,
- cairo_scaled_font_t **font)
-{
- HFONT hfont = NULL;
-
- cairo_win32_font_face_t *font_face = abstract_face;
-
- if (font_face->hfont) {
- /* Check whether it's OK to go ahead and use the font-face's HFONT. */
- if (_is_scale (ctm, 1.) &&
- _is_scale (font_matrix, -font_face->logfont.lfHeight)) {
- hfont = font_face->hfont;
- }
- }
-
- return _win32_scaled_font_create (&font_face->logfont,
- hfont,
- &font_face->base,
- font_matrix, ctm, options,
- font);
-}
-
-const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
- CAIRO_FONT_TYPE_WIN32,
- _cairo_win32_font_face_create_for_toy,
- _cairo_win32_font_face_destroy,
- _cairo_win32_font_face_scaled_font_create
-};
-
/* We maintain a hash table from LOGFONT,HFONT => #cairo_font_face_t.
* The primary purpose of this mapping is to provide unique
* #cairo_font_face_t values so that our cache and mapping from
@@ -1950,7 +1903,7 @@ _cairo_win32_font_face_hash_table_unlock (void)
CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex);
}
-static void
+static cairo_bool_t
_cairo_win32_font_face_destroy (void *abstract_face)
{
cairo_win32_font_face_t *font_face = abstract_face;
@@ -1960,10 +1913,10 @@ _cairo_win32_font_face_destroy (void *abstract_face)
/* All created objects must have been mapped in the hash table. */
assert (hash_table != NULL);
- if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->base.ref_count)) {
+ if (! _cairo_reference_count_dec_and_test (&font_face->base.ref_count)) {
/* somebody recreated the font whilst we waited for the lock */
_cairo_win32_font_face_hash_table_unlock ();
- return;
+ return FALSE;
}
/* Font faces in SUCCESS status are guaranteed to be in the
@@ -1975,6 +1928,7 @@ _cairo_win32_font_face_destroy (void *abstract_face)
_cairo_hash_table_remove (hash_table, &font_face->base.hash_entry);
_cairo_win32_font_face_hash_table_unlock ();
+ return TRUE;
}
static void
@@ -2015,6 +1969,49 @@ _cairo_win32_font_face_keys_equal (const void *key_a,
return FALSE;
}
+/* implement the platform-specific interface */
+
+static cairo_bool_t
+_is_scale (const cairo_matrix_t *matrix, double scale)
+{
+ return matrix->xx == scale && matrix->yy == scale &&
+ matrix->xy == 0. && matrix->yx == 0. &&
+ matrix->x0 == 0. && matrix->y0 == 0.;
+}
+
+static cairo_status_t
+_cairo_win32_font_face_scaled_font_create (void *abstract_face,
+ const cairo_matrix_t *font_matrix,
+ const cairo_matrix_t *ctm,
+ const cairo_font_options_t *options,
+ cairo_scaled_font_t **font)
+{
+ HFONT hfont = NULL;
+
+ cairo_win32_font_face_t *font_face = abstract_face;
+
+ if (font_face->hfont) {
+ /* Check whether it's OK to go ahead and use the font-face's HFONT. */
+ if (_is_scale (ctm, 1.) &&
+ _is_scale (font_matrix, -font_face->logfont.lfHeight)) {
+ hfont = font_face->hfont;
+ }
+ }
+
+ return _win32_scaled_font_create (&font_face->logfont,
+ hfont,
+ &font_face->base,
+ font_matrix, ctm, options,
+ font);
+}
+
+const cairo_font_face_backend_t _cairo_win32_font_face_backend = {
+ CAIRO_FONT_TYPE_WIN32,
+ _cairo_win32_font_face_create_for_toy,
+ _cairo_win32_font_face_destroy,
+ _cairo_win32_font_face_scaled_font_create
+};
+
/**
* cairo_win32_font_face_create_for_logfontw_hfont:
* @logfont: A #LOGFONTW structure specifying the font to use.
diff --git a/src/win32/cairo-win32-gdi-compositor.c b/src/win32/cairo-win32-gdi-compositor.c
index c70b0f90a..073e889ab 100755..100644
--- a/src/win32/cairo-win32-gdi-compositor.c
+++ b/src/win32/cairo-win32-gdi-compositor.c
@@ -151,10 +151,11 @@ static cairo_bool_t upload_box (cairo_box_t *box, void *closure)
int y = _cairo_fixed_integer_part (box->p1.y);
int width = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
+ int src_height = -cb->bi.bmiHeader.biHeight;
TRACE ((stderr, "%s\n", __FUNCTION__));
return StretchDIBits (cb->dst, x, y + height - 1, width, -height,
- x + cb->tx, height - (y + cb->ty - 1),
+ x + cb->tx, src_height - (y + cb->ty - 1),
width, -height,
cb->data, &cb->bi,
DIB_RGB_COLORS, SRCCOPY);
diff --git a/src/win32/cairo-win32-printing-surface.c b/src/win32/cairo-win32-printing-surface.c
index be91445cf..6005cb53d 100755..100644
--- a/src/win32/cairo-win32-printing-surface.c
+++ b/src/win32/cairo-win32-printing-surface.c
@@ -726,6 +726,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_printing_surface_
/* _cairo_pattern_set_matrix guarantees invertibility */
assert (status == CAIRO_STATUS_SUCCESS);
+ cairo_matrix_multiply (&m, &m, &surface->ctm);
cairo_matrix_multiply (&m, &m, &surface->gdi_ctm);
SaveDC (surface->win32.dc);
_cairo_matrix_to_win32_xform (&m, &xform);
@@ -1578,14 +1579,18 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
* CAIRO_INT_STATUS_UNSUPPORTED and a fallback image will be
* used.
*/
+ _cairo_scaled_font_freeze_cache (scaled_font);
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
&scaled_glyph);
if (status)
- return status;
+ break;
}
+ _cairo_scaled_font_thaw_cache (scaled_font);
+ if (status)
+ return status;
return _cairo_win32_printing_surface_analyze_operation (surface, op, source);
}
@@ -1623,6 +1628,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
old_has_ctm = surface->has_ctm;
surface->has_ctm = TRUE;
surface->path_empty = TRUE;
+ _cairo_scaled_font_freeze_cache (scaled_font);
BeginPath (surface->win32.dc);
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_glyph_lookup (scaled_font,
@@ -1636,6 +1642,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
status = _cairo_win32_printing_surface_emit_path (surface, scaled_glyph->path);
}
EndPath (surface->win32.dc);
+ _cairo_scaled_font_thaw_cache (scaled_font);
surface->ctm = old_ctm;
surface->has_ctm = old_has_ctm;
if (status == CAIRO_STATUS_SUCCESS && surface->path_empty == FALSE) {
diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h
index b6c24311a..b6c24311a 100755..100644
--- a/src/win32/cairo-win32-private.h
+++ b/src/win32/cairo-win32-private.h
diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c
index 7cd46fc60..e6862bd10 100755..100644
--- a/src/win32/cairo-win32-surface.c
+++ b/src/win32/cairo-win32-surface.c
@@ -172,6 +172,21 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
}
/**
+ * _cairo_surface_is_win32:
+ * @surface: a #cairo_surface_t
+ *
+ * Checks if a surface is an #cairo_win32_surface_t
+ *
+ * Return value: %TRUE if the surface is an win32 surface
+ **/
+static inline cairo_bool_t
+_cairo_surface_is_win32 (const cairo_surface_t *surface)
+{
+ /* _cairo_surface_nil sets a NULL backend so be safe */
+ return surface->backend && surface->backend->type == CAIRO_SURFACE_TYPE_WIN32;
+}
+
+/**
* cairo_win32_surface_get_image:
* @surface: a #cairo_surface_t
*
@@ -187,8 +202,10 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
cairo_surface_t *
cairo_win32_surface_get_image (cairo_surface_t *surface)
{
- if (surface->backend->type != CAIRO_SURFACE_TYPE_WIN32)
- return NULL;
+
+ if (! _cairo_surface_is_win32 (surface)) {
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
+ }
GdiFlush();
return to_win32_display_surface(surface)->image;
diff --git a/src/win32/cairo-win32-system.c b/src/win32/cairo-win32-system.c
index 878553009..878553009 100755..100644
--- a/src/win32/cairo-win32-system.c
+++ b/src/win32/cairo-win32-system.c